Announce new state of modes when toggled in Modes Dialog

By setting the contentDescription at the row level.

Bug: 359845144
Test: atest ModesDialogViewModelTest + manually with TalkBack
Flag: android.app.modes_ui
Change-Id: I67c2d59fc4a23d882f123a944e10ad77e87d4d3c
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt
index d2bc54e0..827236c5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt
@@ -330,6 +330,67 @@
         }
 
     @Test
+    fun tiles_calculatesContentDescription() =
+        testScope.runTest {
+            val tiles by collectLastValue(underTest.tiles)
+
+            repository.addModes(
+                listOf(
+                    TestModeBuilder()
+                        .setName("With description, inactive")
+                        .setManualInvocationAllowed(true)
+                        .setTriggerDescription("When the going gets tough")
+                        .setActive(false)
+                        .build(),
+                    TestModeBuilder()
+                        .setName("With description, active")
+                        .setManualInvocationAllowed(true)
+                        .setTriggerDescription("When in Rome")
+                        .setActive(true)
+                        .build(),
+                    TestModeBuilder()
+                        .setName("With description, needs setup")
+                        .setManualInvocationAllowed(true)
+                        .setTriggerDescription("When you find yourself in a hole")
+                        .setEnabled(false, /* byUser= */ false)
+                        .build(),
+                    TestModeBuilder()
+                        .setName("Without description, inactive")
+                        .setManualInvocationAllowed(true)
+                        .setTriggerDescription(null)
+                        .setActive(false)
+                        .build(),
+                    TestModeBuilder()
+                        .setName("Without description, active")
+                        .setManualInvocationAllowed(true)
+                        .setTriggerDescription(null)
+                        .setActive(true)
+                        .build(),
+                    TestModeBuilder()
+                        .setName("Without description, needs setup")
+                        .setManualInvocationAllowed(true)
+                        .setTriggerDescription(null)
+                        .setEnabled(false, /* byUser= */ false)
+                        .build(),
+                )
+            )
+            runCurrent()
+
+            assertThat(tiles!!).hasSize(6)
+            assertThat(tiles!![0].contentDescription)
+                .isEqualTo("With description, inactive\nOff\nWhen the going gets tough")
+            assertThat(tiles!![1].contentDescription)
+                .isEqualTo("With description, active\nOn\nWhen in Rome")
+            assertThat(tiles!![2].contentDescription)
+                .isEqualTo("With description, needs setup\nSet up")
+            assertThat(tiles!![3].contentDescription)
+                .isEqualTo("Without description, inactive\nOff")
+            assertThat(tiles!![4].contentDescription).isEqualTo("Without description, active\nOn")
+            assertThat(tiles!![5].contentDescription)
+                .isEqualTo("Without description, needs setup\nSet up")
+        }
+
+    @Test
     fun onClick_togglesTileState() =
         testScope.runTest {
             val tiles by collectLastValue(underTest.tiles)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
index 3fffd9f..8b50f84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
@@ -33,6 +33,9 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.clearAndSetSemantics
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.unit.dp
 import com.android.systemui.common.ui.compose.Icon
@@ -58,7 +61,9 @@
                             onClick = viewModel.onClick,
                             onLongClick = viewModel.onLongClick
                         )
-                        .padding(20.dp),
+                        .padding(20.dp)
+                        .semantics(mergeDescendants = true) {}
+                        .clearAndSetSemantics { contentDescription = viewModel.contentDescription },
                 verticalAlignment = Alignment.CenterVertically,
                 horizontalArrangement =
                     Arrangement.spacedBy(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModeTileViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModeTileViewModel.kt
index 7c1cb6a..921d79b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModeTileViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModeTileViewModel.kt
@@ -28,6 +28,7 @@
     val icon: Icon,
     val text: String,
     val subtext: String,
+    val contentDescription: String,
     val enabled: Boolean,
     val onClick: () -> Unit,
     val onLongClick: () -> Unit,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
index 16c18dd8c..38bade0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
@@ -89,8 +89,9 @@
                     ModeTileViewModel(
                         id = mode.id,
                         icon = zenModeInteractor.getModeIcon(mode, context),
-                        text = mode.rule.name,
+                        text = mode.name,
                         subtext = getTileSubtext(mode),
+                        contentDescription = getTileContentDescription(mode),
                         enabled = mode.isActive,
                         onClick = {
                             if (!mode.rule.isEnabled) {
@@ -147,6 +148,25 @@
         }
     }
 
+    private fun getTileContentDescription(mode: ZenMode): String {
+        return buildList {
+                add(mode.name)
+                if (!mode.rule.isEnabled) {
+                    add(context.getString(R.string.zen_mode_set_up))
+                } else if (!mode.rule.isManualInvocationAllowed && !mode.isActive) {
+                    add(context.getString(R.string.zen_mode_no_manual_invocation))
+                } else {
+                    add(
+                        context.getString(
+                            if (mode.isActive) R.string.zen_mode_on else R.string.zen_mode_off
+                        )
+                    )
+                    mode.getDynamicDescription(context)?.let { add(it) }
+                }
+            }
+            .joinToString(separator = "\n")
+    }
+
     private fun makeZenModeDialog(): Dialog {
         val dialog =
             EnableZenModeDialog(