Handle focused tasks on multiple displays

When the focused task changes displays, make sure to mark the whole
previous display as not part of a focused task.

This change also adds an adb am command to change the task focus.

Test: android.server.cts.ActivityManagerDisplayTests
Test: #testStackFocusSwitchOnTouchEvent
Bug: 35214007
Change-Id: I9cb7372c21a0b592abb6f6d910077ff5097dd6cf
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c45136c..2c315445 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1072,19 +1072,25 @@
     }
 
     void setTouchExcludeRegion(Task focusedTask) {
-        mTouchExcludeRegion.set(mBaseDisplayRect);
-        final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
-        mTmpRect2.setEmpty();
-        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
-            final TaskStack stack = mTaskStackContainers.get(stackNdx);
-            stack.setTouchExcludeRegion(
-                    focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2);
-        }
-        // If we removed the focused task above, add it back and only leave its
-        // outside touch area in the exclusion. TapDectector is not interested in
-        // any touch inside the focused task itself.
-        if (!mTmpRect2.isEmpty()) {
-            mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
+        // The provided task is the task on this display with focus, so if WindowManagerService's
+        // focused app is not on this display, focusedTask will be null.
+        if (focusedTask == null) {
+            mTouchExcludeRegion.setEmpty();
+        } else {
+            mTouchExcludeRegion.set(mBaseDisplayRect);
+            final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
+            mTmpRect2.setEmpty();
+            for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+                final TaskStack stack = mTaskStackContainers.get(stackNdx);
+                stack.setTouchExcludeRegion(
+                        focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2);
+            }
+            // If we removed the focused task above, add it back and only leave its
+            // outside touch area in the exclusion. TapDectector is not interested in
+            // any touch inside the focused task itself.
+            if (!mTmpRect2.isEmpty()) {
+                mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
+            }
         }
         final WindowState inputMethod = mService.mInputMethodWindow;
         if (inputMethod != null && inputMethod.isVisibleLw()) {