Perform magnification viewport drawing outside of WM global lock.
Attempts to fix the deadlock caused by holding onto the WM global lock
too long.
Bug: 276845499
Test: Use magnification, observe no change in behavior
Test: Existing magnification-related tests:
atest frameworks/base/services/tests/servicestests/ \
src/com/android/server/accessibility/magnification
atest frameworks/base/packages/SystemUI/tests/ \
src/com/android/systemui/accessibility
atest cts/tests/accessibilityservice/ \
src/android/accessibilityservice/cts
Change-Id: Id828744c8c5bcb4bdb3be9a11810338614b84b2e
This commit is contained in:
@@ -1280,45 +1280,53 @@ final class AccessibilityController {
|
||||
}
|
||||
|
||||
void drawIfNeeded(SurfaceControl.Transaction t) {
|
||||
// Drawing variables (alpha, dirty rect, and bounds) access is synchronized
|
||||
// using WindowManagerGlobalLock. Grab copies of these values before
|
||||
// drawing on the canvas so that drawing can be performed outside of the lock.
|
||||
int alpha;
|
||||
Rect drawingRect = null;
|
||||
Region drawingBounds = null;
|
||||
synchronized (mService.mGlobalLock) {
|
||||
if (!mInvalidated) {
|
||||
return;
|
||||
}
|
||||
mInvalidated = false;
|
||||
if (mAlpha > 0) {
|
||||
Canvas canvas = null;
|
||||
try {
|
||||
// Empty dirty rectangle means unspecified.
|
||||
if (mDirtyRect.isEmpty()) {
|
||||
mBounds.getBounds(mDirtyRect);
|
||||
}
|
||||
mDirtyRect.inset(-mHalfBorderWidth, -mHalfBorderWidth);
|
||||
canvas = mSurface.lockCanvas(mDirtyRect);
|
||||
if (DEBUG_VIEWPORT_WINDOW) {
|
||||
Slog.i(LOG_TAG, "Dirty rect: " + mDirtyRect);
|
||||
}
|
||||
} catch (IllegalArgumentException iae) {
|
||||
/* ignore */
|
||||
} catch (Surface.OutOfResourcesException oore) {
|
||||
/* ignore */
|
||||
}
|
||||
if (canvas == null) {
|
||||
return;
|
||||
}
|
||||
if (DEBUG_VIEWPORT_WINDOW) {
|
||||
Slog.i(LOG_TAG, "Bounds: " + mBounds);
|
||||
}
|
||||
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
|
||||
mPaint.setAlpha(mAlpha);
|
||||
Path path = mBounds.getBoundaryPath();
|
||||
canvas.drawPath(path, mPaint);
|
||||
|
||||
mSurface.unlockCanvasAndPost(canvas);
|
||||
t.show(mSurfaceControl);
|
||||
} else {
|
||||
t.hide(mSurfaceControl);
|
||||
alpha = mAlpha;
|
||||
if (alpha > 0) {
|
||||
drawingBounds = new Region(mBounds);
|
||||
// Empty dirty rectangle means unspecified.
|
||||
if (mDirtyRect.isEmpty()) {
|
||||
mBounds.getBounds(mDirtyRect);
|
||||
}
|
||||
mDirtyRect.inset(-mHalfBorderWidth, -mHalfBorderWidth);
|
||||
drawingRect = new Rect(mDirtyRect);
|
||||
if (DEBUG_VIEWPORT_WINDOW) {
|
||||
Slog.i(LOG_TAG, "ViewportWindow bounds: " + mBounds);
|
||||
Slog.i(LOG_TAG, "ViewportWindow dirty rect: " + mDirtyRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw without holding WindowManagerGlobalLock.
|
||||
if (alpha > 0) {
|
||||
Canvas canvas = null;
|
||||
try {
|
||||
canvas = mSurface.lockCanvas(drawingRect);
|
||||
} catch (IllegalArgumentException | OutOfResourcesException e) {
|
||||
/* ignore */
|
||||
}
|
||||
if (canvas == null) {
|
||||
return;
|
||||
}
|
||||
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
|
||||
mPaint.setAlpha(alpha);
|
||||
canvas.drawPath(drawingBounds.getBoundaryPath(), mPaint);
|
||||
mSurface.unlockCanvasAndPost(canvas);
|
||||
t.show(mSurfaceControl);
|
||||
} else {
|
||||
t.hide(mSurfaceControl);
|
||||
}
|
||||
}
|
||||
|
||||
void releaseSurface() {
|
||||
|
||||
Reference in New Issue
Block a user