Expose A11yDisplayProxy#findFocus
A proxy can retrieve input or accessibility focus. - Make sure a proxy and non-proxy user cannot obtain each other's nodes. - Remove ACTIVE_WINDOW code when finding focus, since ACTIVE_WINDOW is not used. What this CL does not do: - separate input focus between proxy and non-proxy users. This can't be done properly until V - separate a11y focus between proxy and non-proxy users. This will be in a future CL. Bug: 264594384 Test: atest AccessibiltiyDisplayProxyTest Change-Id: Iefd88806a5a33deb7ef2ec2460ee79167c82519d
This commit is contained in:
@@ -16499,6 +16499,7 @@ package android.view.accessibility {
|
||||
|
||||
public abstract class AccessibilityDisplayProxy {
|
||||
ctor public AccessibilityDisplayProxy(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.List<android.accessibilityservice.AccessibilityServiceInfo>);
|
||||
method @Nullable public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
|
||||
method public int getDisplayId();
|
||||
method @NonNull public final java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAndEnabledServices();
|
||||
method @NonNull public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
|
||||
|
||||
@@ -83,7 +83,7 @@ public abstract class AccessibilityDisplayProxy {
|
||||
* @param displayId the id of the display to proxy.
|
||||
* @param executor the executor used to execute proxy callbacks.
|
||||
* @param installedAndEnabledServices the list of infos representing the installed and
|
||||
* enabled a11y services.
|
||||
* enabled accessibility services.
|
||||
*/
|
||||
public AccessibilityDisplayProxy(int displayId, @NonNull Executor executor,
|
||||
@NonNull List<AccessibilityServiceInfo> installedAndEnabledServices) {
|
||||
@@ -147,19 +147,27 @@ public abstract class AccessibilityDisplayProxy {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the focus of the window specified by {@code windowInfo}.
|
||||
* Gets the node with focus, in this display.
|
||||
*
|
||||
* @param windowInfo the window to search
|
||||
* @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or
|
||||
* <p>For {@link AccessibilityNodeInfo#FOCUS_INPUT}, this returns the input-focused node in the
|
||||
* proxy display if this display can receive unspecified input events (input that does not
|
||||
* specify a target display.)
|
||||
*
|
||||
* <p>For {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}, this returns the
|
||||
* accessibility-focused node in the proxy display if the display has accessibility focus.
|
||||
* @param focusType The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or
|
||||
* {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}.
|
||||
* @return The node info of the focused view or null.
|
||||
* @hide
|
||||
* TODO(254545943): Do not expose until support for accessibility focus and/or input is in place
|
||||
|
||||
*/
|
||||
@Nullable
|
||||
public AccessibilityNodeInfo findFocus(@NonNull AccessibilityWindowInfo windowInfo, int focus) {
|
||||
AccessibilityNodeInfo windowRoot = windowInfo.getRoot();
|
||||
return windowRoot != null ? windowRoot.findFocus(focus) : null;
|
||||
public AccessibilityNodeInfo findFocus(int focusType) {
|
||||
// TODO(264423198): Support querying the focused node of the proxy's display even if it is
|
||||
// not the top-focused display and can't receive untargeted input events.
|
||||
// TODO(254545943): Separate accessibility focus between proxy and phone state.
|
||||
return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId,
|
||||
AccessibilityWindowInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID,
|
||||
focusType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,10 +185,10 @@ public abstract class AccessibilityDisplayProxy {
|
||||
* Sets the list of {@link AccessibilityServiceInfo}s describing the services interested in the
|
||||
* {@link AccessibilityDisplayProxy}'s display.
|
||||
*
|
||||
* <p>These represent a11y features and services that are installed and running. These should
|
||||
* not include {@link AccessibilityService}s installed on the phone.
|
||||
* <p>These represent accessibility features and services that are installed and running. These
|
||||
* should not include {@link AccessibilityService}s installed on the phone.
|
||||
*
|
||||
* @param installedAndEnabledServices the list of installed and running a11y services.
|
||||
* @param installedAndEnabledServices the list of installed and running accessibility services.
|
||||
*/
|
||||
public void setInstalledAndEnabledServices(
|
||||
@NonNull List<AccessibilityServiceInfo> installedAndEnabledServices) {
|
||||
|
||||
@@ -921,8 +921,6 @@ public final class AccessibilityInteractionClient
|
||||
*
|
||||
* @param connectionId The id of a connection for interacting with the system.
|
||||
* @param accessibilityWindowId A unique window id. Use
|
||||
* {@link AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
|
||||
* to query the currently active window. Use
|
||||
* {@link AccessibilityWindowInfo#ANY_WINDOW_ID} to query all
|
||||
* windows
|
||||
* @param accessibilityNodeId A unique view id or virtual descendant id from
|
||||
|
||||
@@ -132,7 +132,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
private static final String TRACE_WM = "WindowManagerInternal";
|
||||
private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000;
|
||||
|
||||
/** Display type for displays associated with the default user of th device. */
|
||||
/** Display type for displays associated with the default user of the device. */
|
||||
public static final int DISPLAY_TYPE_DEFAULT = 1 << 0;
|
||||
/** Display type for displays associated with an AccessibilityDisplayProxy user. */
|
||||
public static final int DISPLAY_TYPE_PROXY = 1 << 1;
|
||||
@@ -1993,17 +1993,29 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
|
||||
private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
|
||||
if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) {
|
||||
return mA11yWindowManager.getActiveWindowId(mSystemSupport.getCurrentUserIdLocked());
|
||||
final int focusedWindowId =
|
||||
mA11yWindowManager.getActiveWindowId(mSystemSupport.getCurrentUserIdLocked());
|
||||
if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) {
|
||||
return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
|
||||
}
|
||||
return focusedWindowId;
|
||||
}
|
||||
return accessibilityWindowId;
|
||||
}
|
||||
|
||||
private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
|
||||
if (windowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) {
|
||||
return mA11yWindowManager.getActiveWindowId(mSystemSupport.getCurrentUserIdLocked());
|
||||
}
|
||||
if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) {
|
||||
return mA11yWindowManager.getFocusedWindowId(focusType);
|
||||
final int focusedWindowId = mA11yWindowManager.getFocusedWindowId(focusType);
|
||||
// If the caller is a proxy and the found window doesn't belong to a proxy display
|
||||
// (or vice versa), then return null. This doesn't work if there are multiple active
|
||||
// proxys, but in the future this code shouldn't be needed if input and a11y focus are
|
||||
// properly split. (so we will deal with the issues if we see them).
|
||||
//TODO(254545943): Remove this when there is user and proxy separation of input and a11y
|
||||
// focus
|
||||
if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) {
|
||||
return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
|
||||
}
|
||||
return focusedWindowId;
|
||||
}
|
||||
return windowId;
|
||||
}
|
||||
|
||||
@@ -155,6 +155,30 @@ public class AccessibilityWindowManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the window belongs to a display of {@code displayTypes}.
|
||||
*/
|
||||
public boolean windowIdBelongsToDisplayType(int focusedWindowId, int displayTypes) {
|
||||
// UIAutomation wants focus from any display type.
|
||||
final int displayTypeMask = DISPLAY_TYPE_PROXY | DISPLAY_TYPE_DEFAULT;
|
||||
if ((displayTypes & displayTypeMask) == displayTypeMask) {
|
||||
return true;
|
||||
}
|
||||
synchronized (mLock) {
|
||||
final int count = mDisplayWindowsObservers.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
|
||||
if (observer != null
|
||||
&& observer.findA11yWindowInfoByIdLocked(focusedWindowId) != null) {
|
||||
return observer.mIsProxy
|
||||
? ((displayTypes & DISPLAY_TYPE_PROXY) != 0)
|
||||
: (displayTypes & DISPLAY_TYPE_DEFAULT) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class implements {@link WindowManagerInternal.WindowsForAccessibilityCallback} to
|
||||
* receive {@link WindowInfo}s from window manager when there's an accessibility change in
|
||||
|
||||
Reference in New Issue
Block a user