diff options
5 files changed, 132 insertions, 52 deletions
diff --git a/api/current.txt b/api/current.txt index eacc45261261..7665f43476d4 100644 --- a/api/current.txt +++ b/api/current.txt @@ -35771,6 +35771,7 @@ package android.view.accessibility { method public android.view.accessibility.AccessibilityWindowInfo getParent(); method public android.view.accessibility.AccessibilityNodeInfo getRoot(); method public int getType(); + method public boolean isAccessibilityFocused(); method public boolean isActive(); method public boolean isFocused(); method public static android.view.accessibility.AccessibilityWindowInfo obtain(); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 19dd5837fe42..f54f8249bbda 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -7021,27 +7021,23 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (another == null) { return 1; } - if (getClass() != another.getClass()) { - return 1; - } - final int topDiference = mLocation.top - another.mLocation.top; - if (topDiference != 0) { - return topDiference; - } - // LTR + // We are ordering left-to-right, top-to-bottom. if (mLayoutDirection == LAYOUT_DIRECTION_LTR) { final int leftDifference = mLocation.left - another.mLocation.left; - // First more to the left than second. if (leftDifference != 0) { return leftDifference; } } else { // RTL final int rightDifference = mLocation.right - another.mLocation.right; - // First more to the right than second. if (rightDifference != 0) { return -rightDifference; } } + // We are ordering left-to-right, top-to-bottom. + final int topDifference = mLocation.top - another.mLocation.top; + if (topDifference != 0) { + return topDifference; + } // Break tie by height. final int heightDiference = mLocation.height() - another.mLocation.height(); if (heightDiference != 0) { diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java index ca6437a4d31c..ead757eb9a7d 100644 --- a/core/java/android/view/accessibility/AccessibilityCache.java +++ b/core/java/android/view/accessibility/AccessibilityCache.java @@ -54,7 +54,12 @@ final class AccessibilityCache { if (DEBUG) { Log.i(LOG_TAG, "Caching window: " + window.getId()); } - mWindowCache.put(window.getId(), window); + final int windowId = window.getId(); + AccessibilityWindowInfo oldWindow = mWindowCache.get(windowId); + if (oldWindow != null) { + oldWindow.recycle(); + } + mWindowCache.put(windowId, AccessibilityWindowInfo.obtain(window)); } } @@ -183,14 +188,13 @@ final class AccessibilityCache { sortedWindows.put(window.getLayer(), window); } - List<AccessibilityWindowInfo> windows = new ArrayList<>(); + List<AccessibilityWindowInfo> windows = new ArrayList<>(windowCount); for (int i = windowCount - 1; i >= 0; i--) { AccessibilityWindowInfo window = sortedWindows.valueAt(i); windows.add(AccessibilityWindowInfo.obtain(window)); + sortedWindows.removeAt(i); } - sortedWindows.clear(); - return windows; } return null; diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java index 80b5c5071c3a..ad55f5f2a097 100644 --- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java +++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java @@ -55,6 +55,7 @@ public final class AccessibilityWindowInfo implements Parcelable { private static final int BOOLEAN_PROPERTY_ACTIVE = 1 << 0; private static final int BOOLEAN_PROPERTY_FOCUSED = 1 << 1; + private static final int BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED = 1 << 2; // Housekeeping. private static final int MAX_POOL_SIZE = 10; @@ -258,6 +259,26 @@ public final class AccessibilityWindowInfo implements Parcelable { } /** + * Gets if this window has accessibility focus. + * + * @return Whether has accessibility focus. + */ + public boolean isAccessibilityFocused() { + return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED); + } + + /** + * Sets if this window has accessibility focus. + * + * @param Whether has accessibility focus. + * + * @hide + */ + public void setAccessibilityFocused(boolean focused) { + setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED, focused); + } + + /** * Gets the number of child windows. * * @return The child count. diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index b1f19540060c..4e2f52c5e5b7 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -124,6 +124,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // when that accessibility services are bound. private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000; + private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000; + private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE = "registerUiTestAutomationService"; @@ -1367,6 +1369,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (mWindowsForAccessibilityCallback != null) { mWindowsForAccessibilityCallback = null; mWindowManagerService.setWindowsForAccessibilityCallback(null); + // Drop all windows we know about. + mSecurityPolicy.clearWindowsLocked(); } } @@ -1631,16 +1635,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { pw.println("}]"); pw.println(); } - final int windowCount = mSecurityPolicy.mWindows.size(); - for (int j = 0; j < windowCount; j++) { - if (j > 0) { - pw.append(','); - pw.println(); + if (mSecurityPolicy.mWindows != null) { + final int windowCount = mSecurityPolicy.mWindows.size(); + for (int j = 0; j < windowCount; j++) { + if (j > 0) { + pw.append(','); + pw.println(); + } + pw.append("Window["); + AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(j); + pw.append(window.toString()); + pw.append(']'); } - pw.append("Window["); - AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(j); - pw.append(window.toString()); - pw.append(']'); } } } @@ -1821,6 +1827,39 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return -1; } + private void ensureWindowsAvailableTimed() { + synchronized (mLock) { + if (mSecurityPolicy.mWindows != null) { + return; + } + // If we have no registered callback, update the state we + // we may have to register one but it didn't happen yet. + if (mWindowsForAccessibilityCallback == null) { + UserState userState = getCurrentUserStateLocked(); + onUserStateChangedLocked(userState); + } + // We have no windows but do not care about them, done. + if (mWindowsForAccessibilityCallback == null) { + return; + } + + // Wait for the windows with a timeout. + final long startMillis = SystemClock.uptimeMillis(); + while (mSecurityPolicy.mWindows == null) { + final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; + final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis; + if (remainMillis <= 0) { + return; + } + try { + mLock.wait(remainMillis); + } catch (InterruptedException ie) { + /* ignore */ + } + } + } + } + /** * This class represents an accessibility service. It stores all per service * data required for the service management, provides API for starting/stopping the @@ -1876,9 +1915,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final KeyEventDispatcher mKeyEventDispatcher = new KeyEventDispatcher(); - final SparseArray<AccessibilityWindowInfo> mIntrospectedWindows = - new SparseArray<>(); - boolean mWasConnectedAndDied; // Handler only for dispatching accessibility events since we use event @@ -1946,10 +1982,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0; mRetrieveInteractiveWindows = (info.flags & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0; - - if (!mRetrieveInteractiveWindows) { - clearIntrospectedWindows(); - } } /** @@ -2065,6 +2097,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public List<AccessibilityWindowInfo> getWindows() { + ensureWindowsAvailableTimed(); synchronized (mLock) { // We treat calls from a profile as if made by its perent as profiles // share the accessibility state of the parent. The call below @@ -2087,7 +2120,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window); windowClone.setConnectionId(mId); - mIntrospectedWindows.put(window.getId(), windowClone); windows.add(windowClone); } return windows; @@ -2096,6 +2128,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public AccessibilityWindowInfo getWindow(int windowId) { + ensureWindowsAvailableTimed(); synchronized (mLock) { // We treat calls from a profile as if made by its parent as profiles // share the accessibility state of the parent. The call below @@ -2115,7 +2148,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (window != null) { AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window); windowClone.setConnectionId(mId); - mIntrospectedWindows.put(windowId, windowClone); return windowClone; } return null; @@ -2607,19 +2639,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } public void notifyClearAccessibilityNodeInfoCache() { - clearIntrospectedWindows(); mInvocationHandler.sendEmptyMessage( InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE); } - private void clearIntrospectedWindows() { - final int windowCount = mIntrospectedWindows.size(); - for (int i = windowCount - 1; i >= 0; i--) { - mIntrospectedWindows.valueAt(i).recycle(); - mIntrospectedWindows.removeAt(i); - } - } - private void notifyGestureInternal(int gestureId) { final IAccessibilityServiceClient listener; synchronized (mLock) { @@ -2955,6 +2978,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // Let the policy update the focused and active windows. mSecurityPolicy.updateWindowsLocked(reportedWindows); + + // Someone may be waiting for the windows - advertise it. + mLock.notifyAll(); } } @@ -3130,7 +3156,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; - public final List<AccessibilityWindowInfo> mWindows = new ArrayList<>(); + public List<AccessibilityWindowInfo> mWindows; public int mActiveWindowId = INVALID_WINDOW_ID; public int mFocusedWindowId = INVALID_WINDOW_ID; @@ -3185,7 +3211,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } + public void clearWindowsLocked() { + List<AccessibilityWindowInfo> windows = Collections.emptyList(); + updateWindowsLocked(windows); + mWindows = null; + } + public void updateWindowsLocked(List<AccessibilityWindowInfo> windows) { + if (mWindows == null) { + mWindows = new ArrayList<>(); + } + final int oldWindowCount = mWindows.size(); for (int i = oldWindowCount - 1; i >= 0; i--) { mWindows.remove(i).recycle(); @@ -3231,6 +3267,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (window.getId() == mActiveWindowId) { window.setActive(true); } + if (window.getId() == mAccessibilityFocusedWindowId) { + window.setAccessibilityFocused(true); + } } } @@ -3298,7 +3337,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (mAccessibilityFocusedWindowId != windowId) { mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS, mAccessibilityFocusedWindowId, 0).sendToTarget(); - mAccessibilityFocusedWindowId = windowId; + mSecurityPolicy.setAccessibilityFocusedWindowLocked(windowId); mAccessibilityFocusNodeId = nodeId; } } @@ -3354,11 +3393,28 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private void setActiveWindowLocked(int windowId) { if (mActiveWindowId != windowId) { mActiveWindowId = windowId; - final int windowCount = mWindows.size(); - for (int i = 0; i < windowCount; i++) { - AccessibilityWindowInfo window = mWindows.get(i); - window.setActive(window.getId() == windowId); + if (mWindows != null) { + final int windowCount = mWindows.size(); + for (int i = 0; i < windowCount; i++) { + AccessibilityWindowInfo window = mWindows.get(i); + window.setActive(window.getId() == windowId); + } + } + notifyWindowsChanged(); + } + } + + private void setAccessibilityFocusedWindowLocked(int windowId) { + if (mAccessibilityFocusedWindowId != windowId) { + mAccessibilityFocusedWindowId = windowId; + if (mWindows != null) { + final int windowCount = mWindows.size(); + for (int i = 0; i < windowCount; i++) { + AccessibilityWindowInfo window = mWindows.get(i); + window.setAccessibilityFocused(window.getId() == windowId); + } } + notifyWindowsChanged(); } } @@ -3444,11 +3500,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } private AccessibilityWindowInfo findWindowById(int windowId) { - final int windowCount = mWindows.size(); - for (int i = 0; i < windowCount; i++) { - AccessibilityWindowInfo window = mWindows.get(i); - if (window.getId() == windowId) { - return window; + if (mWindows != null) { + final int windowCount = mWindows.size(); + for (int i = 0; i < windowCount; i++) { + AccessibilityWindowInfo window = mWindows.get(i); + if (window.getId() == windowId) { + return window; + } } } return null; |