Merge "[Magnifier-87] Fix deadlock causing ANR" into qt-dev
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 1719015..ccafa64 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -277,7 +277,7 @@
                             mWindowElevation, mWindowCornerRadius,
                             mOverlay != null ? mOverlay : new ColorDrawable(Color.TRANSPARENT),
                             Handler.getMain() /* draw the magnifier on the UI thread */, mLock,
-                            mDestroyLock, mCallback);
+                            mCallback);
                 }
             }
             performPixelCopy(startX, startY, true /* update window position */);
@@ -306,11 +306,9 @@
      */
     public void dismiss() {
         if (mWindow != null) {
-            synchronized (mDestroyLock) {
-                synchronized (mLock) {
-                    mWindow.destroy();
-                    mWindow = null;
-                }
+            synchronized (mLock) {
+                mWindow.destroy();
+                mWindow = null;
             }
             mPrevShowSourceCoords.x = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
             mPrevShowSourceCoords.y = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
@@ -835,24 +833,16 @@
         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;
-
         // The current content of the magnifier. It is mBitmap + mOverlay, only used for testing.
         private Bitmap mCurrentContent;
 
         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 Object destroyLock,
-                final Callback callback) {
+                final Handler handler, final Object lock, final Callback callback) {
             mDisplay = display;
             mOverlay = overlay;
             mLock = lock;
-            mDestroyLock = destroyLock;
             mCallback = callback;
 
             mContentWidth = width;
@@ -1039,20 +1029,17 @@
         }
 
         /**
-         * Destroys this instance.
+         * Destroys this instance. The method has to be called in a context holding {@link #mLock}.
          */
         public void destroy() {
-            synchronized (mDestroyLock) {
-                mSurface.destroy();
-            }
-            synchronized (mLock) {
-                mRenderer.destroy();
-                mSurfaceControl.remove();
-                mSurfaceSession.kill();
-                mHandler.removeCallbacks(mMagnifierUpdater);
-                if (mBitmap != null) {
-                    mBitmap.recycle();
-                }
+            // Destroy the renderer. This will not proceed until pending frame callbacks complete.
+            mRenderer.destroy();
+            mSurface.destroy();
+            mSurfaceControl.remove();
+            mSurfaceSession.kill();
+            mHandler.removeCallbacks(mMagnifierUpdater);
+            if (mBitmap != null) {
+                mBitmap.recycle();
             }
         }
 
@@ -1090,24 +1077,20 @@
                     final int pendingY = mWindowPositionY;
 
                     callback = frame -> {
-                        synchronized (mDestroyLock) {
-                            if (!mSurface.isValid()) {
-                                return;
-                            }
-                            synchronized (mLock) {
-                                // 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.setLayer(SURFACE_Z);
-                                    mSurfaceControl.show();
-                                }
-                                SurfaceControl.closeTransaction();
-                            }
+                        if (!mSurface.isValid()) {
+                            return;
                         }
+                        // 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.setLayer(SURFACE_Z);
+                            mSurfaceControl.show();
+                        }
+                        SurfaceControl.closeTransaction();
                     };
                     mRenderer.setLightCenter(mDisplay, pendingX, pendingY);
                 } else {