Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt +21 −0 Original line number Diff line number Diff line Loading @@ -140,6 +140,27 @@ class AppHandleEducationController( windowingEducationViewController.hideEducationTooltip() } } // Listens to a [NoCaption] state change to dismiss any tooltip if the app handle or app // header is gone or de-focused (e.g. when a user swipes up to home, overview, or enters // split screen) applicationCoroutineScope.launch { if ( isAppHandleHintViewed() && isEnterDesktopModeHintViewed() && isExitDesktopModeHintViewed() ) return@launch windowDecorCaptionHandleRepository.captionStateFlow .filter { captionState -> captionState is CaptionState.NoCaption && !isAppHandleHintViewed() && !isEnterDesktopModeHintViewed() && !isExitDesktopModeHintViewed() } .flowOn(backgroundDispatcher) .collectLatest { windowingEducationViewController.hideEducationTooltip() } } } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +1 −1 Original line number Diff line number Diff line Loading @@ -578,6 +578,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin closeHandleMenu(); closeManageWindowsMenu(); closeMaximizeMenu(); notifyNoCaptionHandle(); } updateDragResizeListener(oldDecorationSurface, inFullImmersive); updateMaximizeMenu(startT, inFullImmersive); Loading Loading @@ -716,7 +717,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } private void notifyCaptionStateChanged() { // TODO: b/366159408 - Ensure bounds sent with notification account for RTL mode. if (!canEnterDesktopMode(mContext) || !isEducationEnabled()) { return; } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt +61 −2 Original line number Diff line number Diff line Loading @@ -174,6 +174,64 @@ class AppHandleEducationControllerTest : ShellTestCase() { .updateExitDesktopModeHintViewedTimestampMillis(eq(true)) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun init_noCaptionStateNotified_shouldHideAllTooltips() = testScope.runTest { setShouldShowDesktopModeEducation(true) // Simulate no caption state notification testCaptionStateFlow.value = CaptionState.NoCaption waitForBufferDelay() verify(mockTooltipController, times(1)).hideEducationTooltip() } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun init_appHandleHintViewed_shouldNotListenToNoCaptionNotification() = testScope.runTest { testDataStoreFlow.value = createWindowingEducationProto(appHandleHintViewedTimestampMillis = 123L) setShouldShowDesktopModeEducation(true) // Simulate no caption state notification testCaptionStateFlow.value = CaptionState.NoCaption waitForBufferDelay() verify(mockTooltipController, never()).hideEducationTooltip() } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun init_enterDesktopModeHintViewed_shouldNotListenToNoCaptionNotification() = testScope.runTest { testDataStoreFlow.value = createWindowingEducationProto(enterDesktopModeHintViewedTimestampMillis = 123L) setShouldShowDesktopModeEducation(true) // Simulate no caption state notification testCaptionStateFlow.value = CaptionState.NoCaption waitForBufferDelay() verify(mockTooltipController, never()).hideEducationTooltip() } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun init_exitDesktopModeHintViewed_shouldNotListenToNoCaptionNotification() = testScope.runTest { testDataStoreFlow.value = createWindowingEducationProto(exitDesktopModeHintViewedTimestampMillis = 123L) setShouldShowDesktopModeEducation(true) // Simulate no caption state notification testCaptionStateFlow.value = CaptionState.NoCaption waitForBufferDelay() verify(mockTooltipController, never()).hideEducationTooltip() } @Test @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun init_flagDisabled_shouldNotCallShowEducationTooltip() = Loading Loading @@ -289,8 +347,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { // Mark app handle hint viewed. testDataStoreFlow.value = createWindowingEducationProto(appHandleHintViewedTimestampMillis = 123L) val systemPropertiesKey = "persist.windowing_force_show_desktop_mode_education" whenever(SystemProperties.getBoolean(eq(systemPropertiesKey), anyBoolean())) whenever(SystemProperties.getBoolean(eq(FORCE_SHOW_EDUCATION_SYSPROP), anyBoolean())) .thenReturn(true) setShouldShowDesktopModeEducation(true) Loading Loading @@ -396,5 +453,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { private companion object { val APP_HANDLE_EDUCATION_DELAY_BUFFER_MILLIS: Long = APP_HANDLE_EDUCATION_DELAY_MILLIS + 1000L val FORCE_SHOW_EDUCATION_SYSPROP = "persist.windowing_force_show_desktop_mode_education" } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt +21 −0 Original line number Diff line number Diff line Loading @@ -140,6 +140,27 @@ class AppHandleEducationController( windowingEducationViewController.hideEducationTooltip() } } // Listens to a [NoCaption] state change to dismiss any tooltip if the app handle or app // header is gone or de-focused (e.g. when a user swipes up to home, overview, or enters // split screen) applicationCoroutineScope.launch { if ( isAppHandleHintViewed() && isEnterDesktopModeHintViewed() && isExitDesktopModeHintViewed() ) return@launch windowDecorCaptionHandleRepository.captionStateFlow .filter { captionState -> captionState is CaptionState.NoCaption && !isAppHandleHintViewed() && !isEnterDesktopModeHintViewed() && !isExitDesktopModeHintViewed() } .flowOn(backgroundDispatcher) .collectLatest { windowingEducationViewController.hideEducationTooltip() } } } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +1 −1 Original line number Diff line number Diff line Loading @@ -578,6 +578,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin closeHandleMenu(); closeManageWindowsMenu(); closeMaximizeMenu(); notifyNoCaptionHandle(); } updateDragResizeListener(oldDecorationSurface, inFullImmersive); updateMaximizeMenu(startT, inFullImmersive); Loading Loading @@ -716,7 +717,6 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } private void notifyCaptionStateChanged() { // TODO: b/366159408 - Ensure bounds sent with notification account for RTL mode. if (!canEnterDesktopMode(mContext) || !isEducationEnabled()) { return; } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt +61 −2 Original line number Diff line number Diff line Loading @@ -174,6 +174,64 @@ class AppHandleEducationControllerTest : ShellTestCase() { .updateExitDesktopModeHintViewedTimestampMillis(eq(true)) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun init_noCaptionStateNotified_shouldHideAllTooltips() = testScope.runTest { setShouldShowDesktopModeEducation(true) // Simulate no caption state notification testCaptionStateFlow.value = CaptionState.NoCaption waitForBufferDelay() verify(mockTooltipController, times(1)).hideEducationTooltip() } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun init_appHandleHintViewed_shouldNotListenToNoCaptionNotification() = testScope.runTest { testDataStoreFlow.value = createWindowingEducationProto(appHandleHintViewedTimestampMillis = 123L) setShouldShowDesktopModeEducation(true) // Simulate no caption state notification testCaptionStateFlow.value = CaptionState.NoCaption waitForBufferDelay() verify(mockTooltipController, never()).hideEducationTooltip() } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun init_enterDesktopModeHintViewed_shouldNotListenToNoCaptionNotification() = testScope.runTest { testDataStoreFlow.value = createWindowingEducationProto(enterDesktopModeHintViewedTimestampMillis = 123L) setShouldShowDesktopModeEducation(true) // Simulate no caption state notification testCaptionStateFlow.value = CaptionState.NoCaption waitForBufferDelay() verify(mockTooltipController, never()).hideEducationTooltip() } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun init_exitDesktopModeHintViewed_shouldNotListenToNoCaptionNotification() = testScope.runTest { testDataStoreFlow.value = createWindowingEducationProto(exitDesktopModeHintViewedTimestampMillis = 123L) setShouldShowDesktopModeEducation(true) // Simulate no caption state notification testCaptionStateFlow.value = CaptionState.NoCaption waitForBufferDelay() verify(mockTooltipController, never()).hideEducationTooltip() } @Test @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) fun init_flagDisabled_shouldNotCallShowEducationTooltip() = Loading Loading @@ -289,8 +347,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { // Mark app handle hint viewed. testDataStoreFlow.value = createWindowingEducationProto(appHandleHintViewedTimestampMillis = 123L) val systemPropertiesKey = "persist.windowing_force_show_desktop_mode_education" whenever(SystemProperties.getBoolean(eq(systemPropertiesKey), anyBoolean())) whenever(SystemProperties.getBoolean(eq(FORCE_SHOW_EDUCATION_SYSPROP), anyBoolean())) .thenReturn(true) setShouldShowDesktopModeEducation(true) Loading Loading @@ -396,5 +453,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { private companion object { val APP_HANDLE_EDUCATION_DELAY_BUFFER_MILLIS: Long = APP_HANDLE_EDUCATION_DELAY_MILLIS + 1000L val FORCE_SHOW_EDUCATION_SYSPROP = "persist.windowing_force_show_desktop_mode_education" } }