diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 5460e36a5f1b4..cee6740c8fd5f 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -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,119 +447,6 @@ public class DisplayPolicy { final Looper looper = UiThread.getHandler().getLooper(); mHandler = new PolicyHandler(looper); - mSystemGestures = new SystemGesturesPointerEventListener(mContext, mHandler, - new SystemGesturesPointerEventListener.Callbacks() { - @Override - public void onSwipeFromTop() { - synchronized (mLock) { - if (mStatusBar != null) { - requestTransientBars(mStatusBar); - } - checkAltBarSwipeForTransientBars(ALT_BAR_TOP); - } - } - - @Override - public void onSwipeFromBottom() { - synchronized (mLock) { - if (mNavigationBar != null - && mNavigationBarPosition == NAV_BAR_BOTTOM) { - requestTransientBars(mNavigationBar); - } - checkAltBarSwipeForTransientBars(ALT_BAR_BOTTOM); - } - } - - @Override - public void onSwipeFromRight() { - final Region excludedRegion = Region.obtain(); - synchronized (mLock) { - mDisplayContent.calculateSystemGestureExclusion( - excludedRegion, null /* outUnrestricted */); - final boolean excluded = - mSystemGestures.currentGestureStartedInRegion(excludedRegion); - if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_RIGHT - || !excluded && mNavigationBarAlwaysShowOnSideGesture)) { - requestTransientBars(mNavigationBar); - } - checkAltBarSwipeForTransientBars(ALT_BAR_RIGHT); - } - excludedRegion.recycle(); - } - - @Override - public void onSwipeFromLeft() { - final Region excludedRegion = Region.obtain(); - synchronized (mLock) { - mDisplayContent.calculateSystemGestureExclusion( - excludedRegion, null /* outUnrestricted */); - final boolean excluded = - mSystemGestures.currentGestureStartedInRegion(excludedRegion); - if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_LEFT - || !excluded && mNavigationBarAlwaysShowOnSideGesture)) { - requestTransientBars(mNavigationBar); - } - checkAltBarSwipeForTransientBars(ALT_BAR_LEFT); - } - excludedRegion.recycle(); - } - - @Override - public void onFling(int duration) { - if (mService.mPowerManagerInternal != null) { - mService.mPowerManagerInternal.setPowerBoost( - Boost.INTERACTION, duration); - } - } - - @Override - public void onDebug() { - // no-op - } - - private WindowOrientationListener getOrientationListener() { - final DisplayRotation rotation = mDisplayContent.getDisplayRotation(); - return rotation != null ? rotation.getOrientationListener() : null; - } - - @Override - public void onDown() { - final WindowOrientationListener listener = getOrientationListener(); - if (listener != null) { - listener.onTouchStart(); - } - } - - @Override - public void onUpOrCancel() { - final WindowOrientationListener listener = getOrientationListener(); - if (listener != null) { - listener.onTouchEnd(); - } - } - - @Override - public void onMouseHoverAtTop() { - mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); - Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS); - msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS; - mHandler.sendMessageDelayed(msg, 500 /* delayMillis */); - } - - @Override - public void onMouseHoverAtBottom() { - mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); - Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS); - msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION; - mHandler.sendMessageDelayed(msg, 500 /* delayMillis */); - } - - @Override - public void onMouseLeaveFromEdge() { - mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); - } - }); - displayContent.registerPointerEventListener(mSystemGestures); mAppTransitionListener = new WindowManagerInternal.AppTransitionListener() { private Runnable mAppTransitionPending = () -> { @@ -614,7 +502,7 @@ public class DisplayPolicy { mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext, looper, mService.mVrModeEnabled); - // TODO: Make it can take screenshot on external display + // TODO(b/180986447): Make it can take screenshot on external display mScreenshotHelper = displayContent.isDefaultDisplay ? new ScreenshotHelper(mContext) : null; @@ -638,16 +526,6 @@ public class DisplayPolicy { 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) { @@ -666,12 +544,154 @@ public class DisplayPolicy { } void systemReady() { - mSystemGestures.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() { + synchronized (mLock) { + if (mStatusBar != null) { + requestTransientBars(mStatusBar); + } + checkAltBarSwipeForTransientBars(ALT_BAR_TOP); + } + } + + @Override + public void onSwipeFromBottom() { + synchronized (mLock) { + if (mNavigationBar != null + && mNavigationBarPosition == NAV_BAR_BOTTOM) { + requestTransientBars(mNavigationBar); + } + checkAltBarSwipeForTransientBars(ALT_BAR_BOTTOM); + } + } + + @Override + public void onSwipeFromRight() { + final Region excludedRegion = Region.obtain(); + synchronized (mLock) { + mDisplayContent.calculateSystemGestureExclusion( + excludedRegion, null /* outUnrestricted */); + final boolean excluded = mSystemGestures + .currentGestureStartedInRegion(excludedRegion); + if (mNavigationBar != null + && (mNavigationBarPosition == NAV_BAR_RIGHT + || !excluded && mNavigationBarAlwaysShowOnSideGesture)) { + requestTransientBars(mNavigationBar); + } + checkAltBarSwipeForTransientBars(ALT_BAR_RIGHT); + } + excludedRegion.recycle(); + } + + @Override + public void onSwipeFromLeft() { + final Region excludedRegion = Region.obtain(); + synchronized (mLock) { + mDisplayContent.calculateSystemGestureExclusion( + excludedRegion, null /* outUnrestricted */); + final boolean excluded = mSystemGestures + .currentGestureStartedInRegion(excludedRegion); + if (mNavigationBar != null + && (mNavigationBarPosition == NAV_BAR_LEFT + || !excluded && mNavigationBarAlwaysShowOnSideGesture)) { + requestTransientBars(mNavigationBar); + } + checkAltBarSwipeForTransientBars(ALT_BAR_LEFT); + } + excludedRegion.recycle(); + } + + @Override + public void onFling(int duration) { + if (mService.mPowerManagerInternal != null) { + mService.mPowerManagerInternal.setPowerBoost( + Boost.INTERACTION, duration); + } + } + + @Override + public void onDebug() { + // no-op + } + + private WindowOrientationListener getOrientationListener() { + final DisplayRotation rotation = mDisplayContent.getDisplayRotation(); + return rotation != null ? rotation.getOrientationListener() : null; + } + + @Override + public void onDown() { + final WindowOrientationListener listener = getOrientationListener(); + if (listener != null) { + listener.onTouchStart(); + } + } + + @Override + public void onUpOrCancel() { + final WindowOrientationListener listener = getOrientationListener(); + if (listener != null) { + listener.onTouchEnd(); + } + } + + @Override + public void onMouseHoverAtTop() { + mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); + Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS); + msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS; + mHandler.sendMessageDelayed(msg, 500 /* delayMillis */); + } + + @Override + public void onMouseHoverAtBottom() { + mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); + Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS); + msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION; + mHandler.sendMessageDelayed(msg, 500 /* delayMillis */); + } + + @Override + public void onMouseLeaveFromEdge() { + mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); + } + }); + mDisplayContent.registerPointerEventListener(getSystemGestures()); + if (mService.mSystemReady) { + mSystemGestures.systemReady(); + } + } + 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 diff --git a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java index f3859b41b6fd3..a98a47802914a 100644 --- a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java +++ b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java @@ -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()) { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index 2163661b7506f..db7054d585903 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -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(); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index c13d6b19bf1db..ebc5c4ff280a9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -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;