Add AccessibilityNodeInfo#getBoundsInWindow

We can already get the bounds in terms of the screen and the parent view, but not the containing window.
Fix:253059851
Test: atest FrameworksCoreTests:AccessibilityNodeInfoTest CtsAccessibilityTestCases:AccessibilityNodeInfoTest

Change-Id: Ie86a77951a30e2360c5e491cadb763bf847519c2
This commit is contained in:
Ameer Armaly
2023-02-01 15:53:47 +00:00
parent 7f3a9bce35
commit e97c7e1a45
4 changed files with 104 additions and 3 deletions

View File

@@ -53885,6 +53885,7 @@ package android.view.accessibility {
method public java.util.List<java.lang.String> getAvailableExtraData();
method @Deprecated public void getBoundsInParent(android.graphics.Rect);
method public void getBoundsInScreen(android.graphics.Rect);
method public void getBoundsInWindow(@NonNull android.graphics.Rect);
method public android.view.accessibility.AccessibilityNodeInfo getChild(int);
method @Nullable public android.view.accessibility.AccessibilityNodeInfo getChild(int, int);
method public int getChildCount();
@@ -53963,6 +53964,7 @@ package android.view.accessibility {
method public void setAvailableExtraData(java.util.List<java.lang.String>);
method @Deprecated public void setBoundsInParent(android.graphics.Rect);
method public void setBoundsInScreen(android.graphics.Rect);
method public void setBoundsInWindow(@NonNull android.graphics.Rect);
method public void setCanOpenPopup(boolean);
method public void setCheckable(boolean);
method public void setChecked(boolean);

View File

@@ -8945,11 +8945,33 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
outRect.set(position.left, position.top, position.right, position.bottom);
}
/**
* Gets the location of this view in window coordinates.
*
* @param outRect The output location
* @param clipToParent Whether to clip child bounds to the parent ones.
* @hide
*/
public void getBoundsInWindow(Rect outRect, boolean clipToParent) {
if (mAttachInfo == null) {
return;
}
RectF position = mAttachInfo.mTmpTransformRect;
getBoundsToWindowInternal(position, clipToParent);
outRect.set(Math.round(position.left), Math.round(position.top),
Math.round(position.right), Math.round(position.bottom));
}
private void getBoundsToScreenInternal(RectF position, boolean clipToParent) {
position.set(0, 0, mRight - mLeft, mBottom - mTop);
mapRectFromViewToScreenCoords(position, clipToParent);
}
private void getBoundsToWindowInternal(RectF position, boolean clipToParent) {
position.set(0, 0, mRight - mLeft, mBottom - mTop);
mapRectFromViewToWindowCoords(position, clipToParent);
}
/**
* Map a rectangle from view-relative coordinates to screen-relative coordinates
*
@@ -8958,6 +8980,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
mapRectFromViewToWindowCoords(rect, clipToParent);
rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
}
/**
* Map a rectangle from view-relative coordinates to window-relative coordinates
*
* @param rect The rectangle to be mapped
* @param clipToParent Whether to clip child bounds to the parent ones.
* @hide
*/
public void mapRectFromViewToWindowCoords(RectF rect, boolean clipToParent) {
if (!hasIdentityMatrix()) {
getMatrix().mapRect(rect);
}
@@ -8990,8 +9024,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
rect.offset(0, -viewRootImpl.mCurScrollY);
}
rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
}
/**
@@ -10578,6 +10610,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
getBoundsOnScreen(bounds, true);
info.setBoundsInScreen(bounds);
getBoundsInWindow(bounds, true);
info.setBoundsInWindow(bounds);
ViewParent parent = getParentForAccessibility();
if (parent instanceof View) {

View File

@@ -906,6 +906,7 @@ public class AccessibilityNodeInfo implements Parcelable {
private int mBooleanProperties;
private final Rect mBoundsInParent = new Rect();
private final Rect mBoundsInScreen = new Rect();
private final Rect mBoundsInWindow = new Rect();
private int mDrawingOrderInParent;
private CharSequence mPackageName;
@@ -2155,6 +2156,49 @@ public class AccessibilityNodeInfo implements Parcelable {
mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
}
/**
* Gets the node bounds in window coordinates.
* <p>
* When magnification is enabled, the bounds in window are scaled up by magnification scale
* and the positions are also adjusted according to the offset of magnification viewport.
* For example, it returns Rect(-180, -180, 0, 0) for original bounds Rect(10, 10, 100, 100),
* when the magnification scale is 2 and offsets for X and Y are both 200.
* <p/>
*
* @param outBounds The output node bounds.
*/
public void getBoundsInWindow(@NonNull Rect outBounds) {
outBounds.set(mBoundsInWindow.left, mBoundsInWindow.top,
mBoundsInWindow.right, mBoundsInWindow.bottom);
}
/**
* Returns the actual rect containing the node bounds in window coordinates.
*
* @hide Not safe to expose outside the framework.
*/
@NonNull
public Rect getBoundsInWindow() {
return mBoundsInWindow;
}
/**
* Sets the node bounds in window coordinates.
* <p>
* <strong>Note:</strong> Cannot be called from an
* {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
*
* @param bounds The node bounds.
*
* @throws IllegalStateException If called from an AccessibilityService.
*/
public void setBoundsInWindow(@NonNull Rect bounds) {
enforceNotSealed();
mBoundsInWindow.set(bounds);
}
/**
* Gets whether this node is checkable.
*
@@ -4054,6 +4098,11 @@ public class AccessibilityNodeInfo implements Parcelable {
nonDefaultFields |= bitAt(fieldIndex);
}
fieldIndex++;
if (!Objects.equals(mBoundsInWindow, DEFAULT.mBoundsInWindow)) {
nonDefaultFields |= bitAt(fieldIndex);
}
fieldIndex++;
if (!Objects.equals(mActions, DEFAULT.mActions)) nonDefaultFields |= bitAt(fieldIndex);
fieldIndex++;
if (mMaxTextLength != DEFAULT.mMaxTextLength) nonDefaultFields |= bitAt(fieldIndex);
@@ -4202,6 +4251,13 @@ public class AccessibilityNodeInfo implements Parcelable {
parcel.writeInt(mBoundsInScreen.right);
}
if (isBitSet(nonDefaultFields, fieldIndex++)) {
parcel.writeInt(mBoundsInWindow.top);
parcel.writeInt(mBoundsInWindow.bottom);
parcel.writeInt(mBoundsInWindow.left);
parcel.writeInt(mBoundsInWindow.right);
}
if (isBitSet(nonDefaultFields, fieldIndex++)) {
if (mActions != null && !mActions.isEmpty()) {
final int actionCount = mActions.size();
@@ -4333,6 +4389,7 @@ public class AccessibilityNodeInfo implements Parcelable {
mUniqueId = other.mUniqueId;
mBoundsInParent.set(other.mBoundsInParent);
mBoundsInScreen.set(other.mBoundsInScreen);
mBoundsInWindow.set(other.mBoundsInWindow);
mPackageName = other.mPackageName;
mClassName = other.mClassName;
mText = other.mText;
@@ -4464,6 +4521,13 @@ public class AccessibilityNodeInfo implements Parcelable {
mBoundsInScreen.right = parcel.readInt();
}
if (isBitSet(nonDefaultFields, fieldIndex++)) {
mBoundsInWindow.top = parcel.readInt();
mBoundsInWindow.bottom = parcel.readInt();
mBoundsInWindow.left = parcel.readInt();
mBoundsInWindow.right = parcel.readInt();
}
if (isBitSet(nonDefaultFields, fieldIndex++)) {
final long standardActions = parcel.readLong();
addStandardActions(standardActions);
@@ -4815,6 +4879,7 @@ public class AccessibilityNodeInfo implements Parcelable {
builder.append("; boundsInParent: ").append(mBoundsInParent);
builder.append("; boundsInScreen: ").append(mBoundsInScreen);
builder.append("; boundsInWindow: ").append(mBoundsInScreen);
builder.append("; packageName: ").append(mPackageName);
builder.append("; className: ").append(mClassName);

View File

@@ -46,7 +46,7 @@ public class AccessibilityNodeInfoTest {
// The number of fields tested in the corresponding CTS AccessibilityNodeInfoTest:
// See fullyPopulateAccessibilityNodeInfo, assertEqualsAccessibilityNodeInfo,
// and assertAccessibilityNodeInfoCleared in that class.
private static final int NUM_MARSHALLED_PROPERTIES = 42;
private static final int NUM_MARSHALLED_PROPERTIES = 43;
/**
* The number of properties that are purposely not marshalled