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

Commit de767253 authored by Arthur Hung's avatar Arthur Hung
Browse files

Fix CTS flakes caused by creating duplicated inputconsumer

The nav InputConsumer would be used while nav bar is hidden and
would pending to be dismissed when nav bar isn't visible. That ensure
the application doesn't see the event when nav bar is coming back.

Some CTS flakes from window manager crashing that caused by
creating duplicated inputconsumer exception. The reason is the
previous one hadn't been disposed yet.

- Seperate dismiss and dispose that could make sure that the previous
  nav consumer is removed from InputMonitor when creating the new one,
  and its input receiver will be disposed on the attached thread.

Test: atest com.android.server.wm
Test: atest CtsUiRenderingTestCases
Bug: 148395441
Change-Id: I03c2f3aaece4f3f000651b18709e0732d5965604
parent 45b0fc87
Loading
Loading
Loading
Loading
+4 −8
Original line number Diff line number Diff line
@@ -75,7 +75,6 @@ import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -83,7 +82,6 @@ import android.view.Display;
import android.view.IApplicationToken;
import android.view.IDisplayFoldListener;
import android.view.IWindowManager;
import android.view.InputEventReceiver;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -471,6 +469,10 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
         * Remove the input consumer from the window manager.
         */
        void dismiss();
        /**
         * Dispose the input consumer and input receiver from UI thread.
         */
        void dispose();
    }

    /**
@@ -504,12 +506,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
        public static final int CAMERA_LENS_UNCOVERED = 0;
        public static final int CAMERA_LENS_COVERED = 1;

        /**
         * Add a input consumer which will consume all input events going to any window below it.
         */
        public InputConsumer createInputConsumer(Looper looper, String name,
                InputEventReceiver.Factory inputEventReceiverFactory, int displayId);

        /**
         * Returns a code that describes the current state of the lid switch.
         */
+5 −4
Original line number Diff line number Diff line
@@ -1511,15 +1511,16 @@ public class DisplayPolicy {
        // nav bar and ensure the application doesn't see the event.
        if (navVisible || navAllowedHidden) {
            if (mInputConsumer != null) {
                mInputConsumer.dismiss();
                mHandler.sendMessage(
                        mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer));
                mInputConsumer = null;
            }
        } else if (mInputConsumer == null && mStatusBar != null && canHideNavigationBar()) {
            mInputConsumer = mService.createInputConsumer(mHandler.getLooper(),
            mInputConsumer = mDisplayContent.getInputMonitor().createInputConsumer(
                    mHandler.getLooper(),
                    INPUT_CONSUMER_NAVIGATION,
                    HideNavInputEventReceiver::new,
                    displayFrames.mDisplayId);
                    HideNavInputEventReceiver::new);
            // As long as mInputConsumer is active, hover events are not dispatched to the app
            // and the pointer icon is likely to become stale. Hide it to avoid confusion.
            InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
@@ -3173,7 +3174,7 @@ public class DisplayPolicy {

    private void disposeInputConsumer(InputConsumer inputConsumer) {
        if (inputConsumer != null) {
            inputConsumer.dismiss();
            inputConsumer.dispose();
        }
    }

+40 −32
Original line number Diff line number Diff line
@@ -103,9 +103,17 @@ final class InputMonitor {
        @Override
        public void dismiss() {
            synchronized (mService.mGlobalLock) {
                if (mInputMonitor.destroyInputConsumer(mWindowHandle.name)) {
                    mInputEventReceiver.dispose();
                mInputMonitor.mInputConsumers.remove(mName);
                hide(mInputMonitor.mInputTransaction);
                mInputMonitor.updateInputWindowsLw(true /* force */);
            }
        }

        @Override
        public void dispose() {
            synchronized (mService.mGlobalLock) {
                disposeChannelsLw();
                mInputEventReceiver.dispose();
            }
        }
    }
@@ -415,18 +423,18 @@ final class InputMonitor {
    }

    private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {
        InputConsumerImpl navInputConsumer;
        InputConsumerImpl pipInputConsumer;
        InputConsumerImpl wallpaperInputConsumer;
        InputConsumerImpl recentsAnimationInputConsumer;
        InputConsumerImpl mNavInputConsumer;
        InputConsumerImpl mPipInputConsumer;
        InputConsumerImpl mWallpaperInputConsumer;
        InputConsumerImpl mRecentsAnimationInputConsumer;

        private boolean mAddInputConsumerHandle;
        private boolean mAddNavInputConsumerHandle;
        private boolean mAddPipInputConsumerHandle;
        private boolean mAddWallpaperInputConsumerHandle;
        private boolean mAddRecentsAnimationInputConsumerHandle;

        boolean inDrag;
        WallpaperController wallpaperController;
        boolean mInDrag;
        WallpaperController mWallpaperController;

        // An invalid window handle that tells SurfaceFlinger not update the input info.
        final InputWindowHandle mInvalidInputWindow = new InputWindowHandle(null, mDisplayId);
@@ -434,20 +442,20 @@ final class InputMonitor {
        private void updateInputWindows(boolean inDrag) {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateInputWindows");

            navInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION);
            pipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP);
            wallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER);
            recentsAnimationInputConsumer = getInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
            mNavInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION);
            mPipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP);
            mWallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER);
            mRecentsAnimationInputConsumer = getInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);

            mAddInputConsumerHandle = navInputConsumer != null;
            mAddPipInputConsumerHandle = pipInputConsumer != null;
            mAddWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
            mAddRecentsAnimationInputConsumerHandle = recentsAnimationInputConsumer != null;
            mAddNavInputConsumerHandle = mNavInputConsumer != null;
            mAddPipInputConsumerHandle = mPipInputConsumer != null;
            mAddWallpaperInputConsumerHandle = mWallpaperInputConsumer != null;
            mAddRecentsAnimationInputConsumerHandle = mRecentsAnimationInputConsumer != null;

            mTmpRect.setEmpty();
            mDisableWallpaperTouchEvents = false;
            this.inDrag = inDrag;
            wallpaperController = mDisplayContent.mWallpaperController;
            mInDrag = inDrag;
            mWallpaperController = mDisplayContent.mWallpaperController;

            resetInputConsumers(mInputTransaction);

@@ -455,7 +463,7 @@ final class InputMonitor {
                    true /* traverseTopToBottom */);

            if (mAddWallpaperInputConsumerHandle) {
                wallpaperInputConsumer.show(mInputTransaction, 0);
                mWallpaperInputConsumer.show(mInputTransaction, 0);
            }

            if (mApplyImmediately) {
@@ -494,8 +502,8 @@ final class InputMonitor {
                if (recentsAnimationController != null
                        && recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord)) {
                    if (recentsAnimationController.updateInputConsumerForApp(
                            recentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
                        recentsAnimationInputConsumer.show(mInputTransaction, w);
                            mRecentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
                        mRecentsAnimationInputConsumer.show(mInputTransaction, w);
                        mAddRecentsAnimationInputConsumerHandle = false;
                    }
                }
@@ -505,25 +513,25 @@ final class InputMonitor {
                if (mAddPipInputConsumerHandle) {
                    // Update the bounds of the Pip input consumer to match the window bounds.
                    w.getBounds(mTmpRect);
                    pipInputConsumer.layout(mInputTransaction, mTmpRect);
                    mPipInputConsumer.layout(mInputTransaction, mTmpRect);

                    // The touchable region is relative to the surface top-left
                    mTmpRect.offsetTo(0, 0);
                    pipInputConsumer.mWindowHandle.touchableRegion.set(mTmpRect);
                    pipInputConsumer.show(mInputTransaction, w);
                    mPipInputConsumer.mWindowHandle.touchableRegion.set(mTmpRect);
                    mPipInputConsumer.show(mInputTransaction, w);
                    mAddPipInputConsumerHandle = false;
                }
            }

            if (mAddInputConsumerHandle) {
                navInputConsumer.show(mInputTransaction, w);
                mAddInputConsumerHandle = false;
            if (mAddNavInputConsumerHandle) {
                mNavInputConsumer.show(mInputTransaction, w);
                mAddNavInputConsumerHandle = false;
            }

            if (mAddWallpaperInputConsumerHandle) {
                if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) {
                    // Add the wallpaper input consumer above the first visible wallpaper.
                    wallpaperInputConsumer.show(mInputTransaction, w);
                    mWallpaperInputConsumer.show(mInputTransaction, w);
                    mAddWallpaperInputConsumerHandle = false;
                }
            }
@@ -531,13 +539,13 @@ final class InputMonitor {
            if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
                mDisableWallpaperTouchEvents = true;
            }
            final boolean hasWallpaper = wallpaperController.isWallpaperTarget(w)
            final boolean hasWallpaper = mWallpaperController.isWallpaperTarget(w)
                    && !mService.mPolicy.isKeyguardShowing()
                    && !mDisableWallpaperTouchEvents;

            // If there's a drag in progress and 'child' is a potential drop target,
            // make sure it's been told about the drag
            if (inDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
            if (mInDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
                mService.mDragDropController.sendDragStartedIfNeededLocked(w);
            }

+0 −15
Original line number Diff line number Diff line
@@ -229,7 +229,6 @@ import android.view.InputApplicationHandle;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.InputWindowHandle;
import android.view.InsetsState;
import android.view.KeyEvent;
@@ -5741,20 +5740,6 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    @Override
    public WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
            InputEventReceiver.Factory inputEventReceiverFactory, int displayId) {
        synchronized (mGlobalLock) {
            DisplayContent displayContent = mRoot.getDisplayContent(displayId);
            if (displayContent != null) {
                return displayContent.getInputMonitor().createInputConsumer(looper, name,
                        inputEventReceiverFactory);
            } else {
                return null;
            }
        }
    }

    @Override
    public void createInputConsumer(IBinder token, String name, int displayId,
            InputChannel inputChannel) {