Merge "Expose A11yDisplayProxy#findFocus"

This commit is contained in:
Sally Yuen
2023-01-11 17:31:08 +00:00
committed by Android (Google) Code Review
5 changed files with 63 additions and 20 deletions

View File

@@ -16536,6 +16536,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();

View File

@@ -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) {

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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