From b2e2789f239b1742522ea6f73b64744723a925a1 Mon Sep 17 00:00:00 2001 From: Maryam Dehaini Date: Wed, 12 Jul 2023 15:36:54 -0700 Subject: [PATCH] Remove caption when keyguard is visible Adds a DesktopModeKeyguardChangeListener to record if keyguard is visible and occluded. If it is, it means that the task is on top of the keyguard and caption is not usable and should be removed. Bug: 288910972 Test: Open calculator app and turn the screen off and then on. Caption should not be there Change-Id: I199f8233cf55d574bf8d045cb95a710008299b06 --- .../wm/shell/dagger/WMShellModule.java | 4 ++ .../DesktopModeWindowDecorViewModel.java | 48 +++++++++++++++++-- .../DesktopModeWindowDecorViewModelTests.java | 41 +++++++++++++++- 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index 20c3bd2dccc48..f5c6a03336ed6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -203,8 +203,10 @@ public abstract class WMShellModule { Context context, @ShellMainThread Handler mainHandler, @ShellMainThread Choreographer mainChoreographer, + ShellInit shellInit, ShellTaskOrganizer taskOrganizer, DisplayController displayController, + ShellController shellController, SyncTransactionQueue syncQueue, Transitions transitions, Optional desktopModeController, @@ -214,8 +216,10 @@ public abstract class WMShellModule { context, mainHandler, mainChoreographer, + shellInit, taskOrganizer, displayController, + shellController, syncQueue, transitions, desktopModeController, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index 80cf96a93efa6..c6a5e69f44c5a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -72,6 +72,9 @@ import com.android.wm.shell.desktopmode.DesktopModeStatus; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; import com.android.wm.shell.splitscreen.SplitScreenController; +import com.android.wm.shell.sysui.KeyguardChangeListener; +import com.android.wm.shell.sysui.ShellController; +import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration.TaskCornersListener; @@ -89,6 +92,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { private final DesktopModeWindowDecoration.Factory mDesktopModeWindowDecorFactory; private final ActivityTaskManager mActivityTaskManager; private final ShellTaskOrganizer mTaskOrganizer; + private final ShellController mShellController; private final Context mContext; private final Handler mMainHandler; private final Choreographer mMainChoreographer; @@ -114,30 +118,37 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { private MoveToDesktopAnimator mMoveToDesktopAnimator; private final Rect mDragToDesktopAnimationStartBounds = new Rect(); + private final DesktopModeKeyguardChangeListener mDesktopModeKeyguardChangeListener; public DesktopModeWindowDecorViewModel( Context context, Handler mainHandler, Choreographer mainChoreographer, + ShellInit shellInit, ShellTaskOrganizer taskOrganizer, DisplayController displayController, + ShellController shellController, SyncTransactionQueue syncQueue, Transitions transitions, Optional desktopModeController, - Optional desktopTasksController) { + Optional desktopTasksController + ) { this( context, mainHandler, mainChoreographer, + shellInit, taskOrganizer, displayController, + shellController, syncQueue, transitions, desktopModeController, desktopTasksController, new DesktopModeWindowDecoration.Factory(), new InputMonitorFactory(), - SurfaceControl.Transaction::new); + SurfaceControl.Transaction::new, + new DesktopModeKeyguardChangeListener()); } @VisibleForTesting @@ -145,20 +156,24 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { Context context, Handler mainHandler, Choreographer mainChoreographer, + ShellInit shellInit, ShellTaskOrganizer taskOrganizer, DisplayController displayController, + ShellController shellController, SyncTransactionQueue syncQueue, Transitions transitions, Optional desktopModeController, Optional desktopTasksController, DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory, InputMonitorFactory inputMonitorFactory, - Supplier transactionFactory) { + Supplier transactionFactory, + DesktopModeKeyguardChangeListener desktopModeKeyguardChangeListener) { mContext = context; mMainHandler = mainHandler; mMainChoreographer = mainChoreographer; mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class); mTaskOrganizer = taskOrganizer; + mShellController = shellController; mDisplayController = displayController; mSyncQueue = syncQueue; mTransitions = transitions; @@ -168,6 +183,13 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mDesktopModeWindowDecorFactory = desktopModeWindowDecorFactory; mInputMonitorFactory = inputMonitorFactory; mTransactionFactory = transactionFactory; + mDesktopModeKeyguardChangeListener = desktopModeKeyguardChangeListener; + + shellInit.addInitCallback(this::onInit, this); + } + + private void onInit() { + mShellController.addKeyguardChangeListener(mDesktopModeKeyguardChangeListener); } @Override @@ -796,6 +818,10 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { && mSplitScreenController.isTaskRootOrStageRoot(taskInfo.taskId)) { return false; } + if (mDesktopModeKeyguardChangeListener.isKeyguardVisibleAndOccluded() + && taskInfo.isFocused) { + return false; + } return DesktopModeStatus.isProto2Enabled() && taskInfo.getWindowingMode() != WINDOWING_MODE_PINNED && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD @@ -884,6 +910,22 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mDesktopTasksController.ifPresent(d -> d.removeCornersForTask(taskId)); } } + + static class DesktopModeKeyguardChangeListener implements KeyguardChangeListener { + private boolean mIsKeyguardVisible; + private boolean mIsKeyguardOccluded; + + @Override + public void onKeyguardVisibilityChanged(boolean visible, boolean occluded, + boolean animatingDismiss) { + mIsKeyguardVisible = visible; + mIsKeyguardOccluded = occluded; + } + + public boolean isKeyguardVisibleAndOccluded() { + return mIsKeyguardVisible && mIsKeyguardOccluded; + } + } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java index adc2a6fbff238..596d6dd3a3d28 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java @@ -18,12 +18,15 @@ package com.android.wm.shell.windowdecor; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -53,6 +56,8 @@ import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.desktopmode.DesktopModeController; import com.android.wm.shell.desktopmode.DesktopTasksController; +import com.android.wm.shell.sysui.ShellController; +import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import org.junit.Before; @@ -91,6 +96,10 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase { @Mock private Supplier mTransactionFactory; @Mock private SurfaceControl.Transaction mTransaction; @Mock private Display mDisplay; + @Mock private ShellController mShellController; + @Mock private ShellInit mShellInit; + @Mock private DesktopModeWindowDecorViewModel.DesktopModeKeyguardChangeListener + mDesktopModeKeyguardChangeListener; private final List mMockInputManagers = new ArrayList<>(); private DesktopModeWindowDecorViewModel mDesktopModeWindowDecorViewModel; @@ -104,15 +113,18 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase { mContext, mMainHandler, mMainChoreographer, + mShellInit, mTaskOrganizer, mDisplayController, + mShellController, mSyncQueue, mTransitions, Optional.of(mDesktopModeController), Optional.of(mDesktopTasksController), mDesktopModeWindowDecorFactory, mMockInputMonitorFactory, - mTransactionFactory + mTransactionFactory, + mDesktopModeKeyguardChangeListener ); doReturn(mDesktopModeWindowDecoration) @@ -121,6 +133,7 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase { doReturn(mTransaction).when(mTransactionFactory).get(); doReturn(mDisplayLayout).when(mDisplayController).getDisplayLayout(anyInt()); doReturn(STABLE_INSETS).when(mDisplayLayout).stableInsets(); + doNothing().when(mShellController).addKeyguardChangeListener(any()); when(mMockInputMonitorFactory.create(any(), any())).thenReturn(mInputMonitor); // InputChannel cannot be mocked because it passes to InputEventReceiver. @@ -255,6 +268,32 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase { verify(mInputMonitor, times(1)).dispose(); } + @Test + public void testCaptionIsNotCreatedWhenKeyguardIsVisible() throws Exception { + doReturn(true).when( + mDesktopModeKeyguardChangeListener).isKeyguardVisibleAndOccluded(); + + final int taskId = 1; + final ActivityManager.RunningTaskInfo taskInfo = + createTaskInfo(taskId, Display.DEFAULT_DISPLAY, WINDOWING_MODE_FULLSCREEN); + taskInfo.isFocused = true; + SurfaceControl surfaceControl = mock(SurfaceControl.class); + runOnMainThread(() -> { + final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); + + mDesktopModeWindowDecorViewModel.onTaskOpening( + taskInfo, surfaceControl, startT, finishT); + + taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_UNDEFINED); + taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED); + mDesktopModeWindowDecorViewModel.onTaskChanging( + taskInfo, surfaceControl, startT, finishT); + }); + verify(mDesktopModeWindowDecorFactory, never()) + .create(any(), any(), any(), any(), any(), any(), any(), any()); + } + private void runOnMainThread(Runnable r) throws Exception { final Handler mainHandler = new Handler(Looper.getMainLooper()); final CountDownLatch latch = new CountDownLatch(1);