Loading core/java/android/window/DesktopExperienceFlags.java +2 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,8 @@ public enum DesktopExperienceFlags { ENABLE_ACTIVITY_EMBEDDING_SUPPORT_FOR_CONNECTED_DISPLAYS( Flags::enableActivityEmbeddingSupportForConnectedDisplays, true, Flags.FLAG_ENABLE_ACTIVITY_EMBEDDING_SUPPORT_FOR_CONNECTED_DISPLAYS), ENABLE_APP_HANDLE_POSITION_REPORTING(Flags::enableAppHandlePositionReporting, false, Flags.FLAG_ENABLE_APP_HANDLE_POSITION_REPORTING), ENABLE_BLOCK_NON_DESKTOP_DISPLAY_WINDOW_DRAG_BUGFIX( Flags::enableBlockNonDesktopDisplayWindowDragBugfix, false, Flags.FLAG_ENABLE_BLOCK_NON_DESKTOP_DISPLAY_WINDOW_DRAG_BUGFIX), Loading core/java/android/window/flags/lse_desktop_experience.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -1261,6 +1261,16 @@ flag { } } flag { name: "enable_app_handle_position_reporting" namespace: "lse_desktop_experience" description: "Report app handle position to the SysUi." bug: "412444130" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "enable_desktop_app_launch_bugfix" namespace: "lse_desktop_experience" Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +16 −14 Original line number Diff line number Diff line Loading @@ -123,7 +123,7 @@ import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator; import com.android.wm.shell.desktopmode.SpringDragToDesktopTransitionHandler; import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler; import com.android.wm.shell.desktopmode.VisualIndicatorUpdateScheduler; import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository; import com.android.wm.shell.desktopmode.WindowDecorCaptionRepository; import com.android.wm.shell.desktopmode.compatui.SystemModalsTransitionHandler; import com.android.wm.shell.desktopmode.desktopfirst.DesktopDisplayModeController; import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider; Loading Loading @@ -1154,7 +1154,7 @@ public abstract class WMShellModule { AppHandleEducationController appHandleEducationController, AppToWebEducationController appToWebEducationController, AppHandleAndHeaderVisibilityHelper appHandleAndHeaderVisibilityHelper, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, WindowDecorCaptionRepository windowDecorCaptionRepository, Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, Loading @@ -1167,8 +1167,7 @@ public abstract class WMShellModule { Optional<CompatUIHandler> compatUI, DesksOrganizer desksOrganizer, DesktopState desktopState, DesktopConfig desktopConfig, AppHandleNotifier appHandleNotifier DesktopConfig desktopConfig ) { if (!desktopState.canEnterDesktopModeOrShowAppHandle()) { return Optional.empty(); Loading @@ -1182,12 +1181,12 @@ public abstract class WMShellModule { rootTaskDisplayAreaOrganizer, interactionJankMonitor, genericLinksParser, assistContentRequester, windowDecorViewHostSupplier, multiInstanceHelper, desktopTasksLimiter, appHandleEducationController, appToWebEducationController, appHandleAndHeaderVisibilityHelper, windowDecorCaptionHandleRepository, appHandleAndHeaderVisibilityHelper, windowDecorCaptionRepository, activityOrientationChangeHandler, focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger, taskResourceLoader, recentsTransitionHandler, desktopModeCompatPolicy, desktopTilingDecorViewModel, multiDisplayDragMoveIndicatorController, compatUI.orElse(null), desksOrganizer, desktopState, desktopConfig, appHandleNotifier)); desksOrganizer, desktopState, desktopConfig)); } @WMSingleton Loading Loading @@ -1525,8 +1524,11 @@ public abstract class WMShellModule { @WMSingleton @Provides static AppHandleNotifier provideAppHandleNotifier( @ShellMainThread ShellExecutor shellExecutor) { return new AppHandleNotifier(shellExecutor); @ShellMainThread ShellExecutor shellExecutor, WindowDecorCaptionRepository windowDecorCaptionRepository, @ShellMainThread CoroutineScope mainScope) { return new AppHandleNotifier( shellExecutor, windowDecorCaptionRepository, mainScope); } @WMSingleton Loading @@ -1546,8 +1548,8 @@ public abstract class WMShellModule { @WMSingleton @Provides static WindowDecorCaptionHandleRepository provideAppHandleRepository() { return new WindowDecorCaptionHandleRepository(); static WindowDecorCaptionRepository provideAppHandleRepository() { return new WindowDecorCaptionRepository(); } @WMSingleton Loading Loading @@ -1582,7 +1584,7 @@ public abstract class WMShellModule { Context context, AppHandleEducationFilter appHandleEducationFilter, AppHandleEducationDatastoreRepository appHandleEducationDatastoreRepository, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, WindowDecorCaptionRepository windowDecorCaptionRepository, DesktopWindowingEducationTooltipController desktopWindowingEducationTooltipController, @ShellMainThread CoroutineScope applicationScope, @ShellBackgroundThread MainCoroutineDispatcher backgroundDispatcher, Loading @@ -1592,7 +1594,7 @@ public abstract class WMShellModule { context, appHandleEducationFilter, appHandleEducationDatastoreRepository, windowDecorCaptionHandleRepository, windowDecorCaptionRepository, desktopWindowingEducationTooltipController, applicationScope, backgroundDispatcher, Loading Loading @@ -1622,13 +1624,13 @@ public abstract class WMShellModule { Context context, AppToWebEducationFilter appToWebEducationFilter, AppToWebEducationDatastoreRepository appToWebEducationDatastoreRepository, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, WindowDecorCaptionRepository windowDecorCaptionRepository, DesktopWindowingEducationPromoController desktopWindowingEducationPromoController, @ShellMainThread CoroutineScope applicationScope, @ShellBackgroundThread MainCoroutineDispatcher backgroundDispatcher, DesktopState desktopState) { return new AppToWebEducationController(context, appToWebEducationFilter, appToWebEducationDatastoreRepository, windowDecorCaptionHandleRepository, appToWebEducationDatastoreRepository, windowDecorCaptionRepository, desktopWindowingEducationPromoController, applicationScope, backgroundDispatcher, desktopState); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/WindowDecorCaptionHandleRepository.kt→libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/WindowDecorCaptionRepository.kt +16 −4 Original line number Diff line number Diff line Loading @@ -21,13 +21,14 @@ import android.graphics.Rect import com.android.wm.shell.desktopmode.CaptionState.AppHandle import com.android.wm.shell.desktopmode.CaptionState.AppHeader import com.android.wm.shell.desktopmode.CaptionState.NoCaption import com.android.wm.shell.windowdecor.viewholder.AppHandleIdentifier import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow /** Repository to observe caption state. */ class WindowDecorCaptionHandleRepository { private val _captionStateFlow = MutableStateFlow<CaptionState>(CaptionState.NoCaption) class WindowDecorCaptionRepository { private val _captionStateFlow = MutableStateFlow<CaptionState>(NoCaption()) /** Observer for app handle state changes. */ val captionStateFlow: StateFlow<CaptionState> = _captionStateFlow private val _appToWebUsageFlow = MutableSharedFlow<Unit>() Loading @@ -51,14 +52,18 @@ class WindowDecorCaptionHandleRepository { * It can be one of three options: * * [AppHandle]: Indicating that there is at least one visible app handle on the screen. * * [AppHeader]: Indicating that there is at least one visible app chip on the screen. * * [NoCaption]: Signifying that no caption handle is currently visible on the device. * * [NoCaption]: Signifying that no caption handle visible for the given task. */ sealed class CaptionState { abstract val isFocused: Boolean data class AppHandle( val runningTaskInfo: RunningTaskInfo, val isHandleMenuExpanded: Boolean, val globalAppHandleBounds: Rect, val isCapturedLinkAvailable: Boolean, val appHandleIdentifier: AppHandleIdentifier, override val isFocused: Boolean, ) : CaptionState() data class AppHeader( Loading @@ -66,7 +71,14 @@ sealed class CaptionState { val isHeaderMenuExpanded: Boolean, val globalAppChipBounds: Rect, val isCapturedLinkAvailable: Boolean, override val isFocused: Boolean, ) : CaptionState() data object NoCaption : CaptionState() data class NoCaption(val taskId: Int = INVALID_TASK_ID) : CaptionState() { override val isFocused = false } private companion object { private const val INVALID_TASK_ID = -1 } } libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt +18 −8 Original line number Diff line number Diff line Loading @@ -23,16 +23,16 @@ import android.content.res.Resources import android.graphics.Point import android.os.SystemProperties import android.view.View.LAYOUT_DIRECTION_RTL import android.window.DesktopExperienceFlags import com.android.window.flags.Flags import com.android.wm.shell.R import com.android.wm.shell.desktopmode.CaptionState import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository import com.android.wm.shell.desktopmode.WindowDecorCaptionRepository import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository import com.android.wm.shell.shared.annotations.ShellBackgroundThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.canEnterDesktopMode import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.shared.desktopmode.DesktopState import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController Loading Loading @@ -61,7 +61,7 @@ class AppHandleEducationController( private val context: Context, private val appHandleEducationFilter: AppHandleEducationFilter, private val appHandleEducationDatastoreRepository: AppHandleEducationDatastoreRepository, private val windowDecorCaptionHandleRepository: WindowDecorCaptionHandleRepository, private val windowDecorCaptionRepository: WindowDecorCaptionRepository, private val windowingEducationViewController: DesktopWindowingEducationTooltipController, @ShellMainThread private val applicationCoroutineScope: CoroutineScope, @ShellBackgroundThread private val backgroundDispatcher: MainCoroutineDispatcher, Loading @@ -81,11 +81,12 @@ class AppHandleEducationController( // encourage users to open the app handle menu. applicationCoroutineScope.launch { if (isAppHandleHintViewed()) return@launch windowDecorCaptionHandleRepository.captionStateFlow windowDecorCaptionRepository.captionStateFlow .debounce(APP_HANDLE_EDUCATION_DELAY_MILLIS) .filter { captionState -> captionState is CaptionState.AppHandle && !captionState.isHandleMenuExpanded && isCaptionFocused(captionState) && !isAppHandleHintViewed() && appHandleEducationFilter.shouldShowDesktopModeEducation(captionState) } Loading @@ -104,11 +105,12 @@ class AppHandleEducationController( // encourage users to enter desktop mode. applicationCoroutineScope.launch { if (isEnterDesktopModeHintViewed()) return@launch windowDecorCaptionHandleRepository.captionStateFlow windowDecorCaptionRepository.captionStateFlow .debounce(ENTER_DESKTOP_MODE_EDUCATION_DELAY_MILLIS) .filter { captionState -> captionState is CaptionState.AppHandle && captionState.isHandleMenuExpanded && isCaptionFocused(captionState) && !isEnterDesktopModeHintViewed() && appHandleEducationFilter.shouldShowDesktopModeEducation(captionState) } Loading @@ -127,11 +129,12 @@ class AppHandleEducationController( // to let users know how to exit desktop mode. applicationCoroutineScope.launch { if (isExitDesktopModeHintViewed()) return@launch windowDecorCaptionHandleRepository.captionStateFlow windowDecorCaptionRepository.captionStateFlow .debounce(APP_HANDLE_EDUCATION_DELAY_MILLIS) .filter { captionState -> captionState is CaptionState.AppHeader && !captionState.isHeaderMenuExpanded && isCaptionFocused(captionState) && !isExitDesktopModeHintViewed() && appHandleEducationFilter.shouldShowDesktopModeEducation(captionState) } Loading @@ -156,9 +159,9 @@ class AppHandleEducationController( isExitDesktopModeHintViewed() ) return@launch windowDecorCaptionHandleRepository.captionStateFlow windowDecorCaptionRepository.captionStateFlow .filter { captionState -> captionState is CaptionState.NoCaption && !isCaptionFocused(captionState) && !isAppHandleHintViewed() && !isEnterDesktopModeHintViewed() && !isExitDesktopModeHintViewed() Loading @@ -174,6 +177,13 @@ class AppHandleEducationController( block() } private fun isCaptionFocused(captionState: CaptionState) = if (!DesktopExperienceFlags.ENABLE_APP_HANDLE_POSITION_REPORTING.isTrue) { captionState !is CaptionState.NoCaption } else { captionState.isFocused } private fun showEducation(captionState: CaptionState) { val appHandleBounds = (captionState as CaptionState.AppHandle).globalAppHandleBounds val taskInfo = captionState.runningTaskInfo Loading Loading
core/java/android/window/DesktopExperienceFlags.java +2 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,8 @@ public enum DesktopExperienceFlags { ENABLE_ACTIVITY_EMBEDDING_SUPPORT_FOR_CONNECTED_DISPLAYS( Flags::enableActivityEmbeddingSupportForConnectedDisplays, true, Flags.FLAG_ENABLE_ACTIVITY_EMBEDDING_SUPPORT_FOR_CONNECTED_DISPLAYS), ENABLE_APP_HANDLE_POSITION_REPORTING(Flags::enableAppHandlePositionReporting, false, Flags.FLAG_ENABLE_APP_HANDLE_POSITION_REPORTING), ENABLE_BLOCK_NON_DESKTOP_DISPLAY_WINDOW_DRAG_BUGFIX( Flags::enableBlockNonDesktopDisplayWindowDragBugfix, false, Flags.FLAG_ENABLE_BLOCK_NON_DESKTOP_DISPLAY_WINDOW_DRAG_BUGFIX), Loading
core/java/android/window/flags/lse_desktop_experience.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -1261,6 +1261,16 @@ flag { } } flag { name: "enable_app_handle_position_reporting" namespace: "lse_desktop_experience" description: "Report app handle position to the SysUi." bug: "412444130" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "enable_desktop_app_launch_bugfix" namespace: "lse_desktop_experience" Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +16 −14 Original line number Diff line number Diff line Loading @@ -123,7 +123,7 @@ import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator; import com.android.wm.shell.desktopmode.SpringDragToDesktopTransitionHandler; import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler; import com.android.wm.shell.desktopmode.VisualIndicatorUpdateScheduler; import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository; import com.android.wm.shell.desktopmode.WindowDecorCaptionRepository; import com.android.wm.shell.desktopmode.compatui.SystemModalsTransitionHandler; import com.android.wm.shell.desktopmode.desktopfirst.DesktopDisplayModeController; import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider; Loading Loading @@ -1154,7 +1154,7 @@ public abstract class WMShellModule { AppHandleEducationController appHandleEducationController, AppToWebEducationController appToWebEducationController, AppHandleAndHeaderVisibilityHelper appHandleAndHeaderVisibilityHelper, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, WindowDecorCaptionRepository windowDecorCaptionRepository, Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, Loading @@ -1167,8 +1167,7 @@ public abstract class WMShellModule { Optional<CompatUIHandler> compatUI, DesksOrganizer desksOrganizer, DesktopState desktopState, DesktopConfig desktopConfig, AppHandleNotifier appHandleNotifier DesktopConfig desktopConfig ) { if (!desktopState.canEnterDesktopModeOrShowAppHandle()) { return Optional.empty(); Loading @@ -1182,12 +1181,12 @@ public abstract class WMShellModule { rootTaskDisplayAreaOrganizer, interactionJankMonitor, genericLinksParser, assistContentRequester, windowDecorViewHostSupplier, multiInstanceHelper, desktopTasksLimiter, appHandleEducationController, appToWebEducationController, appHandleAndHeaderVisibilityHelper, windowDecorCaptionHandleRepository, appHandleAndHeaderVisibilityHelper, windowDecorCaptionRepository, activityOrientationChangeHandler, focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger, taskResourceLoader, recentsTransitionHandler, desktopModeCompatPolicy, desktopTilingDecorViewModel, multiDisplayDragMoveIndicatorController, compatUI.orElse(null), desksOrganizer, desktopState, desktopConfig, appHandleNotifier)); desksOrganizer, desktopState, desktopConfig)); } @WMSingleton Loading Loading @@ -1525,8 +1524,11 @@ public abstract class WMShellModule { @WMSingleton @Provides static AppHandleNotifier provideAppHandleNotifier( @ShellMainThread ShellExecutor shellExecutor) { return new AppHandleNotifier(shellExecutor); @ShellMainThread ShellExecutor shellExecutor, WindowDecorCaptionRepository windowDecorCaptionRepository, @ShellMainThread CoroutineScope mainScope) { return new AppHandleNotifier( shellExecutor, windowDecorCaptionRepository, mainScope); } @WMSingleton Loading @@ -1546,8 +1548,8 @@ public abstract class WMShellModule { @WMSingleton @Provides static WindowDecorCaptionHandleRepository provideAppHandleRepository() { return new WindowDecorCaptionHandleRepository(); static WindowDecorCaptionRepository provideAppHandleRepository() { return new WindowDecorCaptionRepository(); } @WMSingleton Loading Loading @@ -1582,7 +1584,7 @@ public abstract class WMShellModule { Context context, AppHandleEducationFilter appHandleEducationFilter, AppHandleEducationDatastoreRepository appHandleEducationDatastoreRepository, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, WindowDecorCaptionRepository windowDecorCaptionRepository, DesktopWindowingEducationTooltipController desktopWindowingEducationTooltipController, @ShellMainThread CoroutineScope applicationScope, @ShellBackgroundThread MainCoroutineDispatcher backgroundDispatcher, Loading @@ -1592,7 +1594,7 @@ public abstract class WMShellModule { context, appHandleEducationFilter, appHandleEducationDatastoreRepository, windowDecorCaptionHandleRepository, windowDecorCaptionRepository, desktopWindowingEducationTooltipController, applicationScope, backgroundDispatcher, Loading Loading @@ -1622,13 +1624,13 @@ public abstract class WMShellModule { Context context, AppToWebEducationFilter appToWebEducationFilter, AppToWebEducationDatastoreRepository appToWebEducationDatastoreRepository, WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository, WindowDecorCaptionRepository windowDecorCaptionRepository, DesktopWindowingEducationPromoController desktopWindowingEducationPromoController, @ShellMainThread CoroutineScope applicationScope, @ShellBackgroundThread MainCoroutineDispatcher backgroundDispatcher, DesktopState desktopState) { return new AppToWebEducationController(context, appToWebEducationFilter, appToWebEducationDatastoreRepository, windowDecorCaptionHandleRepository, appToWebEducationDatastoreRepository, windowDecorCaptionRepository, desktopWindowingEducationPromoController, applicationScope, backgroundDispatcher, desktopState); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/WindowDecorCaptionHandleRepository.kt→libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/WindowDecorCaptionRepository.kt +16 −4 Original line number Diff line number Diff line Loading @@ -21,13 +21,14 @@ import android.graphics.Rect import com.android.wm.shell.desktopmode.CaptionState.AppHandle import com.android.wm.shell.desktopmode.CaptionState.AppHeader import com.android.wm.shell.desktopmode.CaptionState.NoCaption import com.android.wm.shell.windowdecor.viewholder.AppHandleIdentifier import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow /** Repository to observe caption state. */ class WindowDecorCaptionHandleRepository { private val _captionStateFlow = MutableStateFlow<CaptionState>(CaptionState.NoCaption) class WindowDecorCaptionRepository { private val _captionStateFlow = MutableStateFlow<CaptionState>(NoCaption()) /** Observer for app handle state changes. */ val captionStateFlow: StateFlow<CaptionState> = _captionStateFlow private val _appToWebUsageFlow = MutableSharedFlow<Unit>() Loading @@ -51,14 +52,18 @@ class WindowDecorCaptionHandleRepository { * It can be one of three options: * * [AppHandle]: Indicating that there is at least one visible app handle on the screen. * * [AppHeader]: Indicating that there is at least one visible app chip on the screen. * * [NoCaption]: Signifying that no caption handle is currently visible on the device. * * [NoCaption]: Signifying that no caption handle visible for the given task. */ sealed class CaptionState { abstract val isFocused: Boolean data class AppHandle( val runningTaskInfo: RunningTaskInfo, val isHandleMenuExpanded: Boolean, val globalAppHandleBounds: Rect, val isCapturedLinkAvailable: Boolean, val appHandleIdentifier: AppHandleIdentifier, override val isFocused: Boolean, ) : CaptionState() data class AppHeader( Loading @@ -66,7 +71,14 @@ sealed class CaptionState { val isHeaderMenuExpanded: Boolean, val globalAppChipBounds: Rect, val isCapturedLinkAvailable: Boolean, override val isFocused: Boolean, ) : CaptionState() data object NoCaption : CaptionState() data class NoCaption(val taskId: Int = INVALID_TASK_ID) : CaptionState() { override val isFocused = false } private companion object { private const val INVALID_TASK_ID = -1 } }
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt +18 −8 Original line number Diff line number Diff line Loading @@ -23,16 +23,16 @@ import android.content.res.Resources import android.graphics.Point import android.os.SystemProperties import android.view.View.LAYOUT_DIRECTION_RTL import android.window.DesktopExperienceFlags import com.android.window.flags.Flags import com.android.wm.shell.R import com.android.wm.shell.desktopmode.CaptionState import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository import com.android.wm.shell.desktopmode.WindowDecorCaptionRepository import com.android.wm.shell.desktopmode.education.data.AppHandleEducationDatastoreRepository import com.android.wm.shell.shared.annotations.ShellBackgroundThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.canEnterDesktopMode import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.shared.desktopmode.DesktopState import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController Loading Loading @@ -61,7 +61,7 @@ class AppHandleEducationController( private val context: Context, private val appHandleEducationFilter: AppHandleEducationFilter, private val appHandleEducationDatastoreRepository: AppHandleEducationDatastoreRepository, private val windowDecorCaptionHandleRepository: WindowDecorCaptionHandleRepository, private val windowDecorCaptionRepository: WindowDecorCaptionRepository, private val windowingEducationViewController: DesktopWindowingEducationTooltipController, @ShellMainThread private val applicationCoroutineScope: CoroutineScope, @ShellBackgroundThread private val backgroundDispatcher: MainCoroutineDispatcher, Loading @@ -81,11 +81,12 @@ class AppHandleEducationController( // encourage users to open the app handle menu. applicationCoroutineScope.launch { if (isAppHandleHintViewed()) return@launch windowDecorCaptionHandleRepository.captionStateFlow windowDecorCaptionRepository.captionStateFlow .debounce(APP_HANDLE_EDUCATION_DELAY_MILLIS) .filter { captionState -> captionState is CaptionState.AppHandle && !captionState.isHandleMenuExpanded && isCaptionFocused(captionState) && !isAppHandleHintViewed() && appHandleEducationFilter.shouldShowDesktopModeEducation(captionState) } Loading @@ -104,11 +105,12 @@ class AppHandleEducationController( // encourage users to enter desktop mode. applicationCoroutineScope.launch { if (isEnterDesktopModeHintViewed()) return@launch windowDecorCaptionHandleRepository.captionStateFlow windowDecorCaptionRepository.captionStateFlow .debounce(ENTER_DESKTOP_MODE_EDUCATION_DELAY_MILLIS) .filter { captionState -> captionState is CaptionState.AppHandle && captionState.isHandleMenuExpanded && isCaptionFocused(captionState) && !isEnterDesktopModeHintViewed() && appHandleEducationFilter.shouldShowDesktopModeEducation(captionState) } Loading @@ -127,11 +129,12 @@ class AppHandleEducationController( // to let users know how to exit desktop mode. applicationCoroutineScope.launch { if (isExitDesktopModeHintViewed()) return@launch windowDecorCaptionHandleRepository.captionStateFlow windowDecorCaptionRepository.captionStateFlow .debounce(APP_HANDLE_EDUCATION_DELAY_MILLIS) .filter { captionState -> captionState is CaptionState.AppHeader && !captionState.isHeaderMenuExpanded && isCaptionFocused(captionState) && !isExitDesktopModeHintViewed() && appHandleEducationFilter.shouldShowDesktopModeEducation(captionState) } Loading @@ -156,9 +159,9 @@ class AppHandleEducationController( isExitDesktopModeHintViewed() ) return@launch windowDecorCaptionHandleRepository.captionStateFlow windowDecorCaptionRepository.captionStateFlow .filter { captionState -> captionState is CaptionState.NoCaption && !isCaptionFocused(captionState) && !isAppHandleHintViewed() && !isEnterDesktopModeHintViewed() && !isExitDesktopModeHintViewed() Loading @@ -174,6 +177,13 @@ class AppHandleEducationController( block() } private fun isCaptionFocused(captionState: CaptionState) = if (!DesktopExperienceFlags.ENABLE_APP_HANDLE_POSITION_REPORTING.isTrue) { captionState !is CaptionState.NoCaption } else { captionState.isFocused } private fun showEducation(captionState: CaptionState) { val appHandleBounds = (captionState as CaptionState.AppHandle).globalAppHandleBounds val taskInfo = captionState.runningTaskInfo Loading