Don't allow to create a window in an unassigned display.

In MUMD (Multiple Users on Multiple Displays) environment, activities
can be launched in the displays to which the user is assigned. But
it is blocked to launch activities to unassigned displays.
Similar to the activity, this patch prevent system alert windows,
toast window and dialog from being shown in the unassigned displays.

Bug: 312321592
Test: atest WindowManagerServiceTests

(cherry picked from https://partner-android-review.googlesource.com/q/commit:e9da1c235fe75621693fa05aa1cdbb3638feac02)
Change-Id: Ia88006b2ffee5d342535b26f2ad3e698bd6604c1
Signed-off-by: Dohyun Lee <[email protected]>
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index fe280cb..0de0e57 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2705,7 +2705,11 @@
      * Returns true if the specified UID has access to this display.
      */
     boolean hasAccess(int uid) {
-        return mDisplay.hasAccess(uid);
+        int userId = UserHandle.getUserId(uid);
+        boolean isUserVisibleOnDisplay = mWmService.mUmInternal.isUserVisible(
+                userId, mDisplayId);
+        return mDisplay.hasAccess(uid)
+                && (userId == UserHandle.USER_SYSTEM || isUserVisibleOnDisplay);
     }
 
     boolean isPrivate() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index e113547..79ca2cf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -101,6 +101,7 @@
 import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerGlobal;
 import android.window.ActivityWindowInfo;
 import android.window.ClientWindowFrames;
 import android.window.InputTransferToken;
@@ -555,6 +556,7 @@
                 .hasListener(eq(windowContextToken));
         doReturn(TYPE_INPUT_METHOD).when(mWm.mWindowContextListenerController)
                 .getWindowType(eq(windowContextToken));
+        doReturn(true).when(mWm.mUmInternal).isUserVisible(anyInt(), anyInt());
 
         mWm.addWindow(session, new TestIWindow(), params, View.VISIBLE, DEFAULT_DISPLAY,
                 UserHandle.USER_SYSTEM, WindowInsets.Type.defaultVisible(), null, new InsetsState(),
@@ -1276,6 +1278,24 @@
         assertEquals(win.mActivityRecord.getActivityWindowInfo(), activityWindowInfo);
     }
 
+    @Test
+    public void testAddOverlayWindowToUnassignedDisplay_notAllowed() {
+        int uid = 100000; // uid for non-system user
+        Session session = createTestSession(mAtm, 1234 /* pid */, uid);
+        DisplayContent dc = createNewDisplay();
+        int displayId = dc.getDisplayId();
+        int userId = UserHandle.getUserId(uid);
+        doReturn(false).when(mWm.mUmInternal).isUserVisible(eq(userId), eq(displayId));
+        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+                LayoutParams.TYPE_APPLICATION_OVERLAY);
+
+        int result = mWm.addWindow(session, new TestIWindow(), params, View.VISIBLE, displayId,
+                userId, WindowInsets.Type.defaultVisible(), null, new InsetsState(),
+                new InsetsSourceControl.Array(), new Rect(), new float[1]);
+
+        assertThat(result).isEqualTo(WindowManagerGlobal.ADD_INVALID_DISPLAY);
+    }
+
     class TestResultReceiver implements IResultReceiver {
         public android.os.Bundle resultData;
         private final IBinder mBinder = mock(IBinder.class);