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

Commit 9dffffc9 authored by Sally Yuen's avatar Sally Yuen Committed by Android (Google) Code Review
Browse files

Merge "Query the cache for AccessibilityInteractionClient's findFocus"

parents 11df2ecd 5fe5f8b8
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -151,7 +151,8 @@ public final class AccessibilityInteractionController {
            if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId
                    && mHandler.hasAccessibilityCallback(message)) {
                AccessibilityInteractionClient.getInstanceForThread(
                        interrogatingTid).setSameThreadMessage(message);
                        interrogatingTid, /* initializeCache= */true)
                        .setSameThreadMessage(message);
            } else {
                // For messages without callback of interrogating client, just handle the
                // message immediately if this is UI thread.
+88 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package android.view.accessibility;


import static android.view.accessibility.AccessibilityNodeInfo.FOCUS_ACCESSIBILITY;

import android.os.Build;
import android.util.ArraySet;
import android.util.Log;
@@ -70,6 +73,7 @@ public class AccessibilityCache {
    private long mInputFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;

    private int mAccessibilityFocusedWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
    private int mInputFocusWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;

    private boolean mIsAllWindowsCached;

@@ -190,6 +194,7 @@ public class AccessibilityCache {
                        removeCachedNodeLocked(event.getWindowId(), mInputFocus);
                    }
                    mInputFocus = event.getSourceNodeId();
                    mInputFocusWindow = event.getWindowId();
                    nodeToRefresh = removeCachedNodeLocked(event.getWindowId(), mInputFocus);
                } break;

@@ -439,6 +444,7 @@ public class AccessibilityCache {
            }
            if (clone.isFocused()) {
                mInputFocus = sourceId;
                mInputFocusWindow = windowId;
            }
        }
    }
@@ -462,6 +468,7 @@ public class AccessibilityCache {
            mInputFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;

            mAccessibilityFocusedWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
            mInputFocusWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
        }
    }

@@ -485,6 +492,87 @@ public class AccessibilityCache {
        mIsAllWindowsCached = false;
    }

    /**
     * Gets a cached {@link AccessibilityNodeInfo} with focus according to focus type.
     *
     * Note: {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID} will return
     * null.
     *
     * @param focusType The focus type.
     * @param windowId A unique window id.
     * @param initialNodeId A unique view id or virtual descendant id from where to start the
     *                      search.
     * @return The cached {@link AccessibilityNodeInfo} if it has a11y focus or null if such not
     * found.
     */
    public AccessibilityNodeInfo getFocus(int focusType, long initialNodeId, int windowId) {
        synchronized (mLock) {
            int currentFocusWindowId;
            long currentFocusId;
            if (focusType == FOCUS_ACCESSIBILITY) {
                currentFocusWindowId = mAccessibilityFocusedWindow;
                currentFocusId = mAccessibilityFocus;
            } else {
                currentFocusWindowId = mInputFocusWindow;
                currentFocusId = mInputFocus;
            }

            if (currentFocusWindowId == AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) {
                return null;
            }

            if (windowId != AccessibilityWindowInfo.ANY_WINDOW_ID
                    && windowId != currentFocusWindowId) {
                return null;
            }

            LongSparseArray<AccessibilityNodeInfo> nodes =
                    mNodeCache.get(currentFocusWindowId);
            if (nodes == null) {
                return null;
            }

            final AccessibilityNodeInfo currentFocusedNode = nodes.get(currentFocusId);
            if (currentFocusedNode == null) {
                return null;
            }

            if (initialNodeId == currentFocusId || (isCachedNodeOrDescendantLocked(
                    currentFocusedNode.getParentNodeId(), initialNodeId, nodes))) {
                if (VERBOSE) {
                    Log.i(LOG_TAG, "getFocus(0x" + Long.toHexString(currentFocusId) + ") = "
                            + currentFocusedNode + " with type: "
                            + (focusType == FOCUS_ACCESSIBILITY
                            ? "FOCUS_ACCESSIBILITY"
                            : "FOCUS_INPUT"));
                }
                // Return a copy since the client calls to AccessibilityNodeInfo#recycle()
                // will wipe the data of the cached info.
                return new AccessibilityNodeInfo(currentFocusedNode);
            }

            if (VERBOSE) {
                Log.i(LOG_TAG, "getFocus is null with type: "
                        + (focusType == FOCUS_ACCESSIBILITY
                        ? "FOCUS_ACCESSIBILITY"
                        : "FOCUS_INPUT"));
            }
            return null;
        }
    }

    private boolean isCachedNodeOrDescendantLocked(long nodeId, long ancestorId,
            LongSparseArray<AccessibilityNodeInfo> nodes) {
        if (ancestorId == nodeId) {
            return true;
        }
        AccessibilityNodeInfo node = nodes.get(nodeId);
        if (node == null) {
            return false;
        }
        return isCachedNodeOrDescendantLocked(node.getParentNodeId(), ancestorId,  nodes);
    }

    /**
     * Clears nodes for the window with the given id
     */
+91 −30
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILIT
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
@@ -114,8 +115,7 @@ public final class AccessibilityInteractionClient
        from a window, mapping from windowId -> timestamp. */
    private static final SparseLongArray sScrollingWindows = new SparseLongArray();

    private static AccessibilityCache sAccessibilityCache =
            new AccessibilityCache(new AccessibilityCache.AccessibilityNodeRefresher());
    private static AccessibilityCache sAccessibilityCache;

    private final AtomicInteger mInteractionIdCounter = new AtomicInteger();

@@ -150,7 +150,7 @@ public final class AccessibilityInteractionClient
    @UnsupportedAppUsage()
    public static AccessibilityInteractionClient getInstance() {
        final long threadId = Thread.currentThread().getId();
        return getInstanceForThread(threadId);
        return getInstanceForThread(threadId, true);
    }

    /**
@@ -161,11 +161,17 @@ public final class AccessibilityInteractionClient
     *
     * @return The client for a given <code>threadId</code>.
     */
    public static AccessibilityInteractionClient getInstanceForThread(long threadId) {
    public static AccessibilityInteractionClient getInstanceForThread(long threadId,
            boolean initializeCache) {
        synchronized (sStaticLock) {
            AccessibilityInteractionClient client = sClients.get(threadId);
            if (client == null) {
                client = new AccessibilityInteractionClient();
                if (Binder.getCallingUid() == Process.SYSTEM_UID) {
                    // Don't initialize a cache for the system process
                    client = new AccessibilityInteractionClient(false);
                } else {
                    client = new AccessibilityInteractionClient(initializeCache);
                }
                sClients.put(threadId, client);
            }
            return client;
@@ -176,11 +182,20 @@ public final class AccessibilityInteractionClient
     * @return The client for the current thread.
     */
    public static AccessibilityInteractionClient getInstance(Context context) {
        return getInstance(/* initializeCache= */true, context);
    }

    /**
     * @param initializeCache whether to initialize the cache in a new client instance
     * @return The client for the current thread.
     */
    public static AccessibilityInteractionClient getInstance(boolean initializeCache,
            Context context) {
        final long threadId = Thread.currentThread().getId();
        if (context != null) {
            return getInstanceForThread(threadId, context);
            return getInstanceForThread(threadId, initializeCache, context);
        }
        return getInstanceForThread(threadId);
        return getInstanceForThread(threadId, initializeCache);
    }

    /**
@@ -189,14 +204,19 @@ public final class AccessibilityInteractionClient
     * We do not have a thread local variable since other threads should be able to
     * look up the correct client knowing a thread id. See ViewRootImpl for details.
     *
     * @param initializeCache whether to initialize the cache in a new client instance
     * @return The client for a given <code>threadId</code>.
     */
    public static AccessibilityInteractionClient getInstanceForThread(
            long threadId, Context context) {
            long threadId, boolean initializeCache, Context context) {
        synchronized (sStaticLock) {
            AccessibilityInteractionClient client = sClients.get(threadId);
            if (client == null) {
                client = new AccessibilityInteractionClient(context);
                if (Binder.getCallingUid() == Process.SYSTEM_UID) {
                    client = new AccessibilityInteractionClient(false, context);
                } else {
                    client = new AccessibilityInteractionClient(initializeCache, context);
                }
                sClients.put(threadId, client);
            }
            return client;
@@ -249,13 +269,26 @@ public final class AccessibilityInteractionClient

    private AccessibilityInteractionClient() {
        /* reducing constructor visibility */
        this(true);
    }

    private AccessibilityInteractionClient(boolean initializeCache) {
        initializeCache(initializeCache);
        mAccessibilityManager = null;
    }

    private AccessibilityInteractionClient(Context context) {
    private AccessibilityInteractionClient(boolean initializeCache, Context context) {
        initializeCache(initializeCache);
        mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
    }

    private static void initializeCache(boolean initialize) {
        if (initialize && sAccessibilityCache == null) {
            sAccessibilityCache = new AccessibilityCache(
                    new AccessibilityCache.AccessibilityNodeRefresher());
        }
    }

    /**
     * Sets the message to be processed if the interacted view hierarchy
     * and the interacting client are running in the same thread.
@@ -311,7 +344,7 @@ public final class AccessibilityInteractionClient
            IAccessibilityServiceConnection connection = getConnection(connectionId);
            if (connection != null) {
                AccessibilityWindowInfo window;
                if (!bypassCache) {
                if (!bypassCache && sAccessibilityCache != null) {
                    window = sAccessibilityCache.getWindow(accessibilityWindowId);
                    if (window != null) {
                        if (DEBUG) {
@@ -341,7 +374,7 @@ public final class AccessibilityInteractionClient
                            + bypassCache);
                }

                if (window != null) {
                if (window != null && sAccessibilityCache != null) {
                    if (!bypassCache) {
                        sAccessibilityCache.addWindow(window);
                    }
@@ -384,8 +417,9 @@ public final class AccessibilityInteractionClient
        try {
            IAccessibilityServiceConnection connection = getConnection(connectionId);
            if (connection != null) {
                SparseArray<List<AccessibilityWindowInfo>> windows =
                        sAccessibilityCache.getWindowsOnAllDisplays();
                SparseArray<List<AccessibilityWindowInfo>> windows;
                if (sAccessibilityCache != null) {
                    windows = sAccessibilityCache.getWindowsOnAllDisplays();
                    if (windows != null) {
                        if (DEBUG) {
                            Log.i(LOG_TAG, "Windows cache hit");
@@ -399,6 +433,8 @@ public final class AccessibilityInteractionClient
                    if (DEBUG) {
                        Log.i(LOG_TAG, "Windows cache miss");
                    }
                }

                final long identityToken = Binder.clearCallingIdentity();
                try {
                    windows = connection.getWindows();
@@ -409,7 +445,9 @@ public final class AccessibilityInteractionClient
                    logTraceClient(connection, "getWindows", "connectionId=" + connectionId);
                }
                if (windows != null) {
                    if (sAccessibilityCache != null) {
                        sAccessibilityCache.setWindowsOnAllDisplays(windows);
                    }
                    return windows;
                }
            } else {
@@ -493,7 +531,7 @@ public final class AccessibilityInteractionClient
        try {
            IAccessibilityServiceConnection connection = getConnection(connectionId);
            if (connection != null) {
                if (!bypassCache) {
                if (!bypassCache && sAccessibilityCache != null) {
                    AccessibilityNodeInfo cachedInfo = sAccessibilityCache.getNode(
                            accessibilityWindowId, accessibilityNodeId);
                    if (cachedInfo != null) {
@@ -725,7 +763,9 @@ public final class AccessibilityInteractionClient
     * @param connectionId The id of a connection for interacting with the system.
     * @param accessibilityWindowId A unique window id. Use
     *     {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
     *     to query the currently active window.
     *     to query the currently active window. Use
     *     {@link android.view.accessibility.AccessibilityWindowInfo#ANY_WINDOW_ID} to query all
     *     windows
     * @param accessibilityNodeId A unique view id or virtual descendant id from
     *     where to start the search. Use
     *     {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
@@ -733,11 +773,28 @@ public final class AccessibilityInteractionClient
     * @param focusType The focus type.
     * @return The accessibility focused {@link AccessibilityNodeInfo}.
     */
    @SuppressLint("LongLogTag")
    public AccessibilityNodeInfo findFocus(int connectionId, int accessibilityWindowId,
            long accessibilityNodeId, int focusType) {
        try {
            IAccessibilityServiceConnection connection = getConnection(connectionId);
            if (connection != null) {
                if (sAccessibilityCache != null) {
                    AccessibilityNodeInfo cachedInfo = sAccessibilityCache.getFocus(focusType,
                            accessibilityNodeId, accessibilityWindowId);
                    if (cachedInfo != null) {
                        if (DEBUG) {
                            Log.i(LOG_TAG, "Focused node cache hit retrieved"
                                    + idToString(cachedInfo.getWindowId(),
                                    cachedInfo.getSourceNodeId()));
                        }
                        return cachedInfo;
                    }
                    if (DEBUG) {
                        Log.i(LOG_TAG, "Focused node cache miss with "
                                + idToString(accessibilityWindowId, accessibilityNodeId));
                    }
                }
                final int interactionId = mInteractionIdCounter.getAndIncrement();
                if (shouldTraceClient()) {
                    logTraceClient(connection, "findFocus",
@@ -901,8 +958,10 @@ public final class AccessibilityInteractionClient
     */
    @UnsupportedAppUsage()
    public void clearCache() {
        if (sAccessibilityCache != null) {
            sAccessibilityCache.clear();
        }
    }

    public void onAccessibilityEvent(AccessibilityEvent event) {
        switch (event.getEventType()) {
@@ -917,8 +976,10 @@ public final class AccessibilityInteractionClient
            default:
                break;
        }
        if (sAccessibilityCache != null) {
            sAccessibilityCache.onAccessibilityEvent(event);
        }
    }

    /**
     * Gets the the result of an async request that returns an {@link AccessibilityNodeInfo}.
@@ -1153,7 +1214,7 @@ public final class AccessibilityInteractionClient
                }
            }
            info.setSealed(true);
            if (!bypassCache) {
            if (!bypassCache && sAccessibilityCache != null) {
                sAccessibilityCache.add(info);
            }
        }
+177 −0
Original line number Diff line number Diff line
@@ -16,6 +16,12 @@

package android.view.accessibility;

import static android.view.accessibility.AccessibilityNodeInfo.FOCUS_ACCESSIBILITY;
import static android.view.accessibility.AccessibilityNodeInfo.FOCUS_INPUT;
import static android.view.accessibility.AccessibilityNodeInfo.ROOT_ITEM_ID;
import static android.view.accessibility.AccessibilityNodeInfo.ROOT_NODE_ID;
import static android.view.accessibility.AccessibilityWindowInfo.ANY_WINDOW_ID;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
@@ -596,6 +602,97 @@ public class AccessibilityCacheTest {
        }
    }

    @Test
    public void getFocus_focusedNodeAsInitialNode_returnsNodeWithA11yFocus() {
        AccessibilityNodeInfo nodeInfo = addFocusedNode(FOCUS_ACCESSIBILITY);
        assertFocus(nodeInfo, FOCUS_ACCESSIBILITY, nodeInfo.getSourceNodeId(),
                nodeInfo.getWindowId());
    }

    @Test
    public void getFocus_focusedNodeAsInitialNode_returnsNodeWithInputFocus() {
        AccessibilityNodeInfo nodeInfo = addFocusedNode(FOCUS_INPUT);
        assertFocus(nodeInfo, FOCUS_INPUT, nodeInfo.getSourceNodeId(), nodeInfo.getWindowId());
    }


    @Test
    public void getFocus_fromAnyWindow_returnsNodeWithA11yFocus() {
        AccessibilityNodeInfo parentNodeInfo =
                getNodeWithA11yAndWindowId(ROOT_ITEM_ID, WINDOW_ID_1);
        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
        nodeInfo.setParent(getMockViewWithA11yAndWindowIds(ROOT_ITEM_ID, WINDOW_ID_1));
        setFocus(nodeInfo, FOCUS_ACCESSIBILITY);
        mAccessibilityCache.add(parentNodeInfo);
        mAccessibilityCache.add(nodeInfo);

        AccessibilityNodeInfo focusedNodeInfo =
                mAccessibilityCache.getFocus(FOCUS_ACCESSIBILITY, ROOT_NODE_ID, ANY_WINDOW_ID);
        try {
            assertEquals(focusedNodeInfo, nodeInfo);
        } finally {
            nodeInfo.recycle();
            parentNodeInfo.recycle();
        }
    }

    @Test
    public void getFocus_fromAnyWindow_returnsNodeWithInputFocus() {
        AccessibilityNodeInfo parentNodeInfo =
                getNodeWithA11yAndWindowId(ROOT_ITEM_ID, WINDOW_ID_1);
        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
        nodeInfo.setParent(getMockViewWithA11yAndWindowIds(ROOT_ITEM_ID, WINDOW_ID_1));
        setFocus(nodeInfo, FOCUS_INPUT);
        mAccessibilityCache.add(parentNodeInfo);
        mAccessibilityCache.add(nodeInfo);

        AccessibilityNodeInfo focusedNodeInfo =
                mAccessibilityCache.getFocus(FOCUS_INPUT, ROOT_NODE_ID, ANY_WINDOW_ID);
        try {
            assertEquals(focusedNodeInfo, nodeInfo);
        } finally {
            nodeInfo.recycle();
            parentNodeInfo.recycle();
        }
    }


    @Test
    public void getFocus_parentNodeAsInitialNode_returnsNodeWithA11yFocus() {
        findFocusReturnsFocus_initialNodeIsParent(FOCUS_ACCESSIBILITY);
    }

    @Test
    public void getFocus_parentNodeAsInitialNode_returnsNodeWithInputFocus() {
        findFocusReturnsFocus_initialNodeIsParent(FOCUS_INPUT);

    }

    @Test
    public void getFocus_nonFocusedChildNodeAsInitialNode_returnsNullA11yFocus() {
        findFocusReturnNull_initialNodeIsNotFocusOrFocusAncestor(FOCUS_ACCESSIBILITY);
    }

    @Test
    public void getFocus_nonFocusedChildNodeAsInitialNode_returnsNullInputFocus() {
        findFocusReturnNull_initialNodeIsNotFocusOrFocusAncestor(FOCUS_INPUT);
    }

    @Test
    public void getFocus_cacheCleared_returnsNullA11yFocus() {
        AccessibilityNodeInfo nodeInfo = addFocusedNode(FOCUS_ACCESSIBILITY);
        mAccessibilityCache.clear();
        assertFocus(null, FOCUS_ACCESSIBILITY, nodeInfo.getSourceNodeId(),
                nodeInfo.getWindowId());
    }

    @Test
    public void getFocus_cacheCleared_returnsNullInputFocus() {
        AccessibilityNodeInfo nodeInfo = addFocusedNode(FOCUS_INPUT);
        mAccessibilityCache.clear();
        assertFocus(null, FOCUS_INPUT, nodeInfo.getSourceNodeId(), nodeInfo.getWindowId());
    }

    @Test
    public void nodeSourceOfInputFocusEvent_getsRefreshed() {
        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
@@ -786,6 +883,86 @@ public class AccessibilityCacheTest {
        }
    }

    private AccessibilityNodeInfo addFocusedNode(int focusType) {
        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
        setFocus(nodeInfo, focusType);
        mAccessibilityCache.add(nodeInfo);
        return nodeInfo;
    }

    private void assertFocus(AccessibilityNodeInfo focus, int focusType, long nodeId,
            int windowId) {
        AccessibilityNodeInfo focusedNodeInfo = mAccessibilityCache.getFocus(
                focusType, nodeId, windowId);
        try {
            assertEquals(focusedNodeInfo, focus);
        } finally {
            if (focus != null) {
                focus.recycle();
            }
            if (focusedNodeInfo != null) {
                focusedNodeInfo.recycle();
            }
        }
    }


    private void findFocusReturnNull_initialNodeIsNotFocusOrFocusAncestor(int focusType) {
        AccessibilityNodeInfo parentNodeInfo =
                getNodeWithA11yAndWindowId(PARENT_VIEW_ID, WINDOW_ID_1);
        AccessibilityNodeInfo childNodeInfo =
                getNodeWithA11yAndWindowId(CHILD_VIEW_ID, WINDOW_ID_1);
        AccessibilityNodeInfo otherChildNodeInfo =
                getNodeWithA11yAndWindowId(OTHER_CHILD_VIEW_ID, WINDOW_ID_1);
        childNodeInfo.setParent(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1));
        otherChildNodeInfo.setParent(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1));
        setFocus(childNodeInfo, focusType);
        mAccessibilityCache.add(parentNodeInfo);
        mAccessibilityCache.add(childNodeInfo);
        mAccessibilityCache.add(otherChildNodeInfo);

        AccessibilityNodeInfo focusedNodeInfo = mAccessibilityCache.getFocus(
                focusType, otherChildNodeInfo.getSourceNodeId(), WINDOW_ID_1);

        try {
            assertNull(focusedNodeInfo);

        } finally {
            parentNodeInfo.recycle();
            childNodeInfo.recycle();
        }
    }

    private void findFocusReturnsFocus_initialNodeIsParent(int focusType) {
        AccessibilityNodeInfo parentNodeInfo =
                getNodeWithA11yAndWindowId(PARENT_VIEW_ID, WINDOW_ID_1);
        AccessibilityNodeInfo childNodeInfo =
                getNodeWithA11yAndWindowId(CHILD_VIEW_ID, WINDOW_ID_1);
        childNodeInfo.setParent(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1));
        setFocus(childNodeInfo, focusType);
        mAccessibilityCache.add(parentNodeInfo);
        mAccessibilityCache.add(childNodeInfo);

        AccessibilityNodeInfo focusedNodeInfo = mAccessibilityCache.getFocus(
                focusType, parentNodeInfo.getSourceNodeId(), WINDOW_ID_1);

        try {
            assertEquals(focusedNodeInfo, childNodeInfo);

        } finally {
            parentNodeInfo.recycle();
            childNodeInfo.recycle();
        }
    }

    private void setFocus(AccessibilityNodeInfo info, int focusType) {
        if (focusType == FOCUS_ACCESSIBILITY) {
            info.setAccessibilityFocused(true);
        } else {
            info.setFocused(true);
        }
    }

    private AccessibilityWindowInfo obtainAccessibilityWindowInfo(int windowId, int layer) {
        AccessibilityWindowInfo windowInfo = AccessibilityWindowInfo.obtain();
        windowInfo.setId(windowId);
+2 −1
Original line number Diff line number Diff line
@@ -3432,7 +3432,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub

            mConnectionId = service.mId;

            mClient = AccessibilityInteractionClient.getInstance(mContext);
            mClient = AccessibilityInteractionClient.getInstance(/* initializeCache= */false,
                    mContext);
            mClient.addConnection(mConnectionId, service);

            //TODO: (multi-display) We need to support multiple displays.