Merge "Postpone window_state_changed events until the window is added" into tm-dev
This commit is contained in:
@@ -187,6 +187,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
|||||||
// their capabilities are ready.
|
// their capabilities are ready.
|
||||||
private static final int WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS = 1000;
|
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 =
|
private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE =
|
||||||
"registerUiTestAutomationService";
|
"registerUiTestAutomationService";
|
||||||
|
|
||||||
@@ -272,6 +279,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
|||||||
private final AccessibilityTraceManager mTraceManager;
|
private final AccessibilityTraceManager mTraceManager;
|
||||||
private final CaptioningManagerImpl mCaptioningManagerImpl;
|
private final CaptioningManagerImpl mCaptioningManagerImpl;
|
||||||
|
|
||||||
|
private final List<SendWindowStateChangedEventRunnable> mSendWindowStateChangedEventRunnables =
|
||||||
|
new ArrayList<>();
|
||||||
|
|
||||||
private int mCurrentUserId = UserHandle.USER_SYSTEM;
|
private int mCurrentUserId = UserHandle.USER_SYSTEM;
|
||||||
|
|
||||||
//TODO: Remove this hack
|
//TODO: Remove this hack
|
||||||
@@ -930,11 +940,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
|||||||
final WindowManagerInternal wm = LocalServices.getService(
|
final WindowManagerInternal wm = LocalServices.getService(
|
||||||
WindowManagerInternal.class);
|
WindowManagerInternal.class);
|
||||||
wm.computeWindowsForAccessibility(displayId);
|
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) {
|
synchronized (mLock) {
|
||||||
notifyAccessibilityServicesDelayedLocked(event, false);
|
dispatchAccessibilityEventLocked(event);
|
||||||
notifyAccessibilityServicesDelayedLocked(event, true);
|
|
||||||
mUiAutomationManager.sendAccessibilityEventLocked(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) {
|
private void sendAccessibilityEventToInputFilter(AccessibilityEvent event) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mHasInputFilter && mInputFilter != null) {
|
if (mHasInputFilter && mInputFilter != null) {
|
||||||
@@ -3339,6 +3359,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendAccessibilityEventForCurrentUserLocked(AccessibilityEvent event) {
|
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);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user