Implementing new API : getWindowsOnAllDisplays()

1. Implementing the new API for supporting multi-display.
SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays()
2. Modifying the documents of this API and its function is to get the window lists of
default display.
List<AccessibilityWindowInfo> getWindows()

Bug: 133279356
Test: a11y CTS & unit tests
Change-Id: Id4e874f43390bdf4196d106a44bbca18bf9fd1d6
diff --git a/api/current.txt b/api/current.txt
index eeaabf6..e2d3b87 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2833,6 +2833,7 @@
     method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
     method @NonNull public final android.accessibilityservice.AccessibilityService.SoftKeyboardController getSoftKeyboardController();
     method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
+    method @NonNull public final android.util.SparseArray<java.util.List<android.view.accessibility.AccessibilityWindowInfo>> getWindowsOnAllDisplays();
     method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public final android.os.IBinder onBind(android.content.Intent);
     method @Deprecated protected boolean onGesture(int);
@@ -6362,6 +6363,7 @@
     method public android.view.WindowAnimationFrameStats getWindowAnimationFrameStats();
     method public android.view.WindowContentFrameStats getWindowContentFrameStats(int);
     method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
+    method @NonNull public android.util.SparseArray<java.util.List<android.view.accessibility.AccessibilityWindowInfo>> getWindowsOnAllDisplays();
     method public void grantRuntimePermission(String, String);
     method public void grantRuntimePermissionAsUser(String, String, android.os.UserHandle);
     method public boolean injectInputEvent(android.view.InputEvent, boolean);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index d3c274f..4603f08 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -605,7 +605,7 @@
     }
 
     /**
-     * Gets the windows on the screen. This method returns only the windows
+     * Gets the windows on the screen of the default display. This method returns only the windows
      * that a sighted user can interact with, as opposed to all windows.
      * For example, if there is a modal dialog shown and the user cannot touch
      * anything behind it, then only the modal window will be reported
@@ -632,6 +632,34 @@
     }
 
     /**
+     * Gets the windows on the screen of all displays. This method returns only the windows
+     * that a sighted user can interact with, as opposed to all windows.
+     * For example, if there is a modal dialog shown and the user cannot touch
+     * anything behind it, then only the modal window will be reported
+     * (assuming it is the top one). For convenience the returned windows
+     * are ordered in a descending layer order, which is the windows that
+     * are on top are reported first. Since the user can always
+     * interact with the window that has input focus by typing, the focused
+     * window is always returned (even if covered by a modal window).
+     * <p>
+     * <strong>Note:</strong> In order to access the windows your service has
+     * to declare the capability to retrieve window content by setting the
+     * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent}
+     * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
+     * Also the service has to opt-in to retrieve the interactive windows by
+     * setting the {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS}
+     * flag.
+     * </p>
+     *
+     * @return The windows of all displays if there are windows and the service is can retrieve
+     *         them, otherwise an empty list. The key of SparseArray is display ID.
+     */
+    @NonNull
+    public final SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays() {
+        return AccessibilityInteractionClient.getInstance().getWindowsOnAllDisplays(mConnectionId);
+    }
+
+    /**
      * Gets the root node in the currently active window if this service
      * can retrieve window content. The active window is the one that the user
      * is currently touching or the window with input focus, if the user is not
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 1ca07dd..4841781 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -60,7 +60,7 @@
 
     AccessibilityWindowInfo getWindow(int windowId);
 
-    List<AccessibilityWindowInfo> getWindows();
+    AccessibilityWindowInfo.WindowListSparseArray getWindows();
 
     AccessibilityServiceInfo getServiceInfo();
 
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index fd93450..13d566c 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -42,6 +42,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Log;
+import android.util.SparseArray;
 import android.view.Display;
 import android.view.InputEvent;
 import android.view.KeyEvent;
@@ -535,7 +536,7 @@
     }
 
     /**
-     * Gets the windows on the screen. This method returns only the windows
+     * Gets the windows on the screen of the default display. This method returns only the windows
      * that a sighted user can interact with, as opposed to all windows.
      * For example, if there is a modal dialog shown and the user cannot touch
      * anything behind it, then only the modal window will be reported
@@ -562,6 +563,35 @@
     }
 
     /**
+     * Gets the windows on the screen of all displays. This method returns only the windows
+     * that a sighted user can interact with, as opposed to all windows.
+     * For example, if there is a modal dialog shown and the user cannot touch
+     * anything behind it, then only the modal window will be reported
+     * (assuming it is the top one). For convenience the returned windows
+     * are ordered in a descending layer order, which is the windows that
+     * are higher in the Z-order are reported first.
+     * <p>
+     * <strong>Note:</strong> In order to access the windows you have to opt-in
+     * to retrieve the interactive windows by setting the
+     * {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS} flag.
+     * </p>
+     *
+     * @return The windows of all displays if there are windows and the service is can retrieve
+     *         them, otherwise an empty list. The key of SparseArray is display ID.
+     */
+    @NonNull
+    public SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays() {
+        final int connectionId;
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+            connectionId = mConnectionId;
+        }
+        // Calling out without a lock held.
+        return AccessibilityInteractionClient.getInstance()
+                .getWindowsOnAllDisplays(connectionId);
+    }
+
+    /**
      * Gets the root {@link AccessibilityNodeInfo} in the active window.
      *
      * @return The root info.
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index d9fa9f2..bb10ef1 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -259,23 +259,38 @@
     }
 
     /**
-     * Gets the info for all windows.
+     * Gets the info for all windows of the default display.
      *
      * @param connectionId The id of a connection for interacting with the system.
      * @return The {@link AccessibilityWindowInfo} list.
      */
     public List<AccessibilityWindowInfo> getWindows(int connectionId) {
+        final SparseArray<List<AccessibilityWindowInfo>> windows =
+                getWindowsOnAllDisplays(connectionId);
+        if (windows.size() > 0) {
+            return windows.valueAt(Display.DEFAULT_DISPLAY);
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * Gets the info for all windows of all displays.
+     *
+     * @param connectionId The id of a connection for interacting with the system.
+     * @return The SparseArray of {@link AccessibilityWindowInfo} list.
+     *         The key of SparseArray is display ID.
+     */
+    public SparseArray<List<AccessibilityWindowInfo>> getWindowsOnAllDisplays(int connectionId) {
         try {
             IAccessibilityServiceConnection connection = getConnection(connectionId);
             if (connection != null) {
-                SparseArray<List<AccessibilityWindowInfo>> allWindows =
+                SparseArray<List<AccessibilityWindowInfo>> windows =
                         sAccessibilityCache.getWindowsOnAllDisplays();
-                List<AccessibilityWindowInfo> windows;
-                if (allWindows != null) {
+                if (windows != null) {
                     if (DEBUG) {
                         Log.i(LOG_TAG, "Windows cache hit");
                     }
-                    return allWindows.valueAt(Display.DEFAULT_DISPLAY);
+                    return windows;
                 }
                 if (DEBUG) {
                     Log.i(LOG_TAG, "Windows cache miss");
@@ -287,9 +302,7 @@
                     Binder.restoreCallingIdentity(identityToken);
                 }
                 if (windows != null) {
-                    allWindows = new SparseArray<>();
-                    allWindows.put(Display.DEFAULT_DISPLAY, windows);
-                    sAccessibilityCache.setWindowsOnAllDisplays(allWindows);
+                    sAccessibilityCache.setWindowsOnAllDisplays(windows);
                     return windows;
                 }
             } else {
@@ -298,9 +311,11 @@
                 }
             }
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error while calling remote getWindows", re);
+            Log.e(LOG_TAG, "Error while calling remote getWindowsOnAllDisplays", re);
         }
-        return Collections.emptyList();
+
+        final SparseArray<List<AccessibilityWindowInfo>> emptyWindows = new SparseArray<>();
+        return emptyWindows;
     }
 
     /**
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.aidl b/core/java/android/view/accessibility/AccessibilityWindowInfo.aidl
index fdb25fb..c36c4aa 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.aidl
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.aidl
@@ -17,3 +17,4 @@
 package android.view.accessibility;
 
 parcelable AccessibilityWindowInfo;
+parcelable AccessibilityWindowInfo.WindowListSparseArray;
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index 6a3af34..5fa8a6e 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -26,9 +26,12 @@
 import android.text.TextUtils;
 import android.util.LongArray;
 import android.util.Pools.SynchronizedPool;
+import android.util.SparseArray;
 import android.view.Display;
 import android.view.accessibility.AccessibilityEvent.WindowsChangeTypes;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -797,4 +800,49 @@
             return new AccessibilityWindowInfo[size];
         }
     };
+
+    /**
+     * Transfers a sparsearray with lists having {@link AccessibilityWindowInfo}s across an IPC.
+     * The key of this sparsearray is display Id.
+     *
+     * @hide
+     */
+    public static final class WindowListSparseArray
+            extends SparseArray<List<AccessibilityWindowInfo>> implements Parcelable {
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            final int count = size();
+            dest.writeInt(count);
+            for (int i = 0; i < count; i++) {
+                dest.writeParcelableList(valueAt(i), 0);
+                dest.writeInt(keyAt(i));
+            }
+        }
+
+        public static final Parcelable.Creator<WindowListSparseArray> CREATOR =
+                new Parcelable.Creator<WindowListSparseArray>() {
+            public WindowListSparseArray createFromParcel(
+                    Parcel source) {
+                final WindowListSparseArray array = new WindowListSparseArray();
+                final ClassLoader loader = array.getClass().getClassLoader();
+                final int count = source.readInt();
+                for (int i = 0; i < count; i++) {
+                    List<AccessibilityWindowInfo> windows = new ArrayList<>();
+                    source.readParcelableList(windows, loader);
+                    array.put(source.readInt(), windows);
+                }
+                return array;
+            }
+
+            public WindowListSparseArray[] newArray(int size) {
+                return new WindowListSparseArray[size];
+            }
+        };
+    }
 }
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
index 682416c..3586216a 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
@@ -23,8 +23,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 
-import java.util.List;
-
 /**
  * Stub implementation of IAccessibilityServiceConnection so each test doesn't need to implement
  * all of the methods
@@ -73,7 +71,7 @@
         return null;
     }
 
-    public List<AccessibilityWindowInfo> getWindows() {
+    public AccessibilityWindowInfo.WindowListSparseArray getWindows() {
         return null;
     }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 4f021ad..514eb77 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -350,9 +350,9 @@
 
     protected abstract boolean hasRightsToCurrentUserLocked();
 
+    @Nullable
     @Override
-    public List<AccessibilityWindowInfo> getWindows() {
-        ensureWindowsAvailableTimed(Display.DEFAULT_DISPLAY);
+    public AccessibilityWindowInfo.WindowListSparseArray getWindows() {
         synchronized (mLock) {
             if (!hasRightsToCurrentUserLocked()) {
                 return null;
@@ -362,38 +362,39 @@
             if (!permissionGranted) {
                 return null;
             }
-            List<AccessibilityWindowInfo> internalWindowList =
-                    mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY);
-            if (internalWindowList == null) {
-                return null;
-            }
             if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
                 return null;
             }
-            List<AccessibilityWindowInfo> returnedWindowList = new ArrayList<>();
-            final int windowCount = internalWindowList.size();
-            for (int i = 0; i < windowCount; i++) {
-                AccessibilityWindowInfo window = internalWindowList.get(i);
-                AccessibilityWindowInfo windowClone =
-                        AccessibilityWindowInfo.obtain(window);
-                windowClone.setConnectionId(mId);
-                returnedWindowList.add(windowClone);
+            final AccessibilityWindowInfo.WindowListSparseArray allWindows =
+                    new AccessibilityWindowInfo.WindowListSparseArray();
+            final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked();
+            final int displayListCounts = displayList.size();
+            if (displayListCounts > 0) {
+                for (int i = 0; i < displayListCounts; i++) {
+                    final int displayId = displayList.get(i);
+                    ensureWindowsAvailableTimedLocked(displayId);
+
+                    final List<AccessibilityWindowInfo> windowList = getWindowsByDisplayLocked(
+                            displayId);
+                    if (windowList != null) {
+                        allWindows.put(displayId, windowList);
+                    }
+                }
             }
-            return returnedWindowList;
+            return allWindows;
         }
     }
 
     @Override
     public AccessibilityWindowInfo getWindow(int windowId) {
-        int displayId = Display.INVALID_DISPLAY;
         synchronized (mLock) {
+            int displayId = Display.INVALID_DISPLAY;
             if (windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) {
                 displayId = mA11yWindowManager.getDisplayIdByUserIdAndWindowIdLocked(
                         mSystemSupport.getCurrentUserIdLocked(), windowId);
             }
-        }
-        ensureWindowsAvailableTimed(displayId);
-        synchronized (mLock) {
+            ensureWindowsAvailableTimedLocked(displayId);
+
             if (!hasRightsToCurrentUserLocked()) {
                 return null;
             }
@@ -1316,35 +1317,33 @@
      *
      * @param displayId The logical display id.
      */
-    private void ensureWindowsAvailableTimed(int displayId) {
-        synchronized (mLock) {
-            if (mA11yWindowManager.getWindowListLocked(displayId) != null) {
-                return;
-            }
-            // If we have no registered callback, update the state we
-            // we may have to register one but it didn't happen yet.
-            if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
-                // Invokes client change to make sure tracking window enabled.
-                mSystemSupport.onClientChangeLocked(false);
-            }
-            // We have no windows but do not care about them, done.
-            if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
-                return;
-            }
+    private void ensureWindowsAvailableTimedLocked(int displayId) {
+        if (mA11yWindowManager.getWindowListLocked(displayId) != null) {
+            return;
+        }
+        // If we have no registered callback, update the state we
+        // we may have to register one but it didn't happen yet.
+        if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
+            // Invokes client change to make sure tracking window enabled.
+            mSystemSupport.onClientChangeLocked(false);
+        }
+        // We have no windows but do not care about them, done.
+        if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
+            return;
+        }
 
-            // Wait for the windows with a timeout.
-            final long startMillis = SystemClock.uptimeMillis();
-            while (mA11yWindowManager.getWindowListLocked(displayId) == null) {
-                final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
-                final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis;
-                if (remainMillis <= 0) {
-                    return;
-                }
-                try {
-                    mLock.wait(remainMillis);
-                } catch (InterruptedException ie) {
-                    /* ignore */
-                }
+        // Wait for the windows with a timeout.
+        final long startMillis = SystemClock.uptimeMillis();
+        while (mA11yWindowManager.getWindowListLocked(displayId) == null) {
+            final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
+            final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis;
+            if (remainMillis <= 0) {
+                return;
+            }
+            try {
+                mLock.wait(remainMillis);
+            } catch (InterruptedException ie) {
+                /* ignore */
             }
         }
     }
@@ -1442,6 +1441,24 @@
                 interrogatingPid, interrogatingTid);
     }
 
+    private List<AccessibilityWindowInfo> getWindowsByDisplayLocked(int displayId) {
+        final List<AccessibilityWindowInfo> internalWindowList =
+                mA11yWindowManager.getWindowListLocked(displayId);
+        if (internalWindowList == null) {
+            return null;
+        }
+        final List<AccessibilityWindowInfo> returnedWindowList = new ArrayList<>();
+        final int windowCount = internalWindowList.size();
+        for (int i = 0; i < windowCount; i++) {
+            AccessibilityWindowInfo window = internalWindowList.get(i);
+            AccessibilityWindowInfo windowClone =
+                    AccessibilityWindowInfo.obtain(window);
+            windowClone.setConnectionId(mId);
+            returnedWindowList.add(windowClone);
+        }
+        return returnedWindowList;
+    }
+
     public ComponentName getComponentName() {
         return mComponentName;
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index 0038a27..cb858ac 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -1472,11 +1472,27 @@
     public int getDisplayIdByUserIdAndWindowIdLocked(int userId, int windowId) {
         final IBinder windowToken = getWindowTokenForUserAndWindowIdLocked(userId, windowId);
         final int displayId = mWindowManagerInternal.getDisplayIdForWindow(windowToken);
-
         return displayId;
     }
 
     /**
+     * Returns the display list including all displays which are tracking windows.
+     *
+     * @return The display list.
+     */
+    public ArrayList<Integer> getDisplayListLocked() {
+        final ArrayList<Integer> displayList = new ArrayList<>();
+        final int count = mDisplayWindowsObservers.size();
+        for (int i = 0; i < count; i++) {
+            final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
+            if (observer != null) {
+                displayList.add(observer.mDisplayId);
+            }
+        }
+        return displayList;
+    }
+
+    /**
      * Gets current input focused window token from window manager, and returns its windowId.
      *
      * @param userId The userId
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
index 73dcb98..43f251a 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
@@ -46,6 +46,7 @@
 import static org.hamcrest.Matchers.hasItems;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -140,6 +141,8 @@
     private final List<AccessibilityWindowInfo> mA11yWindowInfosOnSecondDisplay = new ArrayList<>();
     private Callable[] mFindA11yNodesFunctions;
     private Callable<Boolean> mPerformA11yAction;
+    private ArrayList<Integer> mDisplayList = new ArrayList<>(Arrays.asList(
+            Display.DEFAULT_DISPLAY, SECONDARY_DISPLAY_ID));
 
     // To mock package-private class.
     @Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
@@ -184,6 +187,7 @@
         addA11yWindowInfo(mA11yWindowInfos, PIP_WINDOWID, true, Display.DEFAULT_DISPLAY);
         addA11yWindowInfo(mA11yWindowInfosOnSecondDisplay, WINDOWID_ONSECONDDISPLAY, false,
                 SECONDARY_DISPLAY_ID);
+        when(mMockA11yWindowManager.getDisplayListLocked()).thenReturn(mDisplayList);
         when(mMockA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY))
                 .thenReturn(mA11yWindowInfos);
         when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID))
@@ -285,7 +289,14 @@
 
     @Test
     public void getWindows() {
-        assertThat(mServiceConnection.getWindows(), is(mA11yWindowInfos));
+        final AccessibilityWindowInfo.WindowListSparseArray allWindows =
+                mServiceConnection.getWindows();
+
+        assertEquals(2, allWindows.size());
+        assertThat(allWindows.get(Display.DEFAULT_DISPLAY), is(mA11yWindowInfos));
+        assertEquals(2, allWindows.get(Display.DEFAULT_DISPLAY).size());
+        assertThat(allWindows.get(SECONDARY_DISPLAY_ID), is(mA11yWindowInfosOnSecondDisplay));
+        assertEquals(1, allWindows.get(SECONDARY_DISPLAY_ID).size());
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
index b7b5a4e..b5e5deb 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
@@ -67,6 +67,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -104,6 +105,9 @@
     // List of callback, mapping from displayId -> callback.
     private final SparseArray<WindowsForAccessibilityCallback> mCallbackOfWindows =
             new SparseArray<>();
+    // List of display ID.
+    private final ArrayList<Integer> mExpectedDisplayList = new ArrayList<>(Arrays.asList(
+            Display.DEFAULT_DISPLAY, SECONDARY_DISPLAY_ID));
 
     private final MessageCapturingHandler mHandler = new MessageCapturingHandler(null);
 
@@ -692,6 +696,15 @@
         assertTrue(windowId >= 0);
     }
 
+    @Test
+    public void getDisplayList() throws RemoteException {
+        // Starts tracking window of second display.
+        startTrackingPerDisplay(SECONDARY_DISPLAY_ID);
+
+        final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked();
+        assertTrue(displayList.equals(mExpectedDisplayList));
+    }
+
     private void startTrackingPerDisplay(int displayId) throws RemoteException {
         ArrayList<WindowInfo> windowInfosForDisplay = new ArrayList<>();
         // Adds RemoteAccessibilityConnection into AccessibilityWindowManager, and copy