Merge "Add new APIs to support RegionInScreen in A11yWindowInfo"
diff --git a/api/current.txt b/api/current.txt
index 7c13dc1..e855596 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -52435,6 +52435,7 @@
method public int getId();
method public int getLayer();
method public android.view.accessibility.AccessibilityWindowInfo getParent();
+ method public void getRegionInScreen(@NonNull android.graphics.Region);
method public android.view.accessibility.AccessibilityNodeInfo getRoot();
method @Nullable public CharSequence getTitle();
method public int getType();
diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java
index abf5e3f..57dfc62 100644
--- a/core/java/android/view/WindowInfo.java
+++ b/core/java/android/view/WindowInfo.java
@@ -16,7 +16,7 @@
package android.view;
-import android.graphics.Rect;
+import android.graphics.Region;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -44,7 +44,7 @@
public IBinder parentToken;
public IBinder activityToken;
public boolean focused;
- public final Rect boundsInScreen = new Rect();
+ public Region regionInScreen = new Region();
public List<IBinder> childTokens;
public CharSequence title;
public long accessibilityIdOfAnchor = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
@@ -73,7 +73,7 @@
window.parentToken = other.parentToken;
window.activityToken = other.activityToken;
window.focused = other.focused;
- window.boundsInScreen.set(other.boundsInScreen);
+ window.regionInScreen.set(other.regionInScreen);
window.title = other.title;
window.accessibilityIdOfAnchor = other.accessibilityIdOfAnchor;
window.inPictureInPicture = other.inPictureInPicture;
@@ -109,7 +109,7 @@
parcel.writeStrongBinder(parentToken);
parcel.writeStrongBinder(activityToken);
parcel.writeInt(focused ? 1 : 0);
- boundsInScreen.writeToParcel(parcel, flags);
+ regionInScreen.writeToParcel(parcel, flags);
parcel.writeCharSequence(title);
parcel.writeLong(accessibilityIdOfAnchor);
parcel.writeInt(inPictureInPicture ? 1 : 0);
@@ -132,7 +132,8 @@
builder.append(", type=").append(type);
builder.append(", layer=").append(layer);
builder.append(", token=").append(token);
- builder.append(", bounds=").append(boundsInScreen);
+ builder.append(", region=").append(regionInScreen);
+ builder.append(", bounds=").append(regionInScreen.getBounds());
builder.append(", parent=").append(parentToken);
builder.append(", focused=").append(focused);
builder.append(", children=").append(childTokens);
@@ -151,7 +152,7 @@
parentToken = parcel.readStrongBinder();
activityToken = parcel.readStrongBinder();
focused = (parcel.readInt() == 1);
- boundsInScreen.readFromParcel(parcel);
+ regionInScreen = Region.CREATOR.createFromParcel(parcel);
title = parcel.readCharSequence();
accessibilityIdOfAnchor = parcel.readLong();
inPictureInPicture = (parcel.readInt() == 1);
@@ -174,7 +175,7 @@
parentToken = null;
activityToken = null;
focused = false;
- boundsInScreen.setEmpty();
+ regionInScreen.setEmpty();
if (childTokens != null) {
childTokens.clear();
}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 985effb..fd09a87 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -622,6 +622,10 @@
/**
* Change type for {@link #TYPE_WINDOWS_CHANGED} event:
* The window's bounds changed.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#R R}, this event implies the window's
+ * region changed. It's also possible that region changed but bounds doesn't.
+ * </p>
*/
public static final int WINDOWS_CHANGE_BOUNDS = 0x00000008;
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index ea61ef8..6a3af34 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -16,9 +16,11 @@
package android.view.accessibility;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.graphics.Rect;
+import android.graphics.Region;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -107,7 +109,7 @@
private int mBooleanProperties;
private int mId = UNDEFINED_WINDOW_ID;
private int mParentId = UNDEFINED_WINDOW_ID;
- private final Rect mBoundsInScreen = new Rect();
+ private Region mRegionInScreen = new Region();
private LongArray mChildIds;
private CharSequence mTitle;
private long mAnchorId = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
@@ -305,23 +307,33 @@
}
/**
- * Gets the bounds of this window in the screen.
+ * Gets the touchable region of this window in the screen.
+ *
+ * @param outRegion The out window region.
+ */
+ public void getRegionInScreen(@NonNull Region outRegion) {
+ outRegion.set(mRegionInScreen);
+ }
+
+ /**
+ * Sets the touchable region of this window in the screen.
+ *
+ * @param region The window region.
+ *
+ * @hide
+ */
+ public void setRegionInScreen(Region region) {
+ mRegionInScreen.set(region);
+ }
+
+ /**
+ * Gets the bounds of this window in the screen. This is equivalent to get the bounds of the
+ * Region from {@link #getRegionInScreen(Region)}.
*
* @param outBounds The out window bounds.
*/
public void getBoundsInScreen(Rect outBounds) {
- outBounds.set(mBoundsInScreen);
- }
-
- /**
- * Sets the bounds of this window in the screen.
- *
- * @param bounds The out window bounds.
- *
- * @hide
- */
- public void setBoundsInScreen(Rect bounds) {
- mBoundsInScreen.set(bounds);
+ outBounds.set(mRegionInScreen.getBounds());
}
/**
@@ -522,7 +534,7 @@
parcel.writeInt(mBooleanProperties);
parcel.writeInt(mId);
parcel.writeInt(mParentId);
- mBoundsInScreen.writeToParcel(parcel, flags);
+ mRegionInScreen.writeToParcel(parcel, flags);
parcel.writeCharSequence(mTitle);
parcel.writeLong(mAnchorId);
@@ -552,7 +564,7 @@
mBooleanProperties = other.mBooleanProperties;
mId = other.mId;
mParentId = other.mParentId;
- mBoundsInScreen.set(other.mBoundsInScreen);
+ mRegionInScreen.set(other.mRegionInScreen);
mTitle = other.mTitle;
mAnchorId = other.mAnchorId;
@@ -574,7 +586,7 @@
mBooleanProperties = parcel.readInt();
mId = parcel.readInt();
mParentId = parcel.readInt();
- mBoundsInScreen.readFromParcel(parcel);
+ mRegionInScreen = Region.CREATOR.createFromParcel(parcel);
mTitle = parcel.readCharSequence();
mAnchorId = parcel.readLong();
@@ -621,7 +633,8 @@
builder.append(", id=").append(mId);
builder.append(", type=").append(typeToString(mType));
builder.append(", layer=").append(mLayer);
- builder.append(", bounds=").append(mBoundsInScreen);
+ builder.append(", region=").append(mRegionInScreen);
+ builder.append(", bounds=").append(mRegionInScreen.getBounds());
builder.append(", focused=").append(isFocused());
builder.append(", active=").append(isActive());
builder.append(", pictureInPicture=").append(isInPictureInPictureMode());
@@ -661,7 +674,7 @@
mBooleanProperties = 0;
mId = UNDEFINED_WINDOW_ID;
mParentId = UNDEFINED_WINDOW_ID;
- mBoundsInScreen.setEmpty();
+ mRegionInScreen.setEmpty();
mChildIds = null;
mConnectionId = UNDEFINED_WINDOW_ID;
mAnchorId = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
@@ -716,7 +729,6 @@
}
}
-
/**
* Reports how this window differs from a possibly different state of the same window. The
* argument must have the same id and type as neither of those properties may change.
@@ -739,8 +751,7 @@
if (!TextUtils.equals(mTitle, other.mTitle)) {
changes |= AccessibilityEvent.WINDOWS_CHANGE_TITLE;
}
-
- if (!mBoundsInScreen.equals(other.mBoundsInScreen)) {
+ if (!mRegionInScreen.equals(other.mRegionInScreen)) {
changes |= AccessibilityEvent.WINDOWS_CHANGE_BOUNDS;
}
if (mLayer != other.mLayer) {
diff --git a/core/tests/coretests/src/android/view/WindowInfoTest.java b/core/tests/coretests/src/android/view/WindowInfoTest.java
index 037a0d9..05e8bd8 100644
--- a/core/tests/coretests/src/android/view/WindowInfoTest.java
+++ b/core/tests/coretests/src/android/view/WindowInfoTest.java
@@ -91,7 +91,7 @@
assertFalse(w.focused);
assertFalse(w.inPictureInPicture);
assertFalse(w.hasFlagWatchOutsideTouch);
- assertTrue(w.boundsInScreen.isEmpty());
+ assertTrue(w.regionInScreen.isEmpty());
}
@SmallTest
@@ -114,7 +114,7 @@
equality &= w1.childTokens.equals(w2.childTokens);
equality &= w1.parentToken == w2.parentToken;
equality &= w1.activityToken == w2.activityToken;
- equality &= w1.boundsInScreen.equals(w2.boundsInScreen);
+ equality &= w1.regionInScreen.equals(w2.regionInScreen);
return equality;
}
@@ -132,6 +132,6 @@
windowInfo.focused = true;
windowInfo.inPictureInPicture = true;
windowInfo.hasFlagWatchOutsideTouch = true;
- windowInfo.boundsInScreen.set(0, 0, 1080, 1080);
+ windowInfo.regionInScreen.set(0, 0, 1080, 1080);
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index 8415272..1dea2f2 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -23,7 +23,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
import android.os.Handler;
@@ -277,7 +276,7 @@
} else if (!oldWindow.activityToken.equals(newWindow.activityToken)) {
return true;
}
- if (!oldWindow.boundsInScreen.equals(newWindow.boundsInScreen)) {
+ if (!oldWindow.regionInScreen.equals(newWindow.regionInScreen)) {
return true;
}
if (oldWindow.childTokens != null && newWindow.childTokens != null
@@ -755,20 +754,20 @@
boolean windowInteractiveRegionChanged = false;
final int windowCount = mWindows.size();
- final Rect currentWindowBounds = new Rect();
+ final Region currentWindowRegions = new Region();
for (int i = windowCount - 1; i >= 0; i--) {
AccessibilityWindowInfo currentWindow = mWindows.get(i);
if (windowInteractiveRegion == null) {
if (currentWindow.getId() == windowId) {
- currentWindow.getBoundsInScreen(currentWindowBounds);
- outRegion.set(currentWindowBounds);
+ currentWindow.getRegionInScreen(currentWindowRegions);
+ outRegion.set(currentWindowRegions);
windowInteractiveRegion = outRegion;
continue;
}
} else if (currentWindow.getType()
!= AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) {
- currentWindow.getBoundsInScreen(currentWindowBounds);
- if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) {
+ currentWindow.getRegionInScreen(currentWindowRegions);
+ if (windowInteractiveRegion.op(currentWindowRegions, Region.Op.DIFFERENCE)) {
windowInteractiveRegionChanged = true;
}
}
@@ -1115,7 +1114,7 @@
reportedWindow.setType(getTypeForWindowManagerWindowType(window.type));
reportedWindow.setLayer(window.layer);
reportedWindow.setFocused(window.focused);
- reportedWindow.setBoundsInScreen(window.boundsInScreen);
+ reportedWindow.setRegionInScreen(window.regionInScreen);
reportedWindow.setTitle(window.title);
reportedWindow.setAnchorId(window.accessibilityIdOfAnchor);
reportedWindow.setPictureInPicture(window.inPictureInPicture);
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index bace7e3..8abfde2 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -22,6 +22,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.utils.RegionUtils.forEachRect;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
@@ -1126,14 +1127,13 @@
// Iterate until we figure out what is touchable for the entire screen.
for (int i = visibleWindowCount - 1; i >= 0; i--) {
final WindowState windowState = visibleWindows.valueAt(i);
+ final Region regionInScreen = new Region();
+ computeWindowRegionInScreen(windowState, regionInScreen);
- final Rect boundsInScreen = mTempRect;
- computeWindowBoundsInScreen(windowState, boundsInScreen);
-
- if (windowMattersToAccessibility(windowState, boundsInScreen, unaccountedSpace,
+ if (windowMattersToAccessibility(windowState, regionInScreen, unaccountedSpace,
skipRemainingWindowsForTasks)) {
- addPopulatedWindowInfo(windowState, boundsInScreen, windows, addedWindows);
- updateUnaccountedSpace(windowState, boundsInScreen, unaccountedSpace,
+ addPopulatedWindowInfo(windowState, regionInScreen, windows, addedWindows);
+ updateUnaccountedSpace(windowState, regionInScreen, unaccountedSpace,
skipRemainingWindowsForTasks);
focusedWindowAdded |= windowState.isFocused();
}
@@ -1171,8 +1171,9 @@
clearAndRecycleWindows(windows);
}
- private boolean windowMattersToAccessibility(WindowState windowState, Rect boundsInScreen,
- Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
+ private boolean windowMattersToAccessibility(WindowState windowState,
+ Region regionInScreen, Region unaccountedSpace,
+ HashSet<Integer> skipRemainingWindowsForTasks) {
if (windowState.isFocused()) {
return true;
}
@@ -1192,7 +1193,7 @@
}
// If the window is completely covered by other windows - ignore.
- if (unaccountedSpace.quickReject(boundsInScreen)) {
+ if (unaccountedSpace.quickReject(regionInScreen)) {
return false;
}
@@ -1204,7 +1205,7 @@
return false;
}
- private void updateUnaccountedSpace(WindowState windowState, Rect boundsInScreen,
+ private void updateUnaccountedSpace(WindowState windowState, Region regionInScreen,
Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
if (windowState.mAttrs.type
!= WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
@@ -1212,59 +1213,71 @@
// Account for the space this window takes if the window
// is not an accessibility overlay which does not change
// the reported windows.
- unaccountedSpace.op(boundsInScreen, unaccountedSpace,
+ unaccountedSpace.op(regionInScreen, unaccountedSpace,
Region.Op.REVERSE_DIFFERENCE);
// If a window is modal it prevents other windows from being touched
if ((windowState.mAttrs.flags & (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)) == 0) {
- // Account for all space in the task, whether the windows in it are
- // touchable or not. The modal window blocks all touches from the task's
- // area.
- unaccountedSpace.op(windowState.getDisplayFrameLw(), unaccountedSpace,
- Region.Op.REVERSE_DIFFERENCE);
+ if (!windowState.hasTapExcludeRegion()) {
+ // Account for all space in the task, whether the windows in it are
+ // touchable or not. The modal window blocks all touches from the task's
+ // area.
+ unaccountedSpace.op(windowState.getDisplayFrameLw(), unaccountedSpace,
+ Region.Op.REVERSE_DIFFERENCE);
+ } else {
+ // If a window has tap exclude region, we need to account it.
+ final Region displayRegion = new Region(windowState.getDisplayFrameLw());
+ final Region tapExcludeRegion = new Region();
+ windowState.amendTapExcludeRegion(tapExcludeRegion);
+ displayRegion.op(tapExcludeRegion, displayRegion,
+ Region.Op.REVERSE_DIFFERENCE);
+ unaccountedSpace.op(displayRegion, unaccountedSpace,
+ Region.Op.REVERSE_DIFFERENCE);
+ }
final Task task = windowState.getTask();
if (task != null) {
// If the window is associated with a particular task, we can skip the
// rest of the windows for that task.
skipRemainingWindowsForTasks.add(task.mTaskId);
- } else {
+ } else if (!windowState.hasTapExcludeRegion()) {
// If the window is not associated with a particular task, then it is
- // globally modal. In this case we can skip all remaining windows.
+ // globally modal. In this case we can skip all remaining windows when
+ // it doesn't has tap exclude region.
unaccountedSpace.setEmpty();
}
}
}
}
- private void computeWindowBoundsInScreen(WindowState windowState, Rect outBounds) {
+ private void computeWindowRegionInScreen(WindowState windowState, Region outRegion) {
// Get the touchable frame.
Region touchableRegion = mTempRegion1;
windowState.getTouchableRegion(touchableRegion);
- Rect touchableFrame = mTempRect;
- touchableRegion.getBounds(touchableFrame);
-
- // Move to origin as all transforms are captured by the matrix.
- RectF windowFrame = mTempRectF;
- windowFrame.set(touchableFrame);
- windowFrame.offset(-windowState.getFrameLw().left, -windowState.getFrameLw().top);
// Map the frame to get what appears on the screen.
Matrix matrix = mTempMatrix;
populateTransformationMatrixLocked(windowState, matrix);
- matrix.mapRect(windowFrame);
- // Got the bounds.
- outBounds.set((int) windowFrame.left, (int) windowFrame.top,
- (int) windowFrame.right, (int) windowFrame.bottom);
+ forEachRect(touchableRegion, rect -> {
+ // Move to origin as all transforms are captured by the matrix.
+ RectF windowFrame = mTempRectF;
+ windowFrame.set(rect);
+ windowFrame.offset(-windowState.getFrameLw().left, -windowState.getFrameLw().top);
+
+ matrix.mapRect(windowFrame);
+
+ // Union all rects.
+ outRegion.union(new Rect((int) windowFrame.left, (int) windowFrame.top,
+ (int) windowFrame.right, (int) windowFrame.bottom));
+ });
}
- private static void addPopulatedWindowInfo(
- WindowState windowState, Rect boundsInScreen,
+ private static void addPopulatedWindowInfo(WindowState windowState, Region regionInScreen,
List<WindowInfo> out, Set<IBinder> tokenOut) {
final WindowInfo window = windowState.getWindowInfo();
- window.boundsInScreen.set(boundsInScreen);
+ window.regionInScreen.set(regionInScreen);
window.layer = tokenOut.size();
out.add(window);
tokenOut.add(window.token);
@@ -1293,7 +1306,7 @@
private void populateVisibleWindowsOnScreenLocked(SparseArray<WindowState> outWindows) {
final List<WindowState> tempWindowStatesList = new ArrayList<>();
final DisplayContent dc = mService.getDefaultDisplayContentLocked();
- dc.forAllWindows((w) -> {
+ dc.forAllWindows(w -> {
if (w.isVisibleLw()) {
tempWindowStatesList.add(w);
}
@@ -1306,17 +1319,11 @@
return;
}
- // TODO: Use Region instead to get rid of this complicated logic.
- // Check the tap exclude region of the parent window. If the tap exclude region
- // is empty, it means there is another can-receive-pointer-event view on top of
- // the region. Hence, we don't count the window as visible.
if (w.isVisibleLw() && parentWindow.getDisplayContent().isDefaultDisplay
- && parentWindow.hasTapExcludeRegion()
&& tempWindowStatesList.contains(parentWindow)) {
- tempWindowStatesList.add(
- tempWindowStatesList.lastIndexOf(parentWindow) + 1, w);
+ tempWindowStatesList.add(tempWindowStatesList.lastIndexOf(parentWindow), w);
}
- }, true /* traverseTopToBottom */);
+ }, false /* traverseTopToBottom */);
for (int i = 0; i < tempWindowStatesList.size(); i++) {
outWindows.put(i, tempWindowStatesList.get(i));
}
diff --git a/services/core/java/com/android/server/wm/utils/RegionUtils.java b/services/core/java/com/android/server/wm/utils/RegionUtils.java
index b1b3070..ce7776f 100644
--- a/services/core/java/com/android/server/wm/utils/RegionUtils.java
+++ b/services/core/java/com/android/server/wm/utils/RegionUtils.java
@@ -50,6 +50,20 @@
/**
* Applies actions on each rect contained within a {@code Region}.
*
+ * @param region the given region.
+ * @param rectConsumer the action holder.
+ */
+ public static void forEachRect(Region region, Consumer<Rect> rectConsumer) {
+ final RegionIterator it = new RegionIterator(region);
+ final Rect rect = new Rect();
+ while (it.next(rect)) {
+ rectConsumer.accept(rect);
+ }
+ }
+
+ /**
+ * Applies actions on each rect contained within a {@code Region}.
+ *
* Order is bottom to top, then right to left.
*
* @param region the given region.
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
index 22408cc..e125329 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
@@ -238,7 +238,7 @@
windowInfo.type = AccessibilityWindowInfo.TYPE_APPLICATION;
windowInfo.token = token.asBinder();
windowInfo.layer = 0;
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
mWindowInfos.set(0, windowInfo);
mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
@@ -305,67 +305,73 @@
}
@Test
- public void computePartialInteractiveRegionForWindow_wholeWindowVisible_returnWholeRegion() {
+ public void computePartialInteractiveRegionForWindow_wholeVisible_returnWholeRegion() {
// Updates top 2 z-order WindowInfo are whole visible.
WindowInfo windowInfo = mWindowInfos.get(0);
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
+ windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
windowInfo = mWindowInfos.get(1);
- windowInfo.boundsInScreen.set(0, SCREEN_HEIGHT / 2,
- SCREEN_WIDTH, SCREEN_HEIGHT);
+ windowInfo.regionInScreen.set(0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT);
mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
final Region outBounds = new Region();
int windowId = a11yWindows.get(0).getId();
- mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
- windowId, outBounds);
+ mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds);
assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH));
assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT / 2));
windowId = a11yWindows.get(1).getId();
- mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
- windowId, outBounds);
+ mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds);
assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH));
assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT / 2));
}
@Test
- public void computePartialInteractiveRegionForWindow_halfWindowVisible_returnHalfRegion() {
+ public void computePartialInteractiveRegionForWindow_halfVisible_returnHalfRegion() {
// Updates z-order #1 WindowInfo is half visible
WindowInfo windowInfo = mWindowInfos.get(0);
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
- windowInfo = mWindowInfos.get(1);
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
final Region outBounds = new Region();
int windowId = a11yWindows.get(1).getId();
- mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
- windowId, outBounds);
+ mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds);
assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH));
assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT / 2));
}
@Test
- public void computePartialInteractiveRegionForWindow_windowNotVisible_returnEmptyRegion() {
- // Updates z-order #1 WindowInfo is not visible
+ public void computePartialInteractiveRegionForWindow_notVisible_returnEmptyRegion() {
+ // Since z-order #0 WindowInfo is full screen, z-order #1 WindowInfo should be invisible.
+ final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
+ final Region outBounds = new Region();
+ int windowId = a11yWindows.get(1).getId();
+
+ mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds);
+ assertTrue(outBounds.getBounds().isEmpty());
+ }
+
+ @Test
+ public void computePartialInteractiveRegionForWindow_partialVisible_returnVisibleRegion() {
+ // Updates z-order #0 WindowInfo to have two interact-able areas.
+ Region region = new Region(0, 0, SCREEN_WIDTH, 200);
+ region.op(0, SCREEN_HEIGHT - 200, SCREEN_WIDTH, SCREEN_HEIGHT, Region.Op.UNION);
WindowInfo windowInfo = mWindowInfos.get(0);
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
- windowInfo = mWindowInfos.get(1);
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ windowInfo.regionInScreen.set(region);
mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
final Region outBounds = new Region();
int windowId = a11yWindows.get(1).getId();
- mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
- windowId, outBounds);
- assertTrue(outBounds.getBounds().isEmpty());
+ mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds);
+ assertFalse(outBounds.getBounds().isEmpty());
+ assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH));
+ assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT - 400));
}
@Test
@@ -588,7 +594,7 @@
windowInfo.type = AccessibilityWindowInfo.TYPE_APPLICATION;
windowInfo.token = windowToken.asBinder();
windowInfo.layer = layer;
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
mWindowInfos.add(windowInfo);
}