summaryrefslogtreecommitdiff
path: root/core/java/android/widget
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2018-02-23 12:50:37 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2018-02-23 12:50:37 +0000
commit24257520267701f36e67754677bdae9472b05428 (patch)
tree51ce142f5ff74476afbcaa33836d62d873d79e46 /core/java/android/widget
parentadd2d38cfc243f0faecb6a6d73addd22eeffab17 (diff)
parent39a71338939f419ddf7faaacb73f82371cb7db16 (diff)
Merge "[Magnifier-25] Fix race condition after #dismiss"
Diffstat (limited to 'core/java/android/widget')
-rw-r--r--core/java/android/widget/Magnifier.java40
1 files changed, 26 insertions, 14 deletions
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 64279655f799..eb2af60a2170 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -89,6 +89,9 @@ public final class Magnifier {
NONEXISTENT_PREVIOUS_CONFIG_VALUE, NONEXISTENT_PREVIOUS_CONFIG_VALUE);
// Rectangle defining the view surface area we pixel copy content from.
private final Rect mPixelCopyRequestRect = new Rect();
+ // 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();
/**
* Initializes a magnifier.
@@ -170,9 +173,12 @@ public final class Magnifier {
if (xPosInView != mPrevPosInView.x || yPosInView != mPrevPosInView.y) {
if (mWindow == null) {
- mWindow = new InternalPopupWindow(mView.getContext(), mView.getDisplay(),
- getValidViewSurface(), mWindowWidth, mWindowHeight, mWindowElevation,
- Handler.getMain() /* draw the magnifier on the UI thread */, mCallback);
+ synchronized (mLock) {
+ mWindow = new InternalPopupWindow(mView.getContext(), mView.getDisplay(),
+ getValidViewSurface(), mWindowWidth, mWindowHeight, mWindowElevation,
+ Handler.getMain() /* draw the magnifier on the UI thread */, mLock,
+ mCallback);
+ }
}
performPixelCopy(startX, startY, true /* update window position */);
mPrevPosInView.x = xPosInView;
@@ -200,8 +206,10 @@ public final class Magnifier {
*/
public void dismiss() {
if (mWindow != null) {
- mWindow.destroy();
- mWindow = null;
+ synchronized (mLock) {
+ mWindow.destroy();
+ mWindow = null;
+ }
}
}
@@ -281,19 +289,22 @@ public final class Magnifier {
clampedStartYInSurface + mBitmapHeight);
final int windowCoordsX = mWindowCoords.x;
final int windowCoordsY = mWindowCoords.y;
+ final InternalPopupWindow currentWindowInstance = mWindow;
final Bitmap bitmap =
Bitmap.createBitmap(mBitmapWidth, mBitmapHeight, Bitmap.Config.ARGB_8888);
PixelCopy.request(surface, mPixelCopyRequestRect, bitmap,
result -> {
- synchronized (mWindow.mLock) {
- if (mWindow != null) {
- if (updateWindowPosition) {
- // TODO: pull the position update outside #performPixelCopy
- mWindow.setContentPositionForNextDraw(windowCoordsX, windowCoordsY);
- }
- mWindow.updateContent(bitmap);
+ synchronized (mLock) {
+ if (mWindow != currentWindowInstance) {
+ // The magnifier was dismissed (and maybe shown again) in the meantime.
+ return;
+ }
+ if (updateWindowPosition) {
+ // TODO: pull the position update outside #performPixelCopy
+ mWindow.setContentPositionForNextDraw(windowCoordsX, windowCoordsY);
}
+ mWindow.updateContent(bitmap);
}
},
sPixelCopyHandlerThread.getThreadHandler());
@@ -337,7 +348,7 @@ public final class Magnifier {
// Members below describe the state of the magnifier. Reads/writes to them
// have to be synchronized between the UI thread and the thread that handles
// the pixel copy results. This is the purpose of mLock.
- private final Object mLock = new Object();
+ private final Object mLock;
// Whether a magnifier frame draw is currently pending in the UI thread queue.
private boolean mFrameDrawScheduled;
// The content bitmap.
@@ -353,8 +364,9 @@ public final class Magnifier {
InternalPopupWindow(final Context context, final Display display,
final Surface parentSurface,
final int width, final int height, final float elevation,
- final Handler handler, final Callback callback) {
+ final Handler handler, final Object lock, final Callback callback) {
mDisplay = display;
+ mLock = lock;
mCallback = callback;
mContentWidth = width;