summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ryan Lin <ryanlwlin@google.com> 2022-05-04 04:35:41 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2022-05-04 04:35:41 +0000
commit7b5e81f2980174e2583a874c19daa611779c958b (patch)
tree7cc60ce263c82cf242fab5d06895cd099dba30b6
parent4f07b7672df61f3d5b591471601c9bc91600f15c (diff)
parent4db5adedbd329030662748a1457278fc83fac90e (diff)
Merge "Postpone window_state_changed events until the window is added" into tm-dev am: 857459ff56 am: 4db5adedbd
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17741153 Change-Id: I51c4ab30cf5cd7dbf29d5078813514d46d0d5015 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java94
1 files changed, 91 insertions, 3 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index cbeb01a68778..4806514a0e13 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -187,6 +187,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
// their capabilities are ready.
private static final int WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS = 1000;
+
+ // This postpones state changes events when a window doesn't exist with the expectation that
+ // a race condition will resolve. It is determined by observing elapsed time of the
+ // corresponding window added.
+ //TODO(b/230810909) : Fix it with a better idea.
+ private static final int POSTPONE_WINDOW_STATE_CHANGED_EVENT_TIMEOUT_MILLIS = 500;
+
private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE =
"registerUiTestAutomationService";
@@ -272,6 +279,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private final AccessibilityTraceManager mTraceManager;
private final CaptioningManagerImpl mCaptioningManagerImpl;
+ private final List<SendWindowStateChangedEventRunnable> mSendWindowStateChangedEventRunnables =
+ new ArrayList<>();
+
private int mCurrentUserId = UserHandle.USER_SYSTEM;
//TODO: Remove this hack
@@ -930,11 +940,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
final WindowManagerInternal wm = LocalServices.getService(
WindowManagerInternal.class);
wm.computeWindowsForAccessibility(displayId);
+ // The App side sends a event to notify that the window visible or focused,
+ // but the window information in framework is not updated yet, so we postpone it.
+ if (postponeWindowStateEvent(event)) {
+ return;
+ }
}
+
synchronized (mLock) {
- notifyAccessibilityServicesDelayedLocked(event, false);
- notifyAccessibilityServicesDelayedLocked(event, true);
- mUiAutomationManager.sendAccessibilityEventLocked(event);
+ dispatchAccessibilityEventLocked(event);
}
}
@@ -943,6 +957,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
}
+ private void dispatchAccessibilityEventLocked(AccessibilityEvent event) {
+ notifyAccessibilityServicesDelayedLocked(event, false);
+ notifyAccessibilityServicesDelayedLocked(event, true);
+ mUiAutomationManager.sendAccessibilityEventLocked(event);
+ }
+
private void sendAccessibilityEventToInputFilter(AccessibilityEvent event) {
synchronized (mLock) {
if (mHasInputFilter && mInputFilter != null) {
@@ -3339,6 +3359,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
@Override
public void sendAccessibilityEventForCurrentUserLocked(AccessibilityEvent event) {
+ if (event.getWindowChanges() == AccessibilityEvent.WINDOWS_CHANGE_ADDED) {
+ // We need to ensure the window is available before sending pending
+ // window_state_changed events.
+ sendPendingWindowStateChangedEventsForAvailableWindowLocked(event.getWindowId());
+ }
sendAccessibilityEventLocked(event, mCurrentUserId);
}
@@ -4505,4 +4530,67 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
}
}
+
+ private final class SendWindowStateChangedEventRunnable implements Runnable {
+
+ private final AccessibilityEvent mPendingEvent;
+ private final int mWindowId;
+
+ SendWindowStateChangedEventRunnable(@NonNull AccessibilityEvent event) {
+ mPendingEvent = event;
+ mWindowId = event.getWindowId();
+ }
+
+ @Override
+ public void run() {
+ synchronized (mLock) {
+ Slog.w(LOG_TAG, " wait for adding window timeout: " + mWindowId);
+ sendPendingEventLocked();
+ }
+ }
+
+ private void sendPendingEventLocked() {
+ mSendWindowStateChangedEventRunnables.remove(this);
+ dispatchAccessibilityEventLocked(mPendingEvent);
+ }
+
+ private int getWindowId() {
+ return mWindowId;
+ }
+ }
+
+ void sendPendingWindowStateChangedEventsForAvailableWindowLocked(int windowId) {
+ final int eventSize = mSendWindowStateChangedEventRunnables.size();
+ for (int i = eventSize - 1; i >= 0; i--) {
+ final SendWindowStateChangedEventRunnable runnable =
+ mSendWindowStateChangedEventRunnables.get(i);
+ if (runnable.getWindowId() == windowId) {
+ mMainHandler.removeCallbacks(runnable);
+ runnable.sendPendingEventLocked();
+ }
+ }
+ }
+
+ /**
+ * Postpones the {@link AccessibilityEvent} with
+ * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}
+ * which doesn't have the corresponding window until the window is added or timeout.
+ *
+ * @return {@code true} if the event is postponed.
+ */
+ private boolean postponeWindowStateEvent(AccessibilityEvent event) {
+ synchronized (mLock) {
+ final int resolvedWindowId = mA11yWindowManager.resolveParentWindowIdLocked(
+ event.getWindowId());
+ if (mA11yWindowManager.findWindowInfoByIdLocked(resolvedWindowId) != null) {
+ return false;
+ }
+ final SendWindowStateChangedEventRunnable pendingRunnable =
+ new SendWindowStateChangedEventRunnable(new AccessibilityEvent(event));
+ mMainHandler.postDelayed(pendingRunnable,
+ POSTPONE_WINDOW_STATE_CHANGED_EVENT_TIMEOUT_MILLIS);
+ mSendWindowStateChangedEventRunnables.add(pendingRunnable);
+ return true;
+ }
+ }
}