Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2588ab0f authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Dispose per-display input channel explicilty when removing display

Also simplify the initialization and cleanup of PointerEventDispatcher
because the null condition should never happen.

Bug: 126141550
Test: atest DisplayContentTests
Test: manual - Create virtual display and remove it many times. Observe
      no "Input channel object ... was finalized without being disposed!"
      in device log. And "dumpsys input" don't show MonitoringChannels
      in the removed display.

Change-Id: Id768a1a77169a91fd0762e166f49e15f37668000
parent 1cc1db0a
Loading
Loading
Loading
Loading
+17 −37
Original line number Diff line number Diff line
@@ -392,7 +392,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo

        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,10 +2441,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            mTmpRegion.set(mTmpRect);
            mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
        }
        if (mTapDetector != null) {
        mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
    }
    }

    /**
     * Union the region with all the tap exclude region provided by windows on this display.
@@ -2502,11 +2491,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            mRemovingDisplay = false;
        }

        mDisplayPolicy.onDisplayRemoved();
        mWmService.mWindowPlacerLocked.requestTraversal();
    }

@@ -4825,16 +4809,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    }

    void registerPointerEventListener(@NonNull PointerEventListener listener) {
        if (mPointerEventDispatcher != null) {
        mPointerEventDispatcher.registerInputEventListener(listener);
    }
    }

    void unregisterPointerEventListener(@NonNull PointerEventListener listener) {
        if (mPointerEventDispatcher != null) {
        mPointerEventDispatcher.unregisterInputEventListener(listener);
    }
    }

    void prepareAppTransition(@WindowManager.TransitionType int transit,
            boolean alwaysKeepCurrent) {
+0 −5
Original line number Diff line number Diff line
@@ -221,7 +221,6 @@ public class DisplayPolicy {
        }
    }

    @VisibleForTesting
    private final SystemGesturesPointerEventListener mSystemGestures;

    private volatile int mLidState = LID_ABSENT;
@@ -548,10 +547,6 @@ public class DisplayPolicy {
        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;
+15 −2
Original line number Diff line number Diff line
@@ -28,11 +28,13 @@ import com.android.server.UiThread;
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 @@ public class PointerEventDispatcher extends InputEventReceiver {
            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;
        }
    }
}