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

Commit eb1375c0 authored by Eugene Susla's avatar Eugene Susla
Browse files

Always propagate AccessibilityCache events

Bug: b/32642665
Test: Steps:
	- Retrieve root AccessibilityNodeInfo
	- Change text on its child TextView
	- Wait for a few seconds to let the AccessibilityEvent propagate to
    the AccessibilityCache
	- Get the child AccessibilityNodeInfo from the root, corresponding to
    that TextView, and ensure that it's updated to reflect the text
    change
Change-Id: Icbdb91803b646fa06aaf11996d350f6f65c1e809
parent 96b97d72
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -1531,8 +1531,9 @@ public abstract class AccessibilityService extends Service {
            mCaller.sendMessage(message);
        }

        public void onAccessibilityEvent(AccessibilityEvent event) {
            Message message = mCaller.obtainMessageO(DO_ON_ACCESSIBILITY_EVENT, event);
        public void onAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent) {
            Message message = mCaller.obtainMessageBO(
                    DO_ON_ACCESSIBILITY_EVENT, serviceWantsEvent, event);
            mCaller.sendMessage(message);
        }

@@ -1581,9 +1582,14 @@ public abstract class AccessibilityService extends Service {
            switch (message.what) {
                case DO_ON_ACCESSIBILITY_EVENT: {
                    AccessibilityEvent event = (AccessibilityEvent) message.obj;
                    boolean serviceWantsEvent = message.arg1 != 0;
                    if (event != null) {
                        // Send the event to AccessibilityCache via AccessibilityInteractionClient
                        AccessibilityInteractionClient.getInstance().onAccessibilityEvent(event);
                        if (serviceWantsEvent) {
                            // Send the event to AccessibilityService
                            mCallback.onAccessibilityEvent(event);
                        }
                        // Make sure the event is recycled.
                        try {
                            event.recycle();
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ import android.view.KeyEvent;

    void init(in IAccessibilityServiceConnection connection, int connectionId, IBinder windowToken);

    void onAccessibilityEvent(in AccessibilityEvent event);
    void onAccessibilityEvent(in AccessibilityEvent event, in boolean serviceWantsEvent);

    void onInterrupt();

+23 −0
Original line number Diff line number Diff line
@@ -42,6 +42,26 @@ public final class AccessibilityCache {

    private static final boolean CHECK_INTEGRITY = "eng".equals(Build.TYPE);

    /**
     * {@link AccessibilityEvent} types that are critical for the cache to stay up to date
     *
     * When adding new event types in {@link #onAccessibilityEvent}, please add it here also, to
     * make sure that the events are delivered to cache regardless of
     * {@link android.accessibilityservice.AccessibilityServiceInfo#eventTypes}
     */
    public static final int CACHE_CRITICAL_EVENTS_MASK =
            AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
                    | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
                    | AccessibilityEvent.TYPE_VIEW_FOCUSED
                    | AccessibilityEvent.TYPE_VIEW_SELECTED
                    | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
                    | AccessibilityEvent.TYPE_VIEW_CLICKED
                    | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
                    | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
                    | AccessibilityEvent.TYPE_VIEW_SCROLLED
                    | AccessibilityEvent.TYPE_WINDOWS_CHANGED
                    | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;

    private final Object mLock = new Object();

    private final AccessibilityNodeRefresher mAccessibilityNodeRefresher;
@@ -100,6 +120,9 @@ public final class AccessibilityCache {
     * Notifies the cache that the something in the UI changed. As a result
     * the cache will either refresh some nodes or evict some nodes.
     *
     * Note: any event that ends up affecting the cache should also be present in
     * {@link #CACHE_CRITICAL_EVENTS_MASK}
     *
     * @param event An event.
     */
    public void onAccessibilityEvent(AccessibilityEvent event) {
+19 −8
Original line number Diff line number Diff line
@@ -78,10 +78,10 @@ import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
import android.view.MotionEvent;
import android.view.WindowInfo;
import android.view.WindowManager;
import android.view.WindowManagerInternal;
import android.view.accessibility.AccessibilityCache;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityManager;
@@ -1151,8 +1151,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
                Service service = state.mBoundServices.get(i);

                if (service.mIsDefault == isDefault) {
                    if (canDispatchEventToServiceLocked(service, event)) {
                        service.notifyAccessibilityEvent(event);
                    if (doesServiceWantEventLocked(service, event)) {
                        service.notifyAccessibilityEvent(event, true);
                    } else if ((AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK
                            & event.getEventType()) != 0) {
                        service.notifyAccessibilityEvent(event, false);
                    }
                }
            }
@@ -1201,7 +1204,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
     * @param event The event.
     * @return True if the listener should be notified, false otherwise.
     */
    private boolean canDispatchEventToServiceLocked(Service service, AccessibilityEvent event) {
    private boolean doesServiceWantEventLocked(Service service, AccessibilityEvent event) {

        if (!service.canReceiveEventsLocked()) {
            return false;
@@ -2285,7 +2288,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
            public void handleMessage(Message message) {
                final int eventType =  message.what;
                AccessibilityEvent event = (AccessibilityEvent) message.obj;
                notifyAccessibilityEventInternal(eventType, event);
                boolean serviceWantsEvent = message.arg1 != 0;
                notifyAccessibilityEventInternal(eventType, event, serviceWantsEvent);
            }
        };

@@ -3200,8 +3204,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
         * Performs a notification for an {@link AccessibilityEvent}.
         *
         * @param event The event.
         * @param serviceWantsEvent whether the event should be received by
         *  {@link AccessibilityService#onAccessibilityEvent} (true),
         *  as opposed to just {@link AccessibilityInteractionClient#onAccessibilityEvent} (false)
         */
        public void notifyAccessibilityEvent(AccessibilityEvent event) {
        public void notifyAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent) {
            synchronized (mLock) {
                final int eventType = event.getEventType();
                // Make a copy since during dispatch it is possible the event to
@@ -3223,6 +3230,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
                    // Send all messages, bypassing mPendingEvents
                    message = mEventDispatchHandler.obtainMessage(eventType, newEvent);
                }
                message.arg1 = serviceWantsEvent ? 1 : 0;

                mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
            }
@@ -3233,7 +3241,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
         *
         * @param eventType The type of the event to dispatch.
         */
        private void notifyAccessibilityEventInternal(int eventType, AccessibilityEvent event) {
        private void notifyAccessibilityEventInternal(
                int eventType,
                AccessibilityEvent event,
                boolean serviceWantsEvent) {
            IAccessibilityServiceClient listener;

            synchronized (mLock) {
@@ -3280,7 +3291,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
            }

            try {
                listener.onAccessibilityEvent(event);
                listener.onAccessibilityEvent(event, serviceWantsEvent);
                if (DEBUG) {
                    Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
                }