diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java index 002bfb6e429fe..d6afeba9fed96 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java @@ -64,6 +64,12 @@ public interface SplitScreen { return null; } + /** + * Called when the keyguard occluded state changes. + * @param occluded Indicates if the keyguard is now occluded. + */ + void onKeyguardOccludedChanged(boolean occluded); + /** Get a string representation of a stage type */ static String stageTypeToString(@StageType int stage) { switch (stage) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 9a457b5fd88eb..89e6ca86487fc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -157,6 +157,10 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator.exitSplitScreen(); } + public void onKeyguardOccludedChanged(boolean occluded) { + mStageCoordinator.onKeyguardOccludedChanged(occluded); + } + public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) { mStageCoordinator.exitSplitScreenOnHide(exitSplitScreenOnHide); } @@ -284,6 +288,13 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mISplitScreen = new ISplitScreenImpl(SplitScreenController.this); return mISplitScreen; } + + @Override + public void onKeyguardOccludedChanged(boolean occluded) { + mMainExecutor.execute(() -> { + SplitScreenController.this.onKeyguardOccludedChanged(occluded); + }); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 38f6361387a4d..7f3c6ab77f746 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -116,6 +116,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final DisplayImeController mDisplayImeController; private final SplitScreenTransitions mSplitTransitions; private boolean mExitSplitScreenOnHide = true; + private boolean mKeyguardOccluded; // TODO(b/187041611): remove this flag after totally deprecated legacy split /** Whether the device is supporting legacy split or not. */ @@ -275,6 +276,12 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mTaskOrganizer.applyTransaction(wct); } + void onKeyguardOccludedChanged(boolean occluded) { + // Do not exit split directly, because it needs to wait for task info update to determine + // which task should remain on top after split dismissed. + mKeyguardOccluded = occluded; + } + void exitSplitScreen() { exitSplitScreen(null /* childrenToTop */); } @@ -407,6 +414,13 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Exit split-screen if both stage are not visible. // TODO: This is only a temporary request from UX and is likely to be removed soon... exitSplitScreen(); + } else if (mKeyguardOccluded) { + // At least one of the stages is visible while keyguard occluded. Dismiss split because + // there's show-when-locked activity showing on top of keyguard. Also make sure the + // task contains show-when-locked activity remains on top after split dismissed. + final StageTaskListener toTop = + mainStageVisible ? mMainStage : (sideStageVisible ? mSideStage : null); + exitSplitScreen(toTop); } if (mainStageVisible) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 3d51f23797273..783d814753507 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -2738,6 +2738,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab updateBiometricListeningState(); } + /** Notifies that the occluded state changed. */ + public void onKeyguardOccludedChanged(boolean occluded) { + Assert.isMainThread(); + if (DEBUG) { + Log.d(TAG, "onKeyguardOccludedChanged(" + occluded + ")"); + } + for (int i = 0; i < mCallbacks.size(); i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onKeyguardOccludedChanged(occluded); + } + } + } + /** * Handle {@link #MSG_KEYGUARD_RESET} */ @@ -2920,6 +2934,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab callback.onPhoneStateChanged(mPhoneState); callback.onRefreshCarrierInfo(); callback.onClockVisibilityChanged(); + callback.onKeyguardOccludedChanged(mKeyguardOccluded); callback.onKeyguardVisibilityChangedRaw(mKeyguardIsVisible); callback.onTelephonyCapable(mTelephonyCapable); callback.onLockScreenModeChanged(mLockScreenMode); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index e561a5a84f244..20a0e31931e0a 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -88,6 +88,12 @@ public class KeyguardUpdateMonitorCallback { */ public void onKeyguardVisibilityChanged(boolean showing) { } + /** + * Called when the keyguard occluded state changes. + * @param occluded Indicates if the keyguard is now occluded. + */ + public void onKeyguardOccludedChanged(boolean occluded) { } + public void onKeyguardVisibilityChangedRaw(boolean showing) { final long now = SystemClock.elapsedRealtime(); if (showing == mShowing diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 91d1bd73a403a..c9751144cad99 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -888,6 +888,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mStatusBar.setBouncerShowing(bouncerShowing); } + if (occluded != mLastOccluded || mFirstUpdate) { + mKeyguardUpdateManager.onKeyguardOccludedChanged(occluded); + } if ((showing && !occluded) != (mLastShowing && !mLastOccluded) || mFirstUpdate) { mKeyguardUpdateManager.onKeyguardVisibilityChanged(showing && !occluded); } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index 92ef8504d1232..131944fc7c23b 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -61,6 +61,7 @@ import com.android.wm.shell.onehanded.OneHandedTransitionCallback; import com.android.wm.shell.onehanded.OneHandedUiEventLogger; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.protolog.ShellProtoLogImpl; +import com.android.wm.shell.splitscreen.SplitScreen; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -101,7 +102,8 @@ public final class WMShell extends SystemUI // Shell interfaces private final Optional mPipOptional; - private final Optional mSplitScreenOptional; + private final Optional mLegacySplitScreenOptional; + private final Optional mSplitScreenOptional; private final Optional mOneHandedOptional; private final Optional mHideDisplayCutoutOptional; private final Optional mShellCommandHandler; @@ -116,6 +118,7 @@ public final class WMShell extends SystemUI private final Executor mSysUiMainExecutor; private boolean mIsSysUiStateValid; + private KeyguardUpdateMonitorCallback mLegacySplitScreenKeyguardCallback; private KeyguardUpdateMonitorCallback mSplitScreenKeyguardCallback; private KeyguardUpdateMonitorCallback mPipKeyguardCallback; private KeyguardUpdateMonitorCallback mOneHandedKeyguardCallback; @@ -123,7 +126,8 @@ public final class WMShell extends SystemUI @Inject public WMShell(Context context, Optional pipOptional, - Optional splitScreenOptional, + Optional legacySplitScreenOptional, + Optional splitScreenOptional, Optional oneHandedOptional, Optional hideDisplayCutoutOptional, Optional shellCommandHandler, @@ -143,6 +147,7 @@ public final class WMShell extends SystemUI mScreenLifecycle = screenLifecycle; mSysUiState = sysUiState; mPipOptional = pipOptional; + mLegacySplitScreenOptional = legacySplitScreenOptional; mSplitScreenOptional = splitScreenOptional; mOneHandedOptional = oneHandedOptional; mHideDisplayCutoutOptional = hideDisplayCutoutOptional; @@ -158,6 +163,7 @@ public final class WMShell extends SystemUI mProtoTracer.add(this); mCommandQueue.addCallback(this); mPipOptional.ifPresent(this::initPip); + mLegacySplitScreenOptional.ifPresent(this::initLegacySplitScreen); mSplitScreenOptional.ifPresent(this::initSplitScreen); mOneHandedOptional.ifPresent(this::initOneHanded); mHideDisplayCutoutOptional.ifPresent(this::initHideDisplayCutout); @@ -211,8 +217,8 @@ public final class WMShell extends SystemUI } @VisibleForTesting - void initSplitScreen(LegacySplitScreen legacySplitScreen) { - mSplitScreenKeyguardCallback = new KeyguardUpdateMonitorCallback() { + void initLegacySplitScreen(LegacySplitScreen legacySplitScreen) { + mLegacySplitScreenKeyguardCallback = new KeyguardUpdateMonitorCallback() { @Override public void onKeyguardVisibilityChanged(boolean showing) { // Hide the divider when keyguard is showing. Even though keyguard/statusbar is @@ -222,6 +228,17 @@ public final class WMShell extends SystemUI legacySplitScreen.onKeyguardVisibilityChanged(showing); } }; + mKeyguardUpdateMonitor.registerCallback(mLegacySplitScreenKeyguardCallback); + } + + @VisibleForTesting + void initSplitScreen(SplitScreen splitScreen) { + mSplitScreenKeyguardCallback = new KeyguardUpdateMonitorCallback() { + @Override + public void onKeyguardOccludedChanged(boolean occluded) { + splitScreen.onKeyguardOccludedChanged(occluded); + } + }; mKeyguardUpdateMonitor.registerCallback(mSplitScreenKeyguardCallback); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java index 1dd0b21bda30f..300907ce53f53 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java @@ -39,6 +39,7 @@ import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.onehanded.OneHandedTransitionCallback; import com.android.wm.shell.pip.Pip; +import com.android.wm.shell.splitscreen.SplitScreen; import org.junit.Before; import org.junit.Test; @@ -67,6 +68,7 @@ public class WMShellTest extends SysuiTestCase { @Mock SysUiState mSysUiState; @Mock Pip mPip; @Mock LegacySplitScreen mLegacySplitScreen; + @Mock SplitScreen mSplitScreen; @Mock OneHanded mOneHanded; @Mock HideDisplayCutout mHideDisplayCutout; @Mock ProtoTracer mProtoTracer; @@ -78,7 +80,7 @@ public class WMShellTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mWMShell = new WMShell(mContext, Optional.of(mPip), Optional.of(mLegacySplitScreen), - Optional.of(mOneHanded), Optional.of(mHideDisplayCutout), + Optional.of(mSplitScreen), Optional.of(mOneHanded), Optional.of(mHideDisplayCutout), Optional.of(mShellCommandHandler), mCommandQueue, mConfigurationController, mKeyguardUpdateMonitor, mNavigationModeController, mScreenLifecycle, mSysUiState, mProtoTracer, mSysUiMainExecutor); @@ -91,9 +93,16 @@ public class WMShellTest extends SysuiTestCase { verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class)); } + @Test + public void initLegacySplitScreen_registersCallbacks() { + mWMShell.initLegacySplitScreen(mLegacySplitScreen); + + verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class)); + } + @Test public void initSplitScreen_registersCallbacks() { - mWMShell.initSplitScreen(mLegacySplitScreen); + mWMShell.initSplitScreen(mSplitScreen); verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class)); }