Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c8beb5c0 authored by Bin Chen's avatar Bin Chen Committed by Mihai Popa
Browse files

[Magnifier-86] Fix deadlock causing ANR

"main" prio=5 tid=1 Blocked
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x74aeca00 self=0x7021814c00
  | sysTid=27953 nice=-10 cgrp=default sched=0/0 handle=0x70a85ff548
  | state=S schedstat=( 31382082536 9164116362 28130 ) utm=2661 stm=477 core=0 HZ=100
  | stack=0x7ff7a52000-0x7ff7a54000 stackSize=8MB
  | held mutexes=
  at android.widget.Magnifier$InternalPopupWindow.destroy(Magnifier.java:607)
  - waiting to lock <0x0ef5c351> (a java.lang.Object) held by thread 13
  at android.widget.Magnifier.dismiss(Magnifier.java:191)
  - locked <0x01cd07b6> (a java.lang.Object)

 "hwuiTask1" prio=5 tid=13 Blocked
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x12f815d8 self=0x70000e7800
  | sysTid=28075 nice=-2 cgrp=default sched=0/0 handle=0x70046ba4f0
  | state=S schedstat=( 138800095 85604746 532 ) utm=10 stm=3 core=1 HZ=100
  | stack=0x70045bf000-0x70045c1000 stackSize=1009KB
  | held mutexes=
  at android.widget.Magnifier$InternalPopupWindow.lambda$doDraw$0(Magnifier.java:663)
  - waiting to lock <0x01cd07b6> (a java.lang.Object) held by thread 1
  - locked <0x0ef5c351> (a java.lang.Object)
  at android.widget.-$$Lambda$Magnifier$InternalPopupWindow$vZThyvjDQhg2J1GAeOWCNqy2iiw.onFrameDraw(lambda:-1)

Bug: 133396461
Test: atest CtsWidgetTestCases:android.widget.cts.MagnifierTest
Change-Id: Idf0373ab0d5033d56da0f6f45d7d953f7e796813
Merged-In: Idf0373ab0d5033d56da0f6f45d7d953f7e796813
parent bca73ac0
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -136,6 +136,8 @@ public final class Magnifier {
    // Lock to synchronize between the UI thread and the thread that handles pixel copy results.
    // Only sync mWindow writes from UI thread with mWindow reads from sPixelCopyHandlerThread.
    private final Object mLock = new Object();
    // The lock used to synchronize the UI and render threads when a #dismiss is performed.
    private final Object mDestroyLock = new Object();

    /**
     * Initializes a magnifier.
@@ -275,7 +277,7 @@ public final class Magnifier {
                            mWindowElevation, mWindowCornerRadius,
                            mOverlay != null ? mOverlay : new ColorDrawable(Color.TRANSPARENT),
                            Handler.getMain() /* draw the magnifier on the UI thread */, mLock,
                            mCallback);
                            mDestroyLock, mCallback);
                }
            }
            performPixelCopy(startX, startY, true /* update window position */);
@@ -304,10 +306,12 @@ public final class Magnifier {
     */
    public void dismiss() {
        if (mWindow != null) {
            synchronized (mDestroyLock) {
                synchronized (mLock) {
                    mWindow.destroy();
                    mWindow = null;
                }
            }
            mPrevShowSourceCoords.x = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
            mPrevShowSourceCoords.y = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
            mPrevShowWindowCoords.x = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
@@ -819,7 +823,7 @@ public final class Magnifier {
        // is performed on the UI thread and a frame callback on the render thread.
        // When both mLock and mDestroyLock need to be held at the same time,
        // mDestroyLock should be acquired before mLock in order to avoid deadlocks.
        private final Object mDestroyLock = new Object();
        private final Object mDestroyLock;

        // The current content of the magnifier. It is mBitmap + mOverlay, only used for testing.
        private Bitmap mCurrentContent;
@@ -827,10 +831,12 @@ public final class Magnifier {
        InternalPopupWindow(final Context context, final Display display,
                final SurfaceControl parentSurfaceControl, final int width, final int height,
                final float elevation, final float cornerRadius, final Drawable overlay,
                final Handler handler, final Object lock, final Callback callback) {
                final Handler handler, final Object lock, final Object destroyLock,
                final Callback callback) {
            mDisplay = display;
            mOverlay = overlay;
            mLock = lock;
            mDestroyLock = destroyLock;
            mCallback = callback;

            mContentWidth = width;