Make per-display focus optional (1/2)

In general cases, we don't have multiple input methods simultaneously.
So that it may not make sense to have multiple focused window in the
system. Especially when there are multiple blinking cursors of input
boxes on different displays, the user may not be able to know which
input box can receive key events. In these cases, we let the system
has only one focused window.

In some cases, there can be multiple input methods simultaneously (one
for each display). To enable multiple users to interact with the
corresponding displays at the same time, we should let the system have
per-display focused window in these cases.

This CL makes per-display focus optional, and also reverts ag/5312657

Fix: 120241480
Fix: 120790099
Test: atest ActivityManagerMultiDisplayTests \
            CtsWindowManagerDeviceTestCases \
            WmTests

Change-Id: Ie030eed523599b217060887171710692d050e5d8
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 7c83ecc..8430616 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -19,6 +19,8 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.os.Build.VERSION_CODES.P;
+import static android.os.Build.VERSION_CODES.Q;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
@@ -309,9 +311,27 @@
 
     @Test
     public void testFocusedWindowMultipleDisplays() {
+        doTestFocusedWindowMultipleDisplays(false /* perDisplayFocusEnabled */, Q);
+    }
+
+    @Test
+    public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabled() {
+        doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, Q);
+    }
+
+    @Test
+    public void testFocusedWindowMultipleDisplaysPerDisplayFocusEnabledLegacyApp() {
+        doTestFocusedWindowMultipleDisplays(true /* perDisplayFocusEnabled */, P);
+    }
+
+    private void doTestFocusedWindowMultipleDisplays(boolean perDisplayFocusEnabled,
+            int targetSdk) {
+        mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
+
         // Create a focusable window and check that focus is calculated correctly
         final WindowState window1 =
                 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
+        window1.mAppToken.mTargetSdk = targetSdk;
         updateFocusedWindow();
         assertTrue(window1.isFocused());
         assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
@@ -324,16 +344,17 @@
 
         // Add a window to the second display, and it should be focused
         final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
+        window2.mAppToken.mTargetSdk = targetSdk;
         updateFocusedWindow();
-        assertTrue(window1.isFocused());
         assertTrue(window2.isFocused());
+        assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
         assertEquals(window2, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
 
-        // Move the first window to the to including parents, and make sure focus is updated
+        // Move the first window to top including parents, and make sure focus is updated
         window1.getParent().positionChildAt(POSITION_TOP, window1, true);
         updateFocusedWindow();
         assertTrue(window1.isFocused());
-        assertTrue(window2.isFocused());
+        assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused());
         assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
     }