Merge "Dispose per-display input channel explicilty when removing display"
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 515ac52..db59030 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -392,7 +392,8 @@
     final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
 
     /** Detect user tapping outside of current focused task bounds .*/
-    TaskTapPointerEventListener mTapDetector;
+    @VisibleForTesting
+    final TaskTapPointerEventListener mTapDetector;
 
     /** Detect user tapping outside of current focused stack bounds .*/
     private Region mTouchExcludeRegion = new Region();
@@ -876,14 +877,17 @@
         mBoundsAnimationController = new BoundsAnimationController(service.mContext,
                 mAppTransition, AnimationThread.getHandler(), animationHandler);
 
-        if (mWmService.mInputManager != null) {
-            final InputChannel inputChannel = mWmService.mInputManager.monitorInput("Display "
-                    + mDisplayId, mDisplayId);
-            mPointerEventDispatcher = inputChannel != null
-                    ? new PointerEventDispatcher(inputChannel) : null;
-        } else {
-            mPointerEventDispatcher = null;
-        }
+        final InputChannel inputChannel = mWmService.mInputManager.monitorInput(
+                "PointerEventDispatcher" + mDisplayId, mDisplayId);
+        mPointerEventDispatcher = new PointerEventDispatcher(inputChannel);
+
+        // Tap Listeners are supported for:
+        // 1. All physical displays (multi-display).
+        // 2. VirtualDisplays on VR, AA (and everything else).
+        mTapDetector = new TaskTapPointerEventListener(mWmService, this);
+        registerPointerEventListener(mTapDetector);
+        registerPointerEventListener(mWmService.mMousePositionTracker);
+
         mDisplayPolicy = new DisplayPolicy(service, this);
         mDisplayRotation = new DisplayRotation(service, this);
         if (isDefaultDisplay) {
@@ -1511,19 +1515,6 @@
 
         mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
-
-        // Tap Listeners are supported for:
-        // 1. All physical displays (multi-display).
-        // 2. VirtualDisplays on VR, AA (and everything else).
-        if (mPointerEventDispatcher != null && mTapDetector == null) {
-            if (DEBUG_DISPLAY) {
-                Slog.d(TAG,
-                        "Registering PointerEventListener for DisplayId: " + mDisplayId);
-            }
-            mTapDetector = new TaskTapPointerEventListener(mWmService, this);
-            registerPointerEventListener(mTapDetector);
-            registerPointerEventListener(mWmService.mMousePositionTracker);
-        }
     }
 
     /**
@@ -2450,9 +2441,7 @@
             mTmpRegion.set(mTmpRect);
             mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
         }
-        if (mTapDetector != null) {
-            mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
-        }
+        mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
     }
 
     /**
@@ -2502,11 +2491,7 @@
             mWmService.stopFreezingDisplayLocked();
             super.removeImmediately();
             if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
-            if (mPointerEventDispatcher != null && mTapDetector != null) {
-                unregisterPointerEventListener(mTapDetector);
-                unregisterPointerEventListener(mWmService.mMousePositionTracker);
-                mTapDetector = null;
-            }
+            mPointerEventDispatcher.dispose();
             mWmService.mAnimator.removeDisplayLocked(mDisplayId);
             mWindowingLayer.release();
             mOverlayLayer.release();
@@ -2516,7 +2501,6 @@
             mRemovingDisplay = false;
         }
 
-        mDisplayPolicy.onDisplayRemoved();
         mWmService.mWindowPlacerLocked.requestTraversal();
     }
 
@@ -4825,15 +4809,11 @@
     }
 
     void registerPointerEventListener(@NonNull PointerEventListener listener) {
-        if (mPointerEventDispatcher != null) {
-            mPointerEventDispatcher.registerInputEventListener(listener);
-        }
+        mPointerEventDispatcher.registerInputEventListener(listener);
     }
 
     void unregisterPointerEventListener(@NonNull PointerEventListener listener) {
-        if (mPointerEventDispatcher != null) {
-            mPointerEventDispatcher.unregisterInputEventListener(listener);
-        }
+        mPointerEventDispatcher.unregisterInputEventListener(listener);
     }
 
     void prepareAppTransition(@WindowManager.TransitionType int transit,
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 5862d43..e48361f 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -221,7 +221,6 @@
         }
     }
 
-    @VisibleForTesting
     private final SystemGesturesPointerEventListener mSystemGestures;
 
     private volatile int mLidState = LID_ABSENT;
@@ -548,10 +547,6 @@
         return mDisplayContent.getDisplayId();
     }
 
-    void onDisplayRemoved() {
-        mDisplayContent.unregisterPointerEventListener(mSystemGestures);
-    }
-
     void configure(int width, int height, int shortSizeDp) {
         // Allow the navigation bar to move on non-square small devices (phones).
         mNavigationBarCanMove = width != height && shortSizeDp < 600;
diff --git a/services/core/java/com/android/server/wm/PointerEventDispatcher.java b/services/core/java/com/android/server/wm/PointerEventDispatcher.java
index f815fa0..8d08aa3 100644
--- a/services/core/java/com/android/server/wm/PointerEventDispatcher.java
+++ b/services/core/java/com/android/server/wm/PointerEventDispatcher.java
@@ -28,11 +28,13 @@
 import java.util.ArrayList;
 
 public class PointerEventDispatcher extends InputEventReceiver {
-    ArrayList<PointerEventListener> mListeners = new ArrayList<PointerEventListener>();
-    PointerEventListener[] mListenersArray = new PointerEventListener[0];
+    private final InputChannel mInputChannel;
+    private final ArrayList<PointerEventListener> mListeners = new ArrayList<>();
+    private PointerEventListener[] mListenersArray = new PointerEventListener[0];
 
     public PointerEventDispatcher(InputChannel inputChannel) {
         super(inputChannel, UiThread.getHandler().getLooper());
+        mInputChannel = inputChannel;
     }
 
     @Override
@@ -87,4 +89,15 @@
             mListenersArray = null;
         }
     }
+
+    /** Dispose the associated input channel and clean up the listeners. */
+    @Override
+    public void dispose() {
+        super.dispose();
+        mInputChannel.dispose();
+        synchronized (mListeners) {
+            mListeners.clear();
+            mListenersArray = null;
+        }
+    }
 }