Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b5e81f2 authored by Ryan Lin's avatar Ryan Lin Committed by Automerger Merge Worker
Browse files

Merge "Postpone window_state_changed events until the window is added" into...

Merge "Postpone window_state_changed events until the window is added" into tm-dev am: 857459ff am: 4db5aded

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17741153



Change-Id: I51c4ab30cf5cd7dbf29d5078813514d46d0d5015
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 4f07b767 4db5aded
Loading
Loading
Loading
Loading
+91 −3
Original line number Original line Diff line number Diff line
@@ -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;
        }
    }
}
}