diff options
| author | 2018-04-02 19:53:48 -0700 | |
|---|---|---|
| committer | 2018-04-02 19:53:48 -0700 | |
| commit | da02fac9fea2a3ea5730d6595fb246c48eb3462b (patch) | |
| tree | 0a6b10c456e64e14b710b9147305681ff1872f9e | |
| parent | b0765db5b8e6ac8682b6e795810dc2d129352e26 (diff) | |
| parent | 285797a45a83b20ccdf75a4ca7a762a285e54561 (diff) | |
Merge "[Magnifier-38] Avoid deadlock causing ANR" into pi-dev
am: 285797a45a
Change-Id: I81474f04a8d33d2cf063aa0d89b7abca255d3864
| -rw-r--r-- | core/java/android/widget/Magnifier.java | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java index c1c5d9d688ed..5eb66999b296 100644 --- a/core/java/android/widget/Magnifier.java +++ b/core/java/android/widget/Magnifier.java @@ -393,6 +393,12 @@ public final class Magnifier { private int mWindowPositionY; private boolean mPendingWindowPositionUpdate; + // The lock used to synchronize the UI and render threads when a #destroy + // 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(); + InternalPopupWindow(final Context context, final Display display, final Surface parentSurface, final int width, final int height, final float elevation, final float cornerRadius, @@ -517,9 +523,11 @@ public final class Magnifier { * Destroys this instance. */ public void destroy() { + synchronized (mDestroyLock) { + mSurface.destroy(); + } synchronized (mLock) { mRenderer.destroy(); - mSurface.destroy(); mSurfaceControl.destroy(); mSurfaceSession.kill(); mBitmapRenderNode.destroy(); @@ -567,21 +575,23 @@ public final class Magnifier { final int pendingY = mWindowPositionY; callback = frame -> { - synchronized (mLock) { + synchronized (mDestroyLock) { if (!mSurface.isValid()) { return; } - mRenderer.setLightCenter(mDisplay, pendingX, pendingY); - // Show or move the window at the content draw frame. - SurfaceControl.openTransaction(); - mSurfaceControl.deferTransactionUntil(mSurface, frame); - if (updateWindowPosition) { - mSurfaceControl.setPosition(pendingX, pendingY); - } - if (firstDraw) { - mSurfaceControl.show(); + synchronized (mLock) { + mRenderer.setLightCenter(mDisplay, pendingX, pendingY); + // Show or move the window at the content draw frame. + SurfaceControl.openTransaction(); + mSurfaceControl.deferTransactionUntil(mSurface, frame); + if (updateWindowPosition) { + mSurfaceControl.setPosition(pendingX, pendingY); + } + if (firstDraw) { + mSurfaceControl.show(); + } + SurfaceControl.closeTransaction(); } - SurfaceControl.closeTransaction(); } }; } else { |