summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/res/values/ids.xml5
-rw-r--r--libs/WindowManager/Shell/res/values/strings.xml22
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt95
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt101
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt63
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java3
9 files changed, 331 insertions, 11 deletions
diff --git a/libs/WindowManager/Shell/res/values/ids.xml b/libs/WindowManager/Shell/res/values/ids.xml
index debcba071d9c..122cde04f8e4 100644
--- a/libs/WindowManager/Shell/res/values/ids.xml
+++ b/libs/WindowManager/Shell/res/values/ids.xml
@@ -46,4 +46,9 @@
<item type="id" name="action_move_bubble_bar_right"/>
<item type="id" name="dismiss_view"/>
+
+ <!-- Accessibility actions for desktop windowing. -->
+ <item type="id" name="action_snap_left"/>
+ <item type="id" name="action_snap_right"/>
+ <item type="id" name="action_maximize_restore"/>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml
index 468c345259d0..c29b927f61c2 100644
--- a/libs/WindowManager/Shell/res/values/strings.xml
+++ b/libs/WindowManager/Shell/res/values/strings.xml
@@ -333,6 +333,28 @@
<!-- Accessibility text for the Maximize Menu's snap right button [CHAR LIMIT=NONE] -->
<string name="desktop_mode_maximize_menu_snap_right_button_text">Snap right</string>
+ <!-- Accessibility text for the Maximize Menu's snap left button [CHAR LIMIT=NONE] -->
+ <string name="desktop_mode_a11y_action_snap_left">Resize app window left</string>
+ <!-- Accessibility text for the Maximize Menu's snap right button [CHAR LIMIT=NONE] -->
+ <string name="desktop_mode_a11y_action_snap_right">Resize app window right</string>
+ <!-- Accessibility text for the Maximize Menu's snap maximize/restore [CHAR LIMIT=NONE] -->
+ <string name="desktop_mode_a11y_action_maximize_restore">Maximize or restore window size</string>
+
+ <!-- Accessibility action replacement for caption handle menu split screen button [CHAR LIMIT=NONE] -->
+ <string name="app_handle_menu_talkback_split_screen_mode_button_text">Enter split screen mode</string>
+ <!-- Accessibility action replacement for caption handle menu enter desktop mode button [CHAR LIMIT=NONE] -->
+ <string name="app_handle_menu_talkback_desktop_mode_button_text">Enter desktop windowing mode</string>
+ <!-- Accessibility action replacement for maximize menu enter snap left button [CHAR LIMIT=NONE] -->
+ <string name="maximize_menu_talkback_action_snap_left_text">Resize window to left</string>
+ <!-- Accessibility action replacement for maximize menu enter snap right button [CHAR LIMIT=NONE] -->
+ <string name="maximize_menu_talkback_action_snap_right_text">Resize window to right</string>
+ <!-- Accessibility action replacement for maximize menu enter maximize/restore button [CHAR LIMIT=NONE] -->
+ <string name="maximize_menu_talkback_action_maximize_restore_text">Maximize or restore window size</string>
+ <!-- Accessibility action replacement for app header maximize/restore button [CHAR LIMIT=NONE] -->
+ <string name="maximize_button_talkback_action_maximize_restore_text">Maximize or restore window size</string>
+ <!-- Accessibility action replacement for app header minimize button [CHAR LIMIT=NONE] -->
+ <string name="minimize_button_talkback_action_maximize_restore_text">Minimize app window</string>
+
<!-- Accessibility text for open by default settings button [CHAR LIMIT=NONE] -->
<string name="open_by_default_settings_text">Open by default settings</string>
<!-- Subheader for open by default menu string. -->
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt
index 39dc48d6d206..5d8355625b94 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt
@@ -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() }
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 387dbfa807fc..b6765c477485 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -27,18 +27,17 @@ import static android.view.MotionEvent.ACTION_UP;
import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION;
import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS;
-
import static com.android.wm.shell.shared.desktopmode.DesktopModeStatus.canEnterDesktopMode;
import static com.android.wm.shell.shared.desktopmode.DesktopModeStatus.canEnterDesktopModeOrShowAppHandle;
import static com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.windowdecor.DragPositioningCallbackUtility.DragEventListener;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.DisabledEdge;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.DisabledEdge.NONE;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getFineResizeCornerSize;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getLargeResizeCornerSize;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeEdgeHandleSize;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.getResizeHandleEdgeInset;
-import static com.android.wm.shell.windowdecor.DragPositioningCallbackUtility.DragEventListener;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -112,14 +111,14 @@ import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
-import kotlinx.coroutines.CoroutineScope;
-import kotlinx.coroutines.MainCoroutineDispatcher;
-
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
+import kotlinx.coroutines.CoroutineScope;
+import kotlinx.coroutines.MainCoroutineDispatcher;
+
/**
* Defines visuals and behaviors of a window decoration of a caption bar and shadows. It works with
* {@link DesktopModeWindowDecorViewModel}.
@@ -579,6 +578,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
closeHandleMenu();
closeManageWindowsMenu();
closeMaximizeMenu();
+ notifyNoCaptionHandle();
}
updateDragResizeListener(oldDecorationSurface, inFullImmersive);
updateMaximizeMenu(startT, inFullImmersive);
@@ -717,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;
}
@@ -847,6 +846,9 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mOnCaptionButtonClickListener,
mOnCaptionLongClickListener,
mOnCaptionGenericMotionListener,
+ mOnLeftSnapClickListener,
+ mOnRightSnapClickListener,
+ mOnMaximizeOrRestoreClickListener,
mOnMaximizeHoverListener);
}
throw new IllegalArgumentException("Unexpected layout resource id");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
index 053850480ecc..32a2f8294877 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
@@ -44,6 +44,8 @@ import android.window.SurfaceSyncGroup
import androidx.annotation.StringRes
import androidx.annotation.VisibleForTesting
import androidx.compose.ui.graphics.toArgb
+import androidx.core.view.ViewCompat
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK
import androidx.core.view.isGone
import com.android.window.flags.Flags
import com.android.wm.shell.R
@@ -55,8 +57,8 @@ import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewContainer
import com.android.wm.shell.windowdecor.common.DecorThemeUtil
-import com.android.wm.shell.windowdecor.common.calculateMenuPosition
import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader
+import com.android.wm.shell.windowdecor.common.calculateMenuPosition
import com.android.wm.shell.windowdecor.extension.isFullscreen
import com.android.wm.shell.windowdecor.extension.isMultiWindow
import com.android.wm.shell.windowdecor.extension.isPinned
@@ -536,6 +538,20 @@ class HandleMenu(
}
return@setOnTouchListener true
}
+
+ with(context.resources) {
+ // Update a11y read out to say "double tap to enter desktop windowing mode"
+ ViewCompat.replaceAccessibilityAction(
+ desktopBtn, ACTION_CLICK,
+ getString(R.string.app_handle_menu_talkback_desktop_mode_button_text), null
+ )
+
+ // Update a11y read out to say "double tap to enter split screen mode"
+ ViewCompat.replaceAccessibilityAction(
+ splitscreenBtn, ACTION_CLICK,
+ getString(R.string.app_handle_menu_talkback_split_screen_mode_button_text), null
+ )
+ }
}
/** Binds the menu views to the new data. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
index 1ce0366728b9..be3ea4e7b71e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MaximizeMenu.kt
@@ -34,6 +34,7 @@ import android.graphics.drawable.LayerDrawable
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.StateListDrawable
import android.graphics.drawable.shapes.RoundRectShape
+import android.os.Bundle
import android.util.StateSet
import android.view.LayoutInflater
import android.view.MotionEvent.ACTION_HOVER_ENTER
@@ -51,12 +52,16 @@ import android.view.ViewGroup
import android.view.WindowManager
import android.view.WindowlessWindowManager
import android.view.accessibility.AccessibilityEvent
+import android.view.accessibility.AccessibilityNodeInfo
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
import android.widget.Button
import android.widget.TextView
import android.window.TaskConstants
import androidx.compose.material3.ColorScheme
import androidx.compose.ui.graphics.toArgb
import androidx.core.animation.addListener
+import androidx.core.view.ViewCompat
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import com.android.wm.shell.R
@@ -403,6 +408,96 @@ class MaximizeMenu(
true
}
+ sizeToggleButton.accessibilityDelegate = object : View.AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(AccessibilityAction.ACTION_CLICK)
+ host.isClickable = true
+ }
+
+ override fun performAccessibilityAction(
+ host: View,
+ action: Int,
+ args: Bundle?
+ ): Boolean {
+ if (action == AccessibilityAction.ACTION_CLICK.id) {
+ onMaximizeClickListener?.invoke()
+ }
+ return super.performAccessibilityAction(host, action, args)
+ }
+ }
+
+ snapLeftButton.accessibilityDelegate = object : View.AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(AccessibilityAction.ACTION_CLICK)
+ host.isClickable = true
+ }
+
+ override fun performAccessibilityAction(
+ host: View,
+ action: Int,
+ args: Bundle?
+ ): Boolean {
+ if (action == AccessibilityAction.ACTION_CLICK.id) {
+ onLeftSnapClickListener?.invoke()
+ }
+ return super.performAccessibilityAction(host, action, args)
+ }
+ }
+
+ snapRightButton.accessibilityDelegate = object : View.AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(AccessibilityAction.ACTION_CLICK)
+ host.isClickable = true
+ }
+
+ override fun performAccessibilityAction(
+ host: View,
+ action: Int,
+ args: Bundle?
+ ): Boolean {
+ if (action == AccessibilityAction.ACTION_CLICK.id) {
+ onRightSnapClickListener?.invoke()
+ }
+ return super.performAccessibilityAction(host, action, args)
+ }
+ }
+
+ with(context.resources) {
+ ViewCompat.replaceAccessibilityAction(
+ snapLeftButton,
+ AccessibilityActionCompat.ACTION_CLICK,
+ getString(R.string.maximize_menu_talkback_action_snap_left_text),
+ null
+ )
+
+ ViewCompat.replaceAccessibilityAction(
+ snapRightButton,
+ AccessibilityActionCompat.ACTION_CLICK,
+ getString(R.string.maximize_menu_talkback_action_snap_right_text),
+ null
+ )
+
+ ViewCompat.replaceAccessibilityAction(
+ sizeToggleButton,
+ AccessibilityActionCompat.ACTION_CLICK,
+ getString(R.string.maximize_menu_talkback_action_maximize_restore_text),
+ null
+ )
+ }
+
// Maximize/restore button.
val sizeToggleBtnTextId = if (sizeToggleDirection == SizeToggleDirection.RESTORE)
R.string.desktop_mode_maximize_menu_restore_button_text
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
index 9f8ca7740182..db12f899f42f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHeaderViewHolder.kt
@@ -27,10 +27,13 @@ import android.graphics.drawable.LayerDrawable
import android.graphics.drawable.RippleDrawable
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.RoundRectShape
+import android.os.Bundle
import android.view.View
import android.view.View.OnLongClickListener
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.view.accessibility.AccessibilityEvent
+import android.view.accessibility.AccessibilityNodeInfo
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
@@ -49,6 +52,8 @@ import com.android.internal.R.color.materialColorSurfaceDim
import com.android.window.flags.Flags
import com.android.wm.shell.R
import android.window.DesktopModeFlags
+import androidx.core.view.ViewCompat
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat
import com.android.wm.shell.windowdecor.MaximizeButtonView
import com.android.wm.shell.windowdecor.common.DecorThemeUtil
import com.android.wm.shell.windowdecor.common.OPACITY_100
@@ -71,7 +76,10 @@ class AppHeaderViewHolder(
onCaptionButtonClickListener: View.OnClickListener,
private val onLongClickListener: OnLongClickListener,
onCaptionGenericMotionListener: View.OnGenericMotionListener,
- onMaximizeHoverAnimationFinishedListener: () -> Unit
+ mOnLeftSnapClickListener: () -> Unit,
+ mOnRightSnapClickListener: () -> Unit,
+ mOnMaximizeOrRestoreClickListener: () -> Unit,
+ onMaximizeHoverAnimationFinishedListener: () -> Unit,
) : WindowDecorationViewHolder<AppHeaderViewHolder.HeaderData>(rootView) {
data class HeaderData(
@@ -153,6 +161,91 @@ class AppHeaderViewHolder(
minimizeWindowButton.setOnTouchListener(onCaptionTouchListener)
maximizeButtonView.onHoverAnimationFinishedListener =
onMaximizeHoverAnimationFinishedListener
+
+ val a11yActionSnapLeft = AccessibilityAction(
+ R.id.action_snap_left,
+ context.resources.getString(R.string.desktop_mode_a11y_action_snap_left)
+ )
+ val a11yActionSnapRight = AccessibilityAction(
+ R.id.action_snap_right,
+ context.resources.getString(R.string.desktop_mode_a11y_action_snap_right)
+ )
+ val a11yActionMaximizeRestore = AccessibilityAction(
+ R.id.action_maximize_restore,
+ context.resources.getString(R.string.desktop_mode_a11y_action_maximize_restore)
+ )
+
+ captionHandle.accessibilityDelegate = object : View.AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(a11yActionSnapLeft)
+ info.addAction(a11yActionSnapRight)
+ info.addAction(a11yActionMaximizeRestore)
+ }
+
+ override fun performAccessibilityAction(
+ host: View,
+ action: Int,
+ args: Bundle?
+ ): Boolean {
+ when (action) {
+ R.id.action_snap_left -> mOnLeftSnapClickListener.invoke()
+ R.id.action_snap_right -> mOnRightSnapClickListener.invoke()
+ R.id.action_maximize_restore -> mOnMaximizeOrRestoreClickListener.invoke()
+ }
+
+ return super.performAccessibilityAction(host, action, args)
+ }
+ }
+ maximizeWindowButton.accessibilityDelegate = object : View.AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(AccessibilityAction.ACTION_CLICK)
+ info.addAction(a11yActionSnapLeft)
+ info.addAction(a11yActionSnapRight)
+ info.addAction(a11yActionMaximizeRestore)
+ host.isClickable = true
+ }
+
+ override fun performAccessibilityAction(
+ host: View,
+ action: Int,
+ args: Bundle?
+ ): Boolean {
+ when (action) {
+ AccessibilityAction.ACTION_CLICK.id -> host.performClick()
+ R.id.action_snap_left -> mOnLeftSnapClickListener.invoke()
+ R.id.action_snap_right -> mOnRightSnapClickListener.invoke()
+ R.id.action_maximize_restore -> mOnMaximizeOrRestoreClickListener.invoke()
+ }
+
+ return super.performAccessibilityAction(host, action, args)
+ }
+ }
+
+ with(context.resources) {
+ // Update a11y read out to say "double tap to maximize or restore window size"
+ ViewCompat.replaceAccessibilityAction(
+ maximizeWindowButton,
+ AccessibilityActionCompat.ACTION_CLICK,
+ getString(R.string.maximize_button_talkback_action_maximize_restore_text),
+ null
+ )
+
+ // Update a11y read out to say "double tap to minimize app window"
+ ViewCompat.replaceAccessibilityAction(
+ minimizeWindowButton,
+ AccessibilityActionCompat.ACTION_CLICK,
+ getString(R.string.minimize_button_talkback_action_maximize_restore_text),
+ null
+ )
+ }
}
override fun bindData(data: HeaderData) {
@@ -628,6 +721,9 @@ class AppHeaderViewHolder(
onCaptionButtonClickListener: View.OnClickListener,
onLongClickListener: OnLongClickListener,
onCaptionGenericMotionListener: View.OnGenericMotionListener,
+ mOnLeftSnapClickListener: () -> Unit,
+ mOnRightSnapClickListener: () -> Unit,
+ mOnMaximizeOrRestoreClickListener: () -> Unit,
onMaximizeHoverAnimationFinishedListener: () -> Unit,
): AppHeaderViewHolder = AppHeaderViewHolder(
rootView,
@@ -635,6 +731,9 @@ class AppHeaderViewHolder(
onCaptionButtonClickListener,
onLongClickListener,
onCaptionGenericMotionListener,
+ mOnLeftSnapClickListener,
+ mOnRightSnapClickListener,
+ mOnMaximizeOrRestoreClickListener,
onMaximizeHoverAnimationFinishedListener,
)
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt
index 7d2a8082c43e..1160a9286572 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt
@@ -175,6 +175,64 @@ class AppHandleEducationControllerTest : ShellTestCase() {
}
@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() =
testScope.runTest {
@@ -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)
@@ -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"
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 87198d14c839..76e1e805f5a9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -297,7 +297,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
.thenReturn(mMockHandleMenu);
when(mMockMultiInstanceHelper.supportsMultiInstanceSplit(any(), anyInt()))
.thenReturn(false);
- when(mMockAppHeaderViewHolderFactory.create(any(), any(), any(), any(), any(), any()))
+ when(mMockAppHeaderViewHolderFactory
+ .create(any(), any(), any(), any(), any(), any(), any(), any(), any()))
.thenReturn(mMockAppHeaderViewHolder);
when(mMockDesktopUserRepositories.getCurrent()).thenReturn(mDesktopRepository);
when(mMockDesktopUserRepositories.getProfile(anyInt())).thenReturn(mDesktopRepository);