Merge changes from topic "overlay"

* changes:
  Create  display accessibility overlay API.
  Expose SurfacePackage#getSurfaceControl
This commit is contained in:
Ameer Armaly
2022-11-17 22:53:34 +00:00
committed by Android (Google) Code Review
10 changed files with 112 additions and 10 deletions

View File

@@ -3087,6 +3087,7 @@ package android.accessibilityservice {
public abstract class AccessibilityService extends android.app.Service {
ctor public AccessibilityService();
method public void attachAccessibilityOverlayToDisplay(int, @NonNull android.view.SurfaceControl);
method public boolean clearCache();
method public boolean clearCachedSubtree(@NonNull android.view.accessibility.AccessibilityNodeInfo);
method public final void disableSelf();
@@ -49980,6 +49981,7 @@ package android.view {
public static final class SurfaceControlViewHost.SurfacePackage implements android.os.Parcelable {
ctor public SurfaceControlViewHost.SurfacePackage(@NonNull android.view.SurfaceControlViewHost.SurfacePackage);
method public int describeContents();
method @NonNull public android.view.SurfaceControl getSurfaceControl();
method public void notifyConfigurationChanged(@NonNull android.content.res.Configuration);
method public void notifyDetachedFromWindow();
method public void release();

View File

@@ -56,7 +56,7 @@ import android.util.SparseArray;
import android.view.Display;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityCache;
@@ -2467,8 +2467,8 @@ public abstract class AccessibilityService extends Service {
* </p>
* <p>
* <strong>Note:</strong> If the view with {@link AccessibilityNodeInfo#FOCUS_INPUT}
* is on an embedded view hierarchy which is embedded in a {@link SurfaceView} via
* {@link SurfaceView#setChildSurfacePackage}, there is a limitation that this API
* is on an embedded view hierarchy which is embedded in a {@link android.view.SurfaceView} via
* {@link android.view.SurfaceView#setChildSurfacePackage}, there is a limitation that this API
* won't be able to find the node for the view. It's because views don't know about
* the embedded hierarchies. Instead, you could traverse all the nodes to find the
* focus.
@@ -3379,4 +3379,28 @@ public abstract class AccessibilityService extends Service {
controller.onStateChanged(state);
}
}
/**
* Attaches a {@link android.view.SurfaceControl} containing an accessibility overlay to the
* specified display. This type of overlay should be used for content that does not need to
* track the location and size of Views in the currently active app e.g. service configuration
* or general service UI. To remove this overlay and free the associated resources, use
* <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.
*
* @param displayId the display to which the SurfaceControl should be attached.
* @param sc the SurfaceControl containing the overlay content
*/
public void attachAccessibilityOverlayToDisplay(int displayId, @NonNull SurfaceControl sc) {
Preconditions.checkNotNull(sc, "SurfaceControl cannot be null");
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getConnection(mConnectionId);
if (connection == null) {
return;
}
try {
connection.attachAccessibilityOverlayToDisplay(displayId, sc);
} catch (RemoteException re) {
throw new RuntimeException(re);
}
}
}

View File

@@ -25,6 +25,7 @@ import android.os.Bundle;
import android.os.RemoteCallback;
import android.view.MagnificationSpec;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
@@ -155,4 +156,5 @@ interface IAccessibilityServiceConnection {
void setInstalledAndEnabledServices(in List<AccessibilityServiceInfo> infos);
List<AccessibilityServiceInfo> getInstalledAndEnabledServices();
void attachAccessibilityOverlayToDisplay(int displayId, in SurfaceControl sc);
}

View File

@@ -159,9 +159,11 @@ public class SurfaceControlViewHost {
}
/**
* Use {@link SurfaceView#setChildSurfacePackage} or manually fix
* accessibility (see SurfaceView implementation).
* @hide
* Returns the {@link android.view.SurfaceControl} associated with this SurfacePackage for
* cases where more control is required.
*
* @return the SurfaceControl associated with this SurfacePackage and its containing
* SurfaceControlViewHost
*/
public @NonNull SurfaceControl getSurfaceControl() {
return mSurfaceControl;

View File

@@ -27,6 +27,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.view.SurfaceControl;
import android.window.ScreenCapture;
import java.util.Collections;
@@ -222,4 +223,7 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon
public List<AccessibilityServiceInfo> getInstalledAndEnabledServices() throws RemoteException {
return null;
}
@Override
public void attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc) {}
}

View File

@@ -76,6 +76,7 @@ import android.util.SparseArray;
import android.view.Display;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowInfo;
import android.view.accessibility.AccessibilityCache;
@@ -289,6 +290,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
void requestImeLocked(AbstractAccessibilityServiceConnection connection);
void unbindImeLocked(AbstractAccessibilityServiceConnection connection);
void attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc);
}
public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName,
@@ -2486,4 +2489,9 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
}
@Override
public void attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc) {
mSystemSupport.attachAccessibilityOverlayToDisplay(displayId, sc);
}
}

View File

@@ -109,6 +109,7 @@ import android.view.IWindow;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.WindowInfo;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
@@ -291,12 +292,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private Point mTempPoint = new Point();
private boolean mIsAccessibilityButtonShown;
private boolean mInputBound;
IRemoteAccessibilityInputConnection mRemoteInputConnection;
EditorInfo mEditorInfo;
boolean mRestarting;
boolean mInputSessionRequested;
private SparseArray<SurfaceControl> mA11yOverlayLayers = new SparseArray<>();
private AccessibilityUserState getCurrentUserStateLocked() {
return getUserStateLocked(mCurrentUserId);
@@ -3967,6 +3968,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
synchronized (mLock) {
mDisplaysList.add(display);
mA11yOverlayLayers.put(
displayId, mWindowManagerService.getA11yOverlayLayer(displayId));
if (mInputFilter != null) {
mInputFilter.onDisplayAdded(display);
}
@@ -3990,6 +3993,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
if (!removeDisplayFromList(displayId)) {
return;
}
mA11yOverlayLayers.remove(displayId);
if (mInputFilter != null) {
mInputFilter.onDisplayRemoved(displayId);
}
@@ -4691,4 +4695,30 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
return true;
}
}
@Override
public void attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc) {
mMainHandler.sendMessage(
obtainMessage(
AccessibilityManagerService::attachAccessibilityOverlayToDisplayInternal,
this,
displayId,
sc));
}
void attachAccessibilityOverlayToDisplayInternal(int displayId, SurfaceControl sc) {
if (!mA11yOverlayLayers.contains(displayId)) {
mA11yOverlayLayers.put(displayId, mWindowManagerService.getA11yOverlayLayer(displayId));
}
SurfaceControl parent = mA11yOverlayLayers.get(displayId);
if (parent == null) {
Slog.e(LOG_TAG, "Unable to get accessibility overlay SurfaceControl.");
mA11yOverlayLayers.remove(displayId);
return;
}
SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
transaction.reparent(sc, parent);
transaction.apply();
transaction.close();
}
}

View File

@@ -311,6 +311,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/
private SurfaceControl mOverlayLayer;
/** A surfaceControl specifically for accessibility overlays. */
private SurfaceControl mA11yOverlayLayer;
/**
* The direct child layer of the display to put all non-overlay windows. This is also used for
* screen rotation animation so that there is a parent layer to put the animation leash.
@@ -1269,12 +1272,21 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
transaction.reparent(mOverlayLayer, mSurfaceControl);
}
if (mA11yOverlayLayer == null) {
mA11yOverlayLayer =
b.setName("Accessibility Overlays").setParent(mSurfaceControl).build();
} else {
transaction.reparent(mA11yOverlayLayer, mSurfaceControl);
}
transaction
.setLayer(mSurfaceControl, 0)
.setLayerStack(mSurfaceControl, mDisplayId)
.show(mSurfaceControl)
.setLayer(mOverlayLayer, Integer.MAX_VALUE)
.show(mOverlayLayer);
.show(mOverlayLayer)
.setLayer(mA11yOverlayLayer, Integer.MAX_VALUE - 1)
.show(mA11yOverlayLayer);
}
boolean isReady() {
@@ -3250,6 +3262,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
setRemoteInsetsController(null);
mWmService.mAnimator.removeDisplayLocked(mDisplayId);
mOverlayLayer.release();
mA11yOverlayLayer.release();
mWindowingLayer.release();
mInputMonitor.onDisplayRemoved();
mWmService.mDisplayNotificationController.dispatchDisplayRemoved(this);
@@ -5502,6 +5515,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return mOverlayLayer;
}
SurfaceControl getA11yOverlayLayer() {
return mA11yOverlayLayer;
}
SurfaceControl[] findRoundedCornerOverlays() {
List<SurfaceControl> roundedCornerOverlays = new ArrayList<>();
for (WindowToken token : mTokenMap.values()) {

View File

@@ -903,4 +903,7 @@ public abstract class WindowManagerInternal {
* could not be prepared and the session needs to be torn down.
*/
public abstract boolean setContentRecordingSession(ContentRecordingSession incomingSession);
/** Returns the SurfaceControl accessibility services should use for accessibility overlays. */
public abstract SurfaceControl getA11yOverlayLayer(int displayId);
}

View File

@@ -736,7 +736,6 @@ public class WindowManagerService extends IWindowManager.Stub
@VisibleForTesting
final ContentRecordingController mContentRecordingController = new ContentRecordingController();
@VisibleForTesting
final class SettingsObserver extends ContentObserver {
private final Uri mDisplayInversionEnabledUri =
@@ -8301,6 +8300,17 @@ public class WindowManagerService extends IWindowManager.Stub
return true;
}
}
@Override
public SurfaceControl getA11yOverlayLayer(int displayId) {
synchronized (mGlobalLock) {
DisplayContent dc = mRoot.getDisplayContent(displayId);
if (dc != null) {
return dc.getA11yOverlayLayer();
}
}
return null;
}
}
void registerAppFreezeListener(AppFreezeListener listener) {