Improve the windows register and unregister mechanism am: 31eaf452ad
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14637424 Change-Id: If7b01817b2d76d2b7e4512278f853ba5875d3c4d
This commit is contained in:
@@ -373,6 +373,20 @@ public class AccessibilityWindowManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the display is reparented and becomes an embedded
|
||||
* display.
|
||||
*
|
||||
* @param embeddedDisplayId The embedded display Id.
|
||||
*/
|
||||
@Override
|
||||
public void onDisplayReparented(int embeddedDisplayId) {
|
||||
// Removes the un-used window observer for the embedded display.
|
||||
synchronized (mLock) {
|
||||
mDisplayWindowsObservers.remove(embeddedDisplayId);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldUpdateWindowsLocked(boolean forceSend,
|
||||
@NonNull List<WindowInfo> windows) {
|
||||
if (forceSend) {
|
||||
|
||||
@@ -90,6 +90,7 @@ import android.view.animation.Interpolator;
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.util.TraceBuffer;
|
||||
import com.android.internal.util.function.pooled.PooledLambda;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.policy.WindowManagerPolicy;
|
||||
import com.android.server.wm.WindowManagerInternal.AccessibilityControllerInternal;
|
||||
@@ -172,11 +173,15 @@ final class AccessibilityController {
|
||||
|
||||
/**
|
||||
* Sets a callback for observing which windows are touchable for the purposes
|
||||
* of accessibility on specified display.
|
||||
* of accessibility on specified display. When a display is reparented and becomes
|
||||
* an embedded one, the {@link WindowsForAccessibilityCallback#onDisplayReparented(int)}
|
||||
* will notify the accessibility framework to remove the un-used window observer of
|
||||
* this embedded display.
|
||||
*
|
||||
* @param displayId The logical display id.
|
||||
* @param callback The callback.
|
||||
* @return {@code false} if display id is not valid or an embedded display.
|
||||
* @return {@code false} if display id is not valid or an embedded display when the callback
|
||||
* isn't null.
|
||||
*/
|
||||
boolean setWindowsForAccessibilityCallback(int displayId,
|
||||
WindowsForAccessibilityCallback callback) {
|
||||
@@ -185,12 +190,13 @@ final class AccessibilityController {
|
||||
TAG + ".setWindowsForAccessibilityCallback",
|
||||
"displayId=" + displayId + "; callback={" + callback + "}");
|
||||
}
|
||||
final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
|
||||
if (dc == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (callback != null) {
|
||||
final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
|
||||
if (dc == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WindowsForAccessibilityObserver observer =
|
||||
mWindowsForAccessibilityObserver.get(displayId);
|
||||
if (isEmbeddedDisplay(dc)) {
|
||||
@@ -209,21 +215,13 @@ final class AccessibilityController {
|
||||
if (Build.IS_DEBUGGABLE) {
|
||||
throw new IllegalStateException(errorMessage);
|
||||
}
|
||||
removeObserverOfEmbeddedDisplay(observer);
|
||||
removeObserversForEmbeddedChildDisplays(observer);
|
||||
mWindowsForAccessibilityObserver.remove(displayId);
|
||||
}
|
||||
observer = new WindowsForAccessibilityObserver(mService, displayId, callback);
|
||||
mWindowsForAccessibilityObserver.put(displayId, observer);
|
||||
mAllObserversInitialized &= observer.mInitialized;
|
||||
} else {
|
||||
if (isEmbeddedDisplay(dc)) {
|
||||
// If this display is an embedded one, its window observer should be removed along
|
||||
// with the window observer of its parent display removed because the window
|
||||
// observer of the embedded display and its parent display is the same, and would
|
||||
// be removed together when stopping the window tracking of its parent display. So
|
||||
// here don't need to do removing window observer of the embedded display again.
|
||||
return true;
|
||||
}
|
||||
final WindowsForAccessibilityObserver windowsForA11yObserver =
|
||||
mWindowsForAccessibilityObserver.get(displayId);
|
||||
if (windowsForA11yObserver == null) {
|
||||
@@ -234,7 +232,7 @@ final class AccessibilityController {
|
||||
throw new IllegalStateException(errorMessage);
|
||||
}
|
||||
}
|
||||
removeObserverOfEmbeddedDisplay(windowsForA11yObserver);
|
||||
removeObserversForEmbeddedChildDisplays(windowsForA11yObserver);
|
||||
mWindowsForAccessibilityObserver.remove(displayId);
|
||||
}
|
||||
return true;
|
||||
@@ -507,22 +505,34 @@ final class AccessibilityController {
|
||||
if (embeddedDisplayId == Display.DEFAULT_DISPLAY || parentWindow == null) {
|
||||
return;
|
||||
}
|
||||
// Finds the parent display of this embedded display
|
||||
final int parentDisplayId;
|
||||
WindowState candidate = parentWindow;
|
||||
while (candidate != null) {
|
||||
parentWindow = candidate;
|
||||
candidate = parentWindow.getDisplayContent().getParentWindow();
|
||||
mService.mH.sendMessage(PooledLambda.obtainMessage(
|
||||
AccessibilityController::updateWindowObserverOfEmbeddedDisplay,
|
||||
this, embeddedDisplayId, parentWindow));
|
||||
}
|
||||
|
||||
private void updateWindowObserverOfEmbeddedDisplay(int embeddedDisplayId,
|
||||
WindowState parentWindow) {
|
||||
final WindowsForAccessibilityObserver windowsForA11yObserver;
|
||||
|
||||
synchronized (mService.mGlobalLock) {
|
||||
// Finds the parent display of this embedded display
|
||||
WindowState candidate = parentWindow;
|
||||
while (candidate != null) {
|
||||
parentWindow = candidate;
|
||||
candidate = parentWindow.getDisplayContent().getParentWindow();
|
||||
}
|
||||
final int parentDisplayId = parentWindow.getDisplayId();
|
||||
// Uses the observer of parent display
|
||||
windowsForA11yObserver = mWindowsForAccessibilityObserver.get(parentDisplayId);
|
||||
}
|
||||
parentDisplayId = parentWindow.getDisplayId();
|
||||
// Uses the observer of parent display
|
||||
final WindowsForAccessibilityObserver windowsForA11yObserver =
|
||||
mWindowsForAccessibilityObserver.get(parentDisplayId);
|
||||
|
||||
if (windowsForA11yObserver != null) {
|
||||
windowsForA11yObserver.notifyDisplayReparented(embeddedDisplayId);
|
||||
windowsForA11yObserver.addEmbeddedDisplay(embeddedDisplayId);
|
||||
// Replaces the observer of embedded display to the one of parent display
|
||||
mWindowsForAccessibilityObserver.put(embeddedDisplayId, windowsForA11yObserver);
|
||||
synchronized (mService.mGlobalLock) {
|
||||
// Replaces the observer of embedded display to the one of parent display
|
||||
mWindowsForAccessibilityObserver.put(embeddedDisplayId, windowsForA11yObserver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,7 +565,7 @@ final class AccessibilityController {
|
||||
+ "mWindowsForAccessibilityObserver=" + mWindowsForAccessibilityObserver);
|
||||
}
|
||||
|
||||
private void removeObserverOfEmbeddedDisplay(WindowsForAccessibilityObserver
|
||||
private void removeObserversForEmbeddedChildDisplays(WindowsForAccessibilityObserver
|
||||
observerOfParentDisplay) {
|
||||
final IntArray embeddedDisplayIdList =
|
||||
observerOfParentDisplay.getAndClearEmbeddedDisplayIdList();
|
||||
@@ -1541,6 +1551,13 @@ final class AccessibilityController {
|
||||
mEmbeddedDisplayIdList.add(displayId);
|
||||
}
|
||||
|
||||
void notifyDisplayReparented(int embeddedDisplayId) {
|
||||
// Notifies the A11y framework the display is reparented and
|
||||
// becomes an embedded display for removing the un-used
|
||||
// displayWindowObserver of this embedded one.
|
||||
mCallback.onDisplayReparented(embeddedDisplayId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if windows have changed, and send them to the accessibility subsystem if they have.
|
||||
*
|
||||
|
||||
@@ -115,6 +115,16 @@ public abstract class WindowManagerInternal {
|
||||
*/
|
||||
void onWindowsForAccessibilityChanged(boolean forceSend, int topFocusedDisplayId,
|
||||
IBinder topFocusedWindowToken, @NonNull List<WindowInfo> windows);
|
||||
|
||||
/**
|
||||
* Called when the display is reparented and becomes an embedded
|
||||
* display. The {@link WindowsForAccessibilityCallback} with the given embedded
|
||||
* display will be replaced by the {@link WindowsForAccessibilityCallback}
|
||||
* associated with its parent display at the same time.
|
||||
*
|
||||
* @param embeddedDisplayId The embedded display Id.
|
||||
*/
|
||||
void onDisplayReparented(int embeddedDisplayId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -834,6 +834,19 @@ public class AccessibilityWindowManagerTest {
|
||||
assertNull(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDisplayReparented_shouldRemoveObserver() throws RemoteException {
|
||||
// Starts tracking window of second display.
|
||||
startTrackingPerDisplay(SECONDARY_DISPLAY_ID);
|
||||
assertTrue(mA11yWindowManager.isTrackingWindowsLocked(SECONDARY_DISPLAY_ID));
|
||||
// Notifies the second display is an embedded one of the default display.
|
||||
final WindowsForAccessibilityCallback callbacks =
|
||||
mCallbackOfWindows.get(Display.DEFAULT_DISPLAY);
|
||||
callbacks.onDisplayReparented(SECONDARY_DISPLAY_ID);
|
||||
// Makes sure the observer of the second display is removed.
|
||||
assertFalse(mA11yWindowManager.isTrackingWindowsLocked(SECONDARY_DISPLAY_ID));
|
||||
}
|
||||
|
||||
private void registerLeashedTokenAndWindowId() {
|
||||
mA11yWindowManager.registerIdLocked(mMockHostToken, HOST_WINDOW_ID);
|
||||
mA11yWindowManager.registerIdLocked(mMockEmbeddedToken, EMBEDDED_WINDOW_ID);
|
||||
|
||||
Reference in New Issue
Block a user