Merge "Ensure that windows are separated between the A11yDisplayProxy user and the a11y service user."

This commit is contained in:
Sally Yuen
2022-12-20 15:40:32 +00:00
committed by Android (Google) Code Review
8 changed files with 89 additions and 7 deletions

View File

@@ -42,6 +42,7 @@ import android.accessibilityservice.AccessibilityTrace;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.accessibilityservice.MagnificationConfig;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
@@ -107,6 +108,8 @@ import com.android.server.wm.WindowManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -129,6 +132,11 @@ 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. */
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;
protected static final String TAKE_SCREENSHOT = "takeScreenshot";
protected final Context mContext;
protected final SystemSupport mSystemSupport;
@@ -157,6 +165,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
// The attribution tag set by the service that is bound to this instance
protected String mAttributionTag;
protected int mDisplayTypes = DISPLAY_TYPE_DEFAULT;
// The service that's bound to this instance. Whenever this value is non-null, this
// object is registered as a death recipient
IBinder mService;
@@ -224,6 +234,14 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
*/
private SparseArray<Long> mRequestTakeScreenshotOfWindowTimestampMs = new SparseArray<>();
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true, prefix = { "DISPLAY_TYPE_" }, value = {
DISPLAY_TYPE_DEFAULT,
DISPLAY_TYPE_PROXY
})
public @interface DisplayTypes {}
public interface SystemSupport {
/**
* @return The current dispatcher for key events
@@ -520,7 +538,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
}
final AccessibilityWindowInfo.WindowListSparseArray allWindows =
new AccessibilityWindowInfo.WindowListSparseArray();
final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked();
final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked(
mDisplayTypes);
final int displayListCounts = displayList.size();
if (displayListCounts > 0) {
for (int i = 0; i < displayListCounts; i++) {
@@ -538,6 +557,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
}
}
protected void setDisplayTypes(@DisplayTypes int displayTypes) {
mDisplayTypes = displayTypes;
}
@Override
public AccessibilityWindowInfo getWindow(int windowId) {
if (svcConnTracingEnabled()) {

View File

@@ -457,7 +457,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
new MagnificationScaleProvider(mContext));
mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
mCaptioningManagerImpl = new CaptioningManagerImpl(mContext);
mProxyManager = new ProxyManager(mLock);
mProxyManager = new ProxyManager(mLock, mA11yWindowManager);
init();
}

View File

@@ -21,6 +21,8 @@ import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAG
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static com.android.server.accessibility.AbstractAccessibilityServiceConnection.DISPLAY_TYPE_DEFAULT;
import static com.android.server.accessibility.AbstractAccessibilityServiceConnection.DISPLAY_TYPE_PROXY;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -169,6 +171,7 @@ public class AccessibilityWindowManager {
private List<AccessibilityWindowInfo> mWindows;
private boolean mTrackingWindows = false;
private boolean mHasWatchOutsideTouchWindow;
private boolean mIsProxy;
/**
* Constructor for DisplayWindowsObserver.
@@ -1015,6 +1018,33 @@ public class AccessibilityWindowManager {
}
}
/**
* Starts tracking a display as belonging to a proxy. Creates the window observer if necessary.
* @param displayId
*/
public void startTrackingDisplayProxy(int displayId) {
startTrackingWindows(displayId);
synchronized (mLock) {
DisplayWindowsObserver observer = mDisplayWindowsObservers.get(displayId);
if (observer != null) {
observer.mIsProxy = true;
}
}
}
/**
* Stops tracking a display as belonging to a proxy.
* @param displayId
*/
public void stopTrackingDisplayProxy(int displayId) {
synchronized (mLock) {
DisplayWindowsObserver observer = mDisplayWindowsObservers.get(displayId);
if (observer != null) {
observer.mIsProxy = false;
}
}
}
/**
* Checks if we are tracking windows on any display.
*
@@ -1728,15 +1758,21 @@ public class AccessibilityWindowManager {
/**
* Returns the display list including all displays which are tracking windows.
*
* @param displayTypes the types of displays to retrieve
* @return The display list.
*/
public ArrayList<Integer> getDisplayListLocked() {
public ArrayList<Integer> getDisplayListLocked(
@AbstractAccessibilityServiceConnection.DisplayTypes int displayTypes) {
final ArrayList<Integer> displayList = new ArrayList<>();
final int count = mDisplayWindowsObservers.size();
for (int i = 0; i < count; i++) {
final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
if (observer != null) {
displayList.add(observer.mDisplayId);
if (!observer.mIsProxy && (displayTypes & DISPLAY_TYPE_DEFAULT) != 0) {
displayList.add(observer.mDisplayId);
} else if (observer.mIsProxy && (displayTypes & DISPLAY_TYPE_PROXY) != 0) {
displayList.add(observer.mDisplayId);
}
}
}
return displayList;

View File

@@ -39,12 +39,14 @@ import android.os.RemoteException;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityDisplayProxy;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import androidx.annotation.Nullable;
import com.android.server.wm.WindowManagerInternal;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -74,6 +76,7 @@ public class ProxyAccessibilityServiceConnection extends AccessibilityServiceCon
mainHandler, lock, securityPolicy, systemSupport, trace, windowManagerInternal,
/* systemActionPerformer= */ null, awm, /* activityTaskManagerService= */ null);
mDisplayId = displayId;
setDisplayTypes(DISPLAY_TYPE_PROXY);
}
/**
@@ -188,6 +191,17 @@ public class ProxyAccessibilityServiceConnection extends AccessibilityServiceCon
}
}
@Override
public AccessibilityWindowInfo.WindowListSparseArray getWindows() {
final AccessibilityWindowInfo.WindowListSparseArray allWindows = super.getWindows();
AccessibilityWindowInfo.WindowListSparseArray displayWindows = new
AccessibilityWindowInfo.WindowListSparseArray();
// Filter here so A11yInteractionClient will not cache all the windows belonging to other
// proxy connections.
displayWindows.put(mDisplayId, allWindows.get(mDisplayId, Collections.emptyList()));
return displayWindows;
}
@Override
public void binderDied() {
}

View File

@@ -55,8 +55,11 @@ public class ProxyManager {
private SparseArray<ProxyAccessibilityServiceConnection> mProxyA11yServiceConnections =
new SparseArray<>();
ProxyManager(Object lock) {
private AccessibilityWindowManager mA11yWindowManager;
ProxyManager(Object lock, AccessibilityWindowManager awm) {
mLock = lock;
mA11yWindowManager = awm;
}
/**
@@ -99,6 +102,8 @@ public class ProxyManager {
}
};
client.asBinder().linkToDeath(deathRecipient, 0);
mA11yWindowManager.startTrackingDisplayProxy(displayId);
// Notify apps that the service state has changed.
// A11yManager#A11yServicesStateChangeListener
synchronized (mLock) {
@@ -122,6 +127,7 @@ public class ProxyManager {
return true;
}
}
mA11yWindowManager.stopTrackingDisplayProxy(displayId);
return false;
}

View File

@@ -253,6 +253,7 @@ class UiAutomationManager {
securityPolicy, systemSupport, trace, windowManagerInternal,
systemActionPerformer, awm);
mMainHandler = mainHandler;
setDisplayTypes(DISPLAY_TYPE_DEFAULT | DISPLAY_TYPE_PROXY);
}
void connectServiceUnknownThread() {

View File

@@ -207,7 +207,7 @@ public class AbstractAccessibilityServiceConnectionTest {
addA11yWindowInfo(mA11yWindowInfos, PIP_WINDOWID, true, Display.DEFAULT_DISPLAY);
addA11yWindowInfo(mA11yWindowInfosOnSecondDisplay, WINDOWID_ONSECONDDISPLAY, false,
SECONDARY_DISPLAY_ID);
when(mMockA11yWindowManager.getDisplayListLocked()).thenReturn(mDisplayList);
when(mMockA11yWindowManager.getDisplayListLocked(anyInt())).thenReturn(mDisplayList);
when(mMockA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY))
.thenReturn(mA11yWindowInfos);
when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID))

View File

@@ -16,6 +16,7 @@
package com.android.server.accessibility;
import static com.android.server.accessibility.AbstractAccessibilityServiceConnection.DISPLAY_TYPE_DEFAULT;
import static com.android.server.accessibility.AccessibilityWindowManagerTest.DisplayIdMatcher.displayId;
import static com.android.server.accessibility.AccessibilityWindowManagerTest.WindowChangesMatcher.a11yWindowChanges;
import static com.android.server.accessibility.AccessibilityWindowManagerTest.WindowIdMatcher.a11yWindowId;
@@ -823,7 +824,8 @@ public class AccessibilityWindowManagerTest {
// Starts tracking window of second display.
startTrackingPerDisplay(SECONDARY_DISPLAY_ID);
final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked();
final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked(
DISPLAY_TYPE_DEFAULT);
assertTrue(displayList.equals(mExpectedDisplayList));
}