[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
This commit is contained in:
@@ -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,9 +306,11 @@ public final class Magnifier {
|
||||
*/
|
||||
public void dismiss() {
|
||||
if (mWindow != null) {
|
||||
synchronized (mLock) {
|
||||
mWindow.destroy();
|
||||
mWindow = null;
|
||||
synchronized (mDestroyLock) {
|
||||
synchronized (mLock) {
|
||||
mWindow.destroy();
|
||||
mWindow = null;
|
||||
}
|
||||
}
|
||||
mPrevShowSourceCoords.x = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
|
||||
mPrevShowSourceCoords.y = 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;
|
||||
|
||||
Reference in New Issue
Block a user