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

Commit 68c30247 authored by Charles Chen's avatar Charles Chen
Browse files

Migrate SystemGesturePointerEventListener to WindowContext

Previously system context derived display context passed to
SystemGesturePointerEventListener.
After R, it threw IncorrectContextUsageViolation when initialization
because display context is not a UI context.

This CL changes to pass window context to fix the Violation.

Bug: 177650348
Test: atest WmTests
Test: atest DisplayPolicyTests#testDisplayPolicyNoCrash

Change-Id: I0d17327d8a8c14ec626c0dd9ad1a4e8529174598
parent caf9ae8b
Loading
Loading
Loading
Loading
+154 −135
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
@@ -240,7 +241,7 @@ public class DisplayPolicy {
        }
    }

    private final SystemGesturesPointerEventListener mSystemGestures;
    private SystemGesturesPointerEventListener mSystemGestures;

    private volatile int mLidState = LID_ABSENT;
    private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
@@ -382,7 +383,7 @@ public class DisplayPolicy {
    private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
    private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;

    private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
    private GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;

    private final WindowManagerInternal.AppTransitionListener mAppTransitionListener;

@@ -446,7 +447,130 @@ public class DisplayPolicy {

        final Looper looper = UiThread.getHandler().getLooper();
        mHandler = new PolicyHandler(looper);
        mSystemGestures = new SystemGesturesPointerEventListener(mContext, mHandler,
        mAppTransitionListener = new WindowManagerInternal.AppTransitionListener() {

            private Runnable mAppTransitionPending = () -> {
                StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
                if (statusBar != null) {
                    statusBar.appTransitionPending(displayId);
                }
            };

            private Runnable mAppTransitionCancelled = () -> {
                StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
                if (statusBar != null) {
                    statusBar.appTransitionCancelled(displayId);
                }
            };

            private Runnable mAppTransitionFinished = () -> {
                StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
                if (statusBar != null) {
                    statusBar.appTransitionFinished(displayId);
                }
            };

            @Override
            public void onAppTransitionPendingLocked() {
                mHandler.post(mAppTransitionPending);
            }

            @Override
            public int onAppTransitionStartingLocked(boolean keyguardGoingAway, long duration,
                    long statusBarAnimationStartTime, long statusBarAnimationDuration) {
                mHandler.post(() -> {
                    StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
                    if (statusBar != null) {
                        statusBar.appTransitionStarting(mContext.getDisplayId(),
                                statusBarAnimationStartTime, statusBarAnimationDuration);
                    }
                });
                return 0;
            }

            @Override
            public void onAppTransitionCancelledLocked(boolean keyguardGoingAway) {
                mHandler.post(mAppTransitionCancelled);
            }

            @Override
            public void onAppTransitionFinishedLocked(IBinder token) {
                mHandler.post(mAppTransitionFinished);
            }
        };
        displayContent.mAppTransition.registerListenerLocked(mAppTransitionListener);
        mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext, looper,
                mService.mVrModeEnabled);

        // TODO(b/180986447): Make it can take screenshot on external display
        mScreenshotHelper = displayContent.isDefaultDisplay
                ? new ScreenshotHelper(mContext) : null;

        if (mDisplayContent.isDefaultDisplay) {
            mHasStatusBar = true;
            mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar);

            // Allow a system property to override this. Used by the emulator.
            // See also hasNavigationBar().
            String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
            if ("1".equals(navBarOverride)) {
                mHasNavigationBar = false;
            } else if ("0".equals(navBarOverride)) {
                mHasNavigationBar = true;
            }
        } else {
            mHasStatusBar = false;
            mHasNavigationBar = mDisplayContent.supportsSystemDecorations();
        }

        mRefreshRatePolicy = new RefreshRatePolicy(mService,
                mDisplayContent.getDisplayInfo(),
                mService.mHighRefreshRateDenylist);
    }

    private void checkAltBarSwipeForTransientBars(@WindowManagerPolicy.AltBarPosition int pos) {
        if (mStatusBarAlt != null && mStatusBarAltPosition == pos) {
            requestTransientBars(mStatusBarAlt);
        }
        if (mNavigationBarAlt != null && mNavigationBarAltPosition == pos) {
            requestTransientBars(mNavigationBarAlt);
        }
        if (mClimateBarAlt != null && mClimateBarAltPosition == pos) {
            requestTransientBars(mClimateBarAlt);
        }
        if (mExtraNavBarAlt != null && mExtraNavBarAltPosition == pos) {
            requestTransientBars(mExtraNavBarAlt);
        }
    }

    void systemReady() {
        if (mService.mPointerLocationEnabled) {
            setPointerLocationEnabled(true);
        }
    }

    @NonNull
    private GestureNavigationSettingsObserver getGestureNavigationSettingsObserver() {
        if (mGestureNavigationSettingsObserver == null) {
            mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(mHandler,
                    mContext, () -> {
                synchronized (mLock) {
                    onConfigurationChanged();
                    getSystemGestures().onConfigurationChanged();
                    mDisplayContent.updateSystemGestureExclusion();
                }
            });
            mHandler.post(mGestureNavigationSettingsObserver::register);
        }
        return mGestureNavigationSettingsObserver;
    }

    @NonNull
    private SystemGesturesPointerEventListener getSystemGestures() {
        if (mSystemGestures == null) {
            final Context gestureContext = mUiContext.createWindowContext(
                    mDisplayContent.getDisplay(), TYPE_POINTER, null /* options */);
            mSystemGestures = new SystemGesturesPointerEventListener(gestureContext, mHandler,
                    new SystemGesturesPointerEventListener.Callbacks() {
                        @Override
                        public void onSwipeFromTop() {
@@ -475,9 +599,10 @@ public class DisplayPolicy {
                            synchronized (mLock) {
                                mDisplayContent.calculateSystemGestureExclusion(
                                        excludedRegion, null /* outUnrestricted */);
                            final boolean excluded =
                                    mSystemGestures.currentGestureStartedInRegion(excludedRegion);
                            if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_RIGHT
                                final boolean excluded = mSystemGestures
                                        .currentGestureStartedInRegion(excludedRegion);
                                if (mNavigationBar != null
                                        && (mNavigationBarPosition == NAV_BAR_RIGHT
                                        || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
                                    requestTransientBars(mNavigationBar);
                                }
@@ -492,9 +617,10 @@ public class DisplayPolicy {
                            synchronized (mLock) {
                                mDisplayContent.calculateSystemGestureExclusion(
                                        excludedRegion, null /* outUnrestricted */);
                            final boolean excluded =
                                    mSystemGestures.currentGestureStartedInRegion(excludedRegion);
                            if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_LEFT
                                final boolean excluded = mSystemGestures
                                        .currentGestureStartedInRegion(excludedRegion);
                                if (mNavigationBar != null
                                        && (mNavigationBarPosition == NAV_BAR_LEFT
                                        || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
                                    requestTransientBars(mNavigationBar);
                                }
@@ -558,119 +684,13 @@ public class DisplayPolicy {
                            mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
                        }
                    });
        displayContent.registerPointerEventListener(mSystemGestures);
        mAppTransitionListener = new WindowManagerInternal.AppTransitionListener() {

            private Runnable mAppTransitionPending = () -> {
                StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
                if (statusBar != null) {
                    statusBar.appTransitionPending(displayId);
                }
            };

            private Runnable mAppTransitionCancelled = () -> {
                StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
                if (statusBar != null) {
                    statusBar.appTransitionCancelled(displayId);
                }
            };

            private Runnable mAppTransitionFinished = () -> {
                StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
                if (statusBar != null) {
                    statusBar.appTransitionFinished(displayId);
                }
            };

            @Override
            public void onAppTransitionPendingLocked() {
                mHandler.post(mAppTransitionPending);
            }

            @Override
            public int onAppTransitionStartingLocked(boolean keyguardGoingAway, long duration,
                    long statusBarAnimationStartTime, long statusBarAnimationDuration) {
                mHandler.post(() -> {
                    StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
                    if (statusBar != null) {
                        statusBar.appTransitionStarting(mContext.getDisplayId(),
                                statusBarAnimationStartTime, statusBarAnimationDuration);
                    }
                });
                return 0;
            }

            @Override
            public void onAppTransitionCancelledLocked(boolean keyguardGoingAway) {
                mHandler.post(mAppTransitionCancelled);
            }

            @Override
            public void onAppTransitionFinishedLocked(IBinder token) {
                mHandler.post(mAppTransitionFinished);
            }
        };
        displayContent.mAppTransition.registerListenerLocked(mAppTransitionListener);
        mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext, looper,
                mService.mVrModeEnabled);

        // TODO: Make it can take screenshot on external display
        mScreenshotHelper = displayContent.isDefaultDisplay
                ? new ScreenshotHelper(mContext) : null;

        if (mDisplayContent.isDefaultDisplay) {
            mHasStatusBar = true;
            mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar);

            // Allow a system property to override this. Used by the emulator.
            // See also hasNavigationBar().
            String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
            if ("1".equals(navBarOverride)) {
                mHasNavigationBar = false;
            } else if ("0".equals(navBarOverride)) {
                mHasNavigationBar = true;
            }
        } else {
            mHasStatusBar = false;
            mHasNavigationBar = mDisplayContent.supportsSystemDecorations();
        }

        mRefreshRatePolicy = new RefreshRatePolicy(mService,
                mDisplayContent.getDisplayInfo(),
                mService.mHighRefreshRateDenylist);

        mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(mHandler,
                mContext, () -> {
            synchronized (mLock) {
                onConfigurationChanged();
                mSystemGestures.onConfigurationChanged();
                mDisplayContent.updateSystemGestureExclusion();
            }
        });
        mHandler.post(mGestureNavigationSettingsObserver::register);
    }

    private void checkAltBarSwipeForTransientBars(@WindowManagerPolicy.AltBarPosition int pos) {
        if (mStatusBarAlt != null && mStatusBarAltPosition == pos) {
            requestTransientBars(mStatusBarAlt);
        }
        if (mNavigationBarAlt != null && mNavigationBarAltPosition == pos) {
            requestTransientBars(mNavigationBarAlt);
        }
        if (mClimateBarAlt != null && mClimateBarAltPosition == pos) {
            requestTransientBars(mClimateBarAlt);
        }
        if (mExtraNavBarAlt != null && mExtraNavBarAltPosition == pos) {
            requestTransientBars(mExtraNavBarAlt);
        }
    }

    void systemReady() {
            mDisplayContent.registerPointerEventListener(getSystemGestures());
            if (mService.mSystemReady) {
                mSystemGestures.systemReady();
        if (mService.mPointerLocationEnabled) {
            setPointerLocationEnabled(true);
            }
        }
        return mSystemGestures;
    }

    private int getDisplayId() {
        return mDisplayContent.getDisplayId();
@@ -1447,8 +1467,7 @@ public class DisplayPolicy {
    }

    void onDisplayInfoChanged(DisplayInfo info) {
        mSystemGestures.screenWidth = info.logicalWidth;
        mSystemGestures.screenHeight = info.logicalHeight;
        getSystemGestures().onDisplayInfoChanged(info);
    }

    private void layoutStatusBar(DisplayFrames displayFrames, Rect contentFrame) {
@@ -1961,7 +1980,7 @@ public class DisplayPolicy {
    public void onOverlayChangedLw() {
        updateCurrentUserResources();
        onConfigurationChanged();
        mSystemGestures.onConfigurationChanged();
        getSystemGestures().onConfigurationChanged();
    }

    /**
@@ -2032,10 +2051,10 @@ public class DisplayPolicy {
        }

        mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode);
        mLeftGestureInset = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
        mRightGestureInset = mGestureNavigationSettingsObserver.getRightSensitivity(res);
        mNavButtonForcedVisible =
                mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
        final GestureNavigationSettingsObserver observer = getGestureNavigationSettingsObserver();
        mLeftGestureInset = observer.getLeftSensitivity(res);
        mRightGestureInset = observer.getRightSensitivity(res);
        mNavButtonForcedVisible = observer.areNavigationButtonForcedVisible();
        mNavigationBarLetsThroughTaps = res.getBoolean(R.bool.config_navBarTapThrough);
        mNavigationBarAlwaysShowOnSideGesture =
                res.getBoolean(R.bool.config_navBarAlwaysShowOnSideEdgeGesture);
@@ -3047,7 +3066,7 @@ public class DisplayPolicy {
    }

    void release() {
        mHandler.post(mGestureNavigationSettingsObserver::unregister);
        mHandler.post(getGestureNavigationSettingsObserver()::unregister);
    }

    @VisibleForTesting
+6 −0
Original line number Diff line number Diff line
@@ -126,11 +126,17 @@ class SystemGesturesPointerEventListener implements PointerEventListener {
                Slog.w(TAG, "Cannot create GestureDetector, display removed:" + displayId);
                return;
            }
            onDisplayInfoChanged(info);
            mGestureDetector = new GestureDetector(mContext, new FlingGestureDetector(), mHandler) {
            };
        });
    }

    void onDisplayInfoChanged(DisplayInfo info) {
        screenWidth = info.logicalWidth;
        screenHeight = info.logicalHeight;
    }

    @Override
    public void onPointerEvent(MotionEvent event) {
        if (mGestureDetector != null && event.isTouchEvent()) {
+12 −0
Original line number Diff line number Diff line
@@ -321,4 +321,16 @@ public class DisplayPolicyTests extends WindowTestsBase {
        assertFalse(navBarSource.getFrame().isEmpty());
        assertTrue(imeSource.getFrame().contains(navBarSource.getFrame()));
    }

    @UseTestDisplay
    @Test
    public void testDisplayPolicyNotCrash() {
        final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();

        // Verify if modules initialized after DisplayContent ctr throws NPE.
        displayPolicy.onDisplayInfoChanged(mDisplayInfo);
        displayPolicy.onConfigurationChanged();
        displayPolicy.onOverlayChangedLw();
        displayPolicy.release();
    }
}
+1 −2
Original line number Diff line number Diff line
@@ -538,9 +538,8 @@ class WindowTestsBase extends SystemServiceTestsBase {

    /** Creates a {@link DisplayContent} and adds it to the system. */
    private DisplayContent createNewDisplay(DisplayInfo info, @DisplayImePolicy int imePolicy) {
        final DisplayContent display =
        final DisplayContent dc =
                new TestDisplayContent.Builder(mAtm, info).build();
        final DisplayContent dc = display.mDisplayContent;
        // this display can show IME.
        dc.mWmService.mDisplayWindowSettings.setDisplayImePolicy(dc, imePolicy);
        return dc;