/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view.accessibility; import android.accessibilityservice.AccessibilityGestureEvent; import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.IAccessibilityServiceClient; import android.accessibilityservice.IAccessibilityServiceConnection; import android.accessibilityservice.MagnificationConfig; import android.annotation.ColorInt; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.content.ComponentName; import android.content.Context; import android.content.pm.ResolveInfo; import android.graphics.Region; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.inputmethod.EditorInfo; import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback; import com.android.internal.inputmethod.RemoteAccessibilityInputConnection; import java.util.Collections; import java.util.List; import java.util.concurrent.Executor; /** * Allows a privileged app - an app with MANAGE_ACCESSIBILITY permission and SystemAPI access - to * interact with the windows in the display that this proxy represents. Proxying the default display * or a display that is not tracked by accessibility, such as private displays, will throw an * exception. Only the real user has access to global clients like SystemUI. * *
* To register and unregister a proxy, use * {@link AccessibilityManager#registerDisplayProxy(AccessibilityDisplayProxy)} * and {@link AccessibilityManager#unregisterDisplayProxy(AccessibilityDisplayProxy)}. If the app * that has registered the proxy dies, the system will remove the proxy. * *
* Avoid using the app's main thread. Proxy methods such as {@link #getWindows} and node methods * like {@link AccessibilityNodeInfo#getChild(int)} will happen frequently. Node methods may also * wait on the displayed app's UI thread to obtain accurate screen data. * *
* To get a list of {@link AccessibilityServiceInfo}s that have populated {@link ComponentName}s and
* {@link ResolveInfo}s, retrieve the list using {@link #getInstalledAndEnabledServices()} after
* {@link #onProxyConnected()} has been called.
*
* @hide
*/
@SystemApi
public abstract class AccessibilityDisplayProxy {
private static final String LOG_TAG = "AccessibilityDisplayProxy";
private static final int INVALID_CONNECTION_ID = -1;
private List
* AccessibilityEvents represent changes to the UI, or what parts of the node tree have changed.
* AccessibilityDisplayProxy should use these to query new UI and send appropriate feedback
* to their users.
*
* For example, a {@link AccessibilityEvent#TYPE_WINDOWS_CHANGED} indicates a change in windows,
* so a proxy may query {@link #getWindows} to obtain updated UI and potentially inform of a new
* window title. Or a proxy may emit an earcon on a
* {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
*/
public void onAccessibilityEvent(@NonNull AccessibilityEvent event) {
// Default no-op
}
/**
* Handles a successful system connection after
* {@link AccessibilityManager#registerDisplayProxy(AccessibilityDisplayProxy)} is called.
*
*
* At this point, querying for UI is available and {@link AccessibilityEvent}s will begin being
* sent. An AccessibilityDisplayProxy may instantiate core infrastructure components here.
*/
public void onProxyConnected() {
// Default no-op
}
/**
* Handles a request to interrupt the accessibility feedback.
*
* AccessibilityDisplayProxy should interrupt the accessibility activity occurring on its
* display. For example, a screen reader may interrupt speech.
*
* @see AccessibilityManager#interrupt()
* @see AccessibilityService#onInterrupt()
*/
public void interrupt() {
// Default no-op
}
/**
* Gets the node with focus, in this display.
*
* 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.)
*
* 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.
*/
@Nullable
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);
}
/**
* Gets the windows of the tracked display.
*
* @see AccessibilityService#getWindows()
*/
@NonNull
public List 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 accessibility services.
*/
public void setInstalledAndEnabledServices(
@NonNull List