summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Roy Chou <juchengchou@google.com> 2024-03-07 06:28:59 +0000
committer Roy Chou <juchengchou@google.com> 2024-03-21 07:30:03 +0000
commitf75ad18ed082dd0a95ab277f8214b1070e1fc8d6 (patch)
tree30957518014efbcf5015bd36a8ae5874f0f6a977
parent99075875adc670ea7a3ef409ddc85d41f7095c07 (diff)
fix(magnification): directly use the window touchableRegion in AccessibilityController magnification recomputeBounds
In AccessibilityController recomputeBounds, currently it create a touchable rect from the WindowState's touchableRegion to compute the magnification region. However, if there are separated rects in the touchableRegion, then the created touchable rect might be a large rect consisting of non-touchable areas in that WindowState. Therefore, the fix is to directly use the WindowState's exact touchableRegion in computation so the non-touchable areas will not be included. The fix is guarded behind a flag to verify with rollout process, so we can check if there are some side-effect or performance issues. Bug: 323366243 Flag: ACONFIG com.android.window.flags.use_window_original_touchable_region_when_magnification_recompute_bounds DEVELOPMENT Test: manually flip flag atest AccessibilityMagnificationTest Change-Id: I4681e286f7b4465fca5c77d579be104ff73ad42f
-rw-r--r--core/java/android/window/flags/accessibility.aconfig12
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java63
2 files changed, 65 insertions, 10 deletions
diff --git a/core/java/android/window/flags/accessibility.aconfig b/core/java/android/window/flags/accessibility.aconfig
index 90b54bd76a60..590e88ba11f0 100644
--- a/core/java/android/window/flags/accessibility.aconfig
+++ b/core/java/android/window/flags/accessibility.aconfig
@@ -13,6 +13,16 @@ flag {
description: "Always draw fullscreen orange border in fullscreen magnification"
bug: "291891390"
metadata {
- purpose: PURPOSE_BUGFIX
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "use_window_original_touchable_region_when_magnification_recompute_bounds"
+ namespace: "accessibility"
+ description: "The flag controls whether to use the window original touchable regions in accessibilityController recomputeBounds"
+ bug: "323366243"
+ metadata {
+ purpose: PURPOSE_BUGFIX
}
} \ No newline at end of file
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 418998870f16..3f041cb48ee2 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -961,16 +961,37 @@ final class AccessibilityController {
populateTransformationMatrix(windowState, matrix);
Region touchableRegion = mTempRegion3;
windowState.getTouchableRegion(touchableRegion);
- Rect touchableFrame = mTempRect1;
- touchableRegion.getBounds(touchableFrame);
- RectF windowFrame = mTempRectF;
- windowFrame.set(touchableFrame);
- windowFrame.offset(-windowState.getFrame().left,
- -windowState.getFrame().top);
- matrix.mapRect(windowFrame);
Region windowBounds = mTempRegion2;
- windowBounds.set((int) windowFrame.left, (int) windowFrame.top,
- (int) windowFrame.right, (int) windowFrame.bottom);
+ if (Flags.useWindowOriginalTouchableRegionWhenMagnificationRecomputeBounds()) {
+ // For b/323366243, if using the bounds from touchableRegion.getBounds, in
+ // non-magnifiable windowBounds computation, part of the non-touchableRegion
+ // may be included into nonMagnifiedBounds. This will make users lose
+ // the magnification control on mis-included areas.
+ // Therefore, to prevent the above issue, we change to use the window exact
+ // touchableRegion in magnificationRegion computation.
+ // Like the original approach, the touchableRegion is in non-magnified display
+ // space, so first we need to offset the region by the windowFrames bounds, then
+ // apply the transform matrix to the region to get the exact region in magnified
+ // display space.
+ // TODO: For a long-term plan, since touchable regions provided by WindowState
+ // doesn't actually reflect the real touchable regions on display, we should
+ // delete the WindowState dependency and migrate to use the touchableRegion
+ // from WindowInfoListener data. (b/330653961)
+ touchableRegion.translate(-windowState.getFrame().left,
+ -windowState.getFrame().top);
+ applyMatrixToRegion(matrix, touchableRegion);
+ windowBounds.set(touchableRegion);
+ } else {
+ Rect touchableFrame = mTempRect1;
+ touchableRegion.getBounds(touchableFrame);
+ RectF windowFrame = mTempRectF;
+ windowFrame.set(touchableFrame);
+ windowFrame.offset(-windowState.getFrame().left,
+ -windowState.getFrame().top);
+ matrix.mapRect(windowFrame);
+ windowBounds.set((int) windowFrame.left, (int) windowFrame.top,
+ (int) windowFrame.right, (int) windowFrame.bottom);
+ }
// Only update new regions
Region portionOfWindowAlreadyAccountedFor = mTempRegion3;
portionOfWindowAlreadyAccountedFor.set(mMagnificationRegion);
@@ -1066,6 +1087,30 @@ final class AccessibilityController {
|| windowType == TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
}
+ private void applyMatrixToRegion(Matrix matrix, Region region) {
+ // Since Matrix does not support mapRegion api, so we follow the Matrix#mapRect logic
+ // to apply the matrix to the given region.
+ // In Matrix#mapRect, the internal calculation is applying the transform matrix to
+ // rect's 4 corner points with the below calculation. (see SkMatrix::mapPoints)
+ // |A B C| |x| Ax+By+C Dx+Ey+F
+ // |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
+ // |G H I| |1| Gx+Hy+I Gx+Hy+I
+ // For magnification usage, the matrix is created from
+ // WindowState#getTransformationMatrix. We can simplify the matrix calculation to be
+ // |scale 0 trans_x| |x|
+ // | 0 scale trans_y| |y| = (scale*x + trans_x, scale*y + trans_y)
+ // | 0 0 1 | |1|
+ // So, to follow the simplified matrix computation, we first scale the region with
+ // matrix.scale, then translate the region with matrix.trans_x and matrix.trans_y.
+ float[] transformArray = sTempFloats;
+ matrix.getValues(transformArray);
+ // For magnification transform matrix, the scale_x and scale_y are equal.
+ region.scale(transformArray[Matrix.MSCALE_X]);
+ region.translate(
+ (int) transformArray[Matrix.MTRANS_X],
+ (int) transformArray[Matrix.MTRANS_Y]);
+ }
+
private void populateWindowsOnScreen(SparseArray<WindowState> outWindows) {
mTempLayer = 0;
mDisplayContent.forAllWindows((w) -> {