Glide: Android O hardware crash on transition.

Created on 30 Aug 2017  路  14Comments  路  Source: bumptech/glide


Glide Version:
Last snapshot.

Integration libraries:


Device/Android Version:
Nexus 6P. Pixel XL. Certainly others.


Issue details / Repro steps / Use case background:

I guess this is more or less unavoidable as hard to detect for Glide. I don't even know why it happens.

Question is about https://github.com/bumptech/glide/commit/bb5c391a8b418f8ac2296d4d2c2ca24110e83984

What does this really do and what are the impacts if I disable hardware on all pictures that can be used as transition (A lot)


Glide load line / GlideModule (if any) / list Adapter code (if any):

Glide.with...


Layout XML:

<FrameLayout xmlns:android="...


Stack trace / LogCat:

Fatal Exception: java.lang.IllegalStateException: Software rendering doesn't support hardware bitmaps
       at android.graphics.BaseCanvas.throwIfHwBitmapInSwMode(BaseCanvas.java:532)
       at android.graphics.BaseCanvas.throwIfCannotDraw(BaseCanvas.java:62)
       at android.graphics.BaseCanvas.drawBitmap(BaseCanvas.java:120)
       at android.graphics.Canvas.drawBitmap(Canvas.java:1434)
       at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:529)
       at android.support.v4.app.SharedElementCallback.createDrawableBitmap(SharedElementCallback.java:234)
       at android.support.v4.app.ActivityCompat$SharedElementCallback21Impl.android.support.v4.app.SharedElementCallback.onCaptureSharedElementSnapshot(ActivityCompat.java:1173)
       at android.app.ActivityTransitionCoordinator.captureSharedElementState(ActivityTransitionCoordinator.java:810)
       at android.app.ActivityTransitionCoordinator.captureSharedElementState(ActivityTransitionCoordinator.java:733)
       at android.app.ExitTransitionCoordinator.sharedElementTransitionComplete(ExitTransitionCoordinator.java:405)
       at android.app.ExitTransitionCoordinator$9.onTransitionEnd(ExitTransitionCoordinator.java:362)
       at android.transition.Transition.end(Transition.java:1926)
       at android.transition.TransitionSet$TransitionSetListener.onTransitionEnd(TransitionSet.java:369)
       at android.transition.Transition.end(Transition.java:1926)
       at android.transition.TransitionSet$TransitionSetListener.onTransitionEnd(TransitionSet.java:369)
       at android.transition.Transition.end(Transition.java:1926)
       at android.transition.Transition.runAnimators(Transition.java:883)
       at android.transition.TransitionSet.runAnimators(TransitionSet.java:433)
       at android.transition.TransitionSet.runAnimators(TransitionSet.java:433)
       at android.transition.Transition.playTransition(Transition.java:1780)
       at android.transition.TransitionManager$MultiListener.onPreDraw(TransitionManager.java:315)
       at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:977)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2337)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1386)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6733)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
       at android.view.Choreographer.doCallbacks(Choreographer.java:723)
       at android.view.Choreographer.doFrame(Choreographer.java:658)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
       at android.os.Handler.handleCallback(Handler.java:789)
       at android.os.Handler.dispatchMessage(Handler.java:98)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6541)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
non-library

Most helpful comment

@tibbi http://bumptech.github.io/glide/javadocs/431/com/bumptech/glide/request/RequestOptions.html#disallowHardwareConfig--

Sorry we're still figuring out what the right default should be here.

All 14 comments

Yeah there's a request on the framework side to fix this, but it hasn't gone in yet and I don't know when it will. The workaround is to disable hardware bitmaps for these transitions as you've discovered.

The consequence is primarily increased memory usage with ARGB_8888. HARDWARE retains only a single copy of the pixels in memory, other Bitmap types end up with at least two. It's not a huge deal though, ARGB_8888 didn't get any worse in O, so you're just missing out on an opportunity to lower ram usage over previous versions, you're not regressing anything.

Ok so no cache change that would be impacted good to know thanks for confirmation.

Do you have any details on why it does that only in some very rare case that I can't reproduce? Maybe I can only disable it for those cases and not every-time there's a transition.

Glide only uses hardware bitmaps in some circumstances. It's possible that sometimes the load produces ARGB_8888 bitmaps anyway. hardware bitmaps can't be drawn to a Canvas either, so Glide will only use them for either when no transformation is applied or when scale only transformations (FitCenter, CenterInside etc) are applied that can be performed by the Downsampler.

If you're passing in a hardware Bitmap each time and only seeing this exception sometimes, then I'm not sure. I'd guess there's some fork in the transition library but unfortunately I'm not very familiar with it.

For future reference, the internal bug is b/64851247.

Well at first I did not change anything and have setDefaultRequestOptions(new RequestOptions().format(DecodeFormat.PREFER_RGB_565))

And yes I can't reproduce that crash on emulators. And it's only a rare report in crashlytics when I know that there's quite a few users on O as others problems where reported in the beta.

I'll disable hardware for all calls for now as default for release and will report if I get more information.

Internal bug is closed, I believe this will be fixed in OMR1, but don't hold me to it.

I can confirm the same issue with a Nexus 5x running Android 8.0.0. Glide version 4.3.1. I get the
java.lang.IllegalStateException: Software rendering doesn't support hardware bitmaps Exception.

The problem always happens when I load a full screen drawable into an image view. I tried also setting the layer type programatically with binding.pro_image.setLayerType(View.LAYER_TYPE_SOFTWARE, null) with no visible resolution to the issue.

Any ideas how to solve the problem or is there an usable workaround?

GlideApp.with(this)
        .asBitmap()
        .format(DecodeFormat.PREFER_RGB_565)
        .load(R.drawable.app_default_startscreen)
        .into(binding.pro_image);

The layout file looks as following:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="viewModel"
            type="yyy.WelcomeViewModel" />
    </data>

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@color/white"
        android:orientation="vertical"
        android:layerType="software">

        <android.support.v7.widget.AppCompatImageView
            android:id="@+id/pro_image"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:scaleType="fitEnd"
            android:layout_alignParentRight="true"
            android:layout_alignParentBottom="true"
            android:layerType="software"/>
    </RelativeLayout>
</layout>

Umm, I could use some help too. Im pasting the bitmap obtained from Glide to a canvas, and it crashes with throwIfHwBitmapInSwMode. If I use DecodeFormat.PREFER_ARGB_8888_DISALLOW_HARDWARE, it works fine. It is deprecated tho, so I'd like to use the proper way of setting ALLOW_HARDWARE_CONFIG to false. I couldnt figure out how to do it and for some reason it isn't mentioned on the wiki at all. Can I get some code sample which does it? Thanks

@tibbi http://bumptech.github.io/glide/javadocs/431/com/bumptech/glide/request/RequestOptions.html#disallowHardwareConfig--

Sorry we're still figuring out what the right default should be here.

ah, shame I havent tried that. It works fine, thanks.

@sjudd : Is it a good solution to disallow hardware config directly into my Glide configuration (so global for all the App):

@Override
    public void applyOptions(Context context, GlideBuilder builder) {      
        RequestOptions requestOptions = new RequestOptions();
        requestOptions.format(DecodeFormat.PREFER_ARGB_8888);
        requestOptions.disallowHardwareConfig();
        builder.setDefaultRequestOptions(requestOptions);
    }

Or I must do that on just a specific Glide loading?

Thank you very much!

Hey @sjudd,
We also had this exception on Android O with glide 4.3.1, but we can't reproduce it (report from fabric).
Is it fixed in the newest version - 4.7.1?

@wingu-wiktor You can try disallowHardware as linked above. Right now hardware bitmaps are default off.

@sjudd : Is it a good solution to disallow hardware config directly into my Glide configuration (so global for all the App):

@Override
    public void applyOptions(Context context, GlideBuilder builder) {      
        RequestOptions requestOptions = new RequestOptions();
        requestOptions.format(DecodeFormat.PREFER_ARGB_8888);
        requestOptions.disallowHardwareConfig();
        builder.setDefaultRequestOptions(requestOptions);
    }

Or I must do that on just a specific Glide loading?

Thank you very much!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

technoir42 picture technoir42  路  3Comments

PatrickMA picture PatrickMA  路  3Comments

Ncit picture Ncit  路  3Comments

billy2271 picture billy2271  路  3Comments

mttmllns picture mttmllns  路  3Comments