From 957deabf2955380585650df4eaf2384b1f8ecbbe Mon Sep 17 00:00:00 2001 From: Jackal Guo Date: Tue, 4 Feb 2020 14:34:40 +0800 Subject: [PATCH] Apply the screen matrix to the boundsInScreen View could be embedded within a SurfaceView via SurfaceControlViewHost now. We need to apply the screen matrix to the bound after that since the host SurfaceView may scale or offset the embedded view. Otherwise, the boundsInScreen would be incorrect. Bug: 148821260 Test: a11y CTS & unit tests Change-Id: Ia590cfd20b26a9d9c58b8499098d25ad9d67f261 --- .../view/AccessibilityEmbeddedConnection.java | 9 +++-- .../AccessibilityInteractionController.java | 36 +++++++++++++++++++ core/java/android/view/View.java | 6 ++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/core/java/android/view/AccessibilityEmbeddedConnection.java b/core/java/android/view/AccessibilityEmbeddedConnection.java index cc1e5010edc77..5d3466907ea20 100644 --- a/core/java/android/view/AccessibilityEmbeddedConnection.java +++ b/core/java/android/view/AccessibilityEmbeddedConnection.java @@ -33,6 +33,7 @@ import java.lang.ref.WeakReference; */ final class AccessibilityEmbeddedConnection extends IAccessibilityEmbeddedConnection.Stub { private final WeakReference mViewRootImpl; + private final Matrix mTmpScreenMatrix = new Matrix(); AccessibilityEmbeddedConnection(ViewRootImpl viewRootImpl) { mViewRootImpl = new WeakReference<>(viewRootImpl); @@ -73,9 +74,11 @@ final class AccessibilityEmbeddedConnection extends IAccessibilityEmbeddedConnec public void setScreenMatrix(float[] matrixValues) { final ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null) { - // TODO(b/148821260): Implement the rest of matrix values. - viewRootImpl.mAttachInfo.mLocationInParentDisplay.set( - (int) matrixValues[Matrix.MTRANS_X], (int) matrixValues[Matrix.MTRANS_Y]); + mTmpScreenMatrix.setValues(matrixValues); + if (viewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy == null) { + viewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy = new Matrix(); + } + viewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy.set(mTmpScreenMatrix); } } } diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java index 3ca84c1eb18d0..6d4ac0ed53275 100644 --- a/core/java/android/view/AccessibilityInteractionController.java +++ b/core/java/android/view/AccessibilityInteractionController.java @@ -21,6 +21,7 @@ import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_A import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_REQUESTED_KEY; import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY; +import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; @@ -109,6 +110,7 @@ public final class AccessibilityInteractionController { private final Rect mTempRect = new Rect(); private final Rect mTempRect1 = new Rect(); private final Rect mTempRect2 = new Rect(); + private final RectF mTempRectF = new RectF(); private AddNodeInfosForViewId mAddNodeInfosForViewId; @@ -855,6 +857,38 @@ public final class AccessibilityInteractionController { return mViewRootImpl.mAttachInfo.mLocationInParentDisplay.equals(0, 0); } + private void applyScreenMatrixIfNeeded(List infos) { + if (infos == null || shouldBypassApplyScreenMatrix()) { + return; + } + final int infoCount = infos.size(); + for (int i = 0; i < infoCount; i++) { + final AccessibilityNodeInfo info = infos.get(i); + applyScreenMatrixIfNeeded(info); + } + } + + private void applyScreenMatrixIfNeeded(AccessibilityNodeInfo info) { + if (info == null || shouldBypassApplyScreenMatrix()) { + return; + } + final Rect boundsInScreen = mTempRect; + final RectF transformedBounds = mTempRectF; + final Matrix screenMatrix = mViewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy; + + info.getBoundsInScreen(boundsInScreen); + transformedBounds.set(boundsInScreen); + screenMatrix.mapRect(transformedBounds); + boundsInScreen.set((int) transformedBounds.left, (int) transformedBounds.top, + (int) transformedBounds.right, (int) transformedBounds.bottom); + info.setBoundsInScreen(boundsInScreen); + } + + private boolean shouldBypassApplyScreenMatrix() { + final Matrix screenMatrix = mViewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy; + return screenMatrix == null || screenMatrix.isIdentity(); + } + private void associateLeashedParentIfNeeded(List infos) { if (infos == null || shouldBypassAssociateLeashedParent()) { return; @@ -945,6 +979,7 @@ public final class AccessibilityInteractionController { try { mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; associateLeashedParentIfNeeded(infos); + applyScreenMatrixIfNeeded(infos); adjustBoundsInScreenIfNeeded(infos); // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node, // then impact the visibility result, we need to adjust visibility before apply scale. @@ -967,6 +1002,7 @@ public final class AccessibilityInteractionController { try { mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; associateLeashedParentIfNeeded(info); + applyScreenMatrixIfNeeded(info); adjustBoundsInScreenIfNeeded(info); // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node, // then impact the visibility result, we need to adjust visibility before apply scale. diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index f99c965845859..ac67eb3141684 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -28820,6 +28820,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ final Point mLocationInParentDisplay = new Point(); + /** + * The screen matrix of this view when it's on a {@link SurfaceControlViewHost} that is + * embedded within a SurfaceView. + */ + Matrix mScreenMatrixInEmbeddedHierarchy; + /** * Global to the view hierarchy used as a temporary for dealing with * x/y points in the transparent region computations.