summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Caitlin Shkuratov <caitlinshk@google.com> 2024-07-09 18:23:36 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-07-09 18:23:36 +0000
commit3432a1a9bf701e64dcdd67f0f24bc356d4f03cf1 (patch)
tree6e9549511d1ceeac4ebc6c8c4348ac34a132dfe9
parent4e82c7c66b7424b50c31ee4367bd30d790d2f486 (diff)
parentf2c0a6da1206c304e8c62fee87103757a0bd19b7 (diff)
Merge "[SB][Screen Chips] Update dialog strings." into main
-rw-r--r--packages/SystemUI/res/values/strings.xml42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/interactor/MediaRouterChipInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/model/MediaRouterCastModel.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndCastScreenToOtherDeviceDialogDelegate.kt52
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndGenericCastToOtherDeviceDialogDelegate.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/model/ProjectionChipModel.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelper.kt54
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/view/EndScreenRecordingDialogDelegate.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/view/EndShareToAppDialogDelegate.kt39
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/domian/interactor/MediaRouterChipInteractorTest.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndCastScreenToOtherDeviceDialogDelegateTest.kt127
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndGenericCastToOtherDeviceDialogDelegateTest.kt29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelperTest.kt105
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/view/EndScreenRecordingDialogDelegateTest.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/view/EndShareToAppDialogDelegateTest.kt75
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelperKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelKosmos.kt2
23 files changed, 430 insertions, 202 deletions
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 0bc2c82538c8..dee55289958e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -321,11 +321,11 @@
<!-- A toast message shown when the screen recording cannot be started due to a generic error [CHAR LIMIT=NONE] -->
<string name="screenrecord_start_error">Error starting screen recording</string>
<!-- Title for a dialog shown to the user that will let them stop recording their screen [CHAR LIMIT=50] -->
- <string name="screenrecord_stop_dialog_title">Stop recording screen?</string>
- <!-- Text telling a user that they will stop recording their screen if they click the "Stop recording" button [CHAR LIMIT=100] -->
- <string name="screenrecord_stop_dialog_message">You will stop recording your screen</string>
- <!-- Text telling a user that they will stop recording the contents of the specified [app_name] if they click the "Stop recording" button. Note that the app name will appear in bold. [CHAR LIMIT=100] -->
- <string name="screenrecord_stop_dialog_message_specific_app">You will stop recording &lt;b><xliff:g id="app_name" example="Photos App">%1$s</xliff:g>&lt;/b></string>
+ <string name="screenrecord_stop_dialog_title">Stop recording?</string>
+ <!-- Text telling a user that they're currently recording their screen [CHAR LIMIT=100] -->
+ <string name="screenrecord_stop_dialog_message">You\'re currently recording your entire screen</string>
+ <!-- Text telling a user that they're currently recording the contents of the specified [app_name]. [CHAR LIMIT=100] -->
+ <string name="screenrecord_stop_dialog_message_specific_app">You\'re currently recording <xliff:g id="app_name" example="Photos App">%1$s</xliff:g></string>
<!-- Button to stop a screen recording [CHAR LIMIT=35] -->
<string name="screenrecord_stop_dialog_button">Stop recording</string>
@@ -333,25 +333,33 @@
<string name="share_to_app_chip_accessibility_label">Sharing screen</string>
<!-- Title for a dialog shown to the user that will let them stop sharing their screen to another app on the device [CHAR LIMIT=50] -->
<string name="share_to_app_stop_dialog_title">Stop sharing screen?</string>
- <!-- Text telling a user that they will stop sharing their screen if they click the "Stop sharing" button [CHAR LIMIT=100] -->
- <string name="share_to_app_stop_dialog_message">You will stop sharing your screen</string>
- <!-- Text telling a user that they will stop sharing the contents of the specified [app_name] if they click the "Stop sharing" button. Note that the app name will appear in bold. [CHAR LIMIT=100] -->
- <string name="share_to_app_stop_dialog_message_specific_app">You will stop sharing &lt;b><xliff:g id="app_name" example="Photos App">%1$s</xliff:g>&lt;/b></string>
+ <!-- Text telling a user that they're currently sharing their entire screen to [host_app_name] (i.e. [host_app_name] can currently see all screen content) [CHAR LIMIT=150] -->
+ <string name="share_to_app_stop_dialog_message_entire_screen_with_host_app">You\'re currently sharing your entire screen with <xliff:g id="host_app_name" example="Screen Recorder App">%1$s</xliff:g></string>
+ <!-- Text telling a user that they're currently sharing their entire screen to an app (but we don't know what app) [CHAR LIMIT=150] -->
+ <string name="share_to_app_stop_dialog_message_entire_screen">You\'re currently sharing your entire screen with an app</string>
+ <!-- Text telling a user that they're currently sharing the contents of [app_being_shared_name]. (i.e. some app can currently see the content of [app_being_shared_name]). [CHAR LIMIT=150] -->
+ <string name="share_to_app_stop_dialog_message_single_app_specific">You\'re currently sharing <xliff:g id="app_being_shared_name" example="Photos App">%1$s</xliff:g></string>
+ <!-- Text telling a user that they're currently sharing their screen [CHAR LIMIT=150] -->
+ <string name="share_to_app_stop_dialog_message_single_app_generic">You\'re currently sharing an app</string>
<!-- Button to stop screen sharing [CHAR LIMIT=35] -->
<string name="share_to_app_stop_dialog_button">Stop sharing</string>
<!-- Content description for the status bar chip shown to the user when they're casting their screen to a different device [CHAR LIMIT=NONE] -->
<string name="cast_screen_to_other_device_chip_accessibility_label">Casting screen</string>
- <!-- Title for a dialog shown to the user that will let them stop casting their screen to a different device [CHAR LIMIT=50] -->
- <string name="cast_screen_to_other_device_stop_dialog_title">Stop casting screen?</string>
<!-- Title for a dialog shown to the user that will let them stop casting to a different device [CHAR LIMIT=50] -->
<string name="cast_to_other_device_stop_dialog_title">Stop casting?</string>
- <!-- Text telling a user that they will stop casting their screen to a different device if they click the "Stop casting" button [CHAR LIMIT=100] -->
- <string name="cast_screen_to_other_device_stop_dialog_message">You will stop casting your screen</string>
- <!-- Text telling a user that they will stop casting the contents of the specified [app_name] to a different device if they click the "Stop casting" button. Note that the app name will appear in bold. [CHAR LIMIT=100] -->
- <string name="cast_screen_to_other_device_stop_dialog_message_specific_app">You will stop casting &lt;b><xliff:g id="app_name" example="Photos App">%1$s</xliff:g>&lt;/b></string>
- <!-- Text telling a user that they're currently casting to a different device [CHAR LIMIT=100] -->
- <string name="cast_to_other_device_stop_dialog_message">You\'re currently casting</string>
+ <!-- Text telling a user that they're currently casting their screen to a different device. The device receiving the cast is named [device_name]. [CHAR LIMIT=150] -->
+ <string name="cast_to_other_device_stop_dialog_message_entire_screen_with_device">You\'re currently casting your entire screen to <xliff:g id="device_name" example="Living Room Device">%1$s</xliff:g></string>
+ <!-- Text telling a user that they're currently casting their screen to a nearby device. [CHAR LIMIT=150] -->
+ <string name="cast_to_other_device_stop_dialog_message_entire_screen">You\'re currently casting your entire screen to a nearby device</string>
+ <!-- Text telling a user that they're currently casting the contents of [app_being_shared_name] to a different device. The device receiving the cast is named [device_name]. [CHAR LIMIT=150] -->
+ <string name="cast_to_other_device_stop_dialog_message_specific_app_with_device">You\'re currently casting <xliff:g id="app_being_shared_name" example="Photos App">%1$s</xliff:g> to <xliff:g id="device_name" example="Living Room Device">%2$s</xliff:g></string>
+ <!-- Text telling a user that they're currently casting the contents of [app_being_shared_name] to a different device. [CHAR LIMIT=150] -->
+ <string name="cast_to_other_device_stop_dialog_message_specific_app">You\'re currently casting <xliff:g id="app_being_shared_name" example="Photos App">%1$s</xliff:g> to a nearby device</string>
+ <!-- Text telling a user that they're currently casting to a different device. The device receiving the cast is named [device_name]. [CHAR LIMIT=100] -->
+ <string name="cast_to_other_device_stop_dialog_message_generic_with_device">You\'re currently casting to <xliff:g id="device_name" example="Living Room Device">%1$s</xliff:g></string>
+ <!-- Text telling a user that they're currently casting to a nearby device [CHAR LIMIT=100] -->
+ <string name="cast_to_other_device_stop_dialog_message_generic">You\'re currently casting to a nearby device</string>
<!-- Button to stop screen casting to a different device [CHAR LIMIT=35] -->
<string name="cast_to_other_device_stop_dialog_button">Stop casting</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/interactor/MediaRouterChipInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/interactor/MediaRouterChipInteractor.kt
index 21f301c47467..6917f468ce14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/interactor/MediaRouterChipInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/interactor/MediaRouterChipInteractor.kt
@@ -49,7 +49,7 @@ constructor(
activeCastDevice
.map {
if (it != null) {
- MediaRouterCastModel.Casting
+ MediaRouterCastModel.Casting(deviceName = it.name)
} else {
MediaRouterCastModel.DoingNothing
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/model/MediaRouterCastModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/model/MediaRouterCastModel.kt
index b228922d1721..1f84d7cb60b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/model/MediaRouterCastModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/model/MediaRouterCastModel.kt
@@ -21,6 +21,10 @@ sealed interface MediaRouterCastModel {
/** MediaRouter isn't aware of any active cast. */
data object DoingNothing : MediaRouterCastModel
- /** MediaRouter has an active cast. */
- data object Casting : MediaRouterCastModel
+ /**
+ * MediaRouter has an active cast.
+ *
+ * @property deviceName the name of the device receiving the cast.
+ */
+ data class Casting(val deviceName: String?) : MediaRouterCastModel
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndCastScreenToOtherDeviceDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndCastScreenToOtherDeviceDialogDelegate.kt
index ffb20a7fd3b8..cac3f252a7e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndCastScreenToOtherDeviceDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndCastScreenToOtherDeviceDialogDelegate.kt
@@ -16,7 +16,9 @@
package com.android.systemui.statusbar.chips.casttootherdevice.ui.view
+import android.content.Context
import android.os.Bundle
+import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.casttootherdevice.ui.viewmodel.CastToOtherDeviceChipViewModel.Companion.CAST_TO_OTHER_DEVICE_ICON
import com.android.systemui.statusbar.chips.mediaprojection.domain.model.ProjectionChipModel
@@ -26,6 +28,7 @@ import com.android.systemui.statusbar.phone.SystemUIDialog
/** A dialog that lets the user stop an ongoing cast-screen-to-other-device event. */
class EndCastScreenToOtherDeviceDialogDelegate(
private val endMediaProjectionDialogHelper: EndMediaProjectionDialogHelper,
+ private val context: Context,
private val stopAction: () -> Unit,
private val state: ProjectionChipModel.Projecting,
) : SystemUIDialog.Delegate {
@@ -36,16 +39,8 @@ class EndCastScreenToOtherDeviceDialogDelegate(
override fun beforeCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
with(dialog) {
setIcon(CAST_TO_OTHER_DEVICE_ICON)
- setTitle(R.string.cast_screen_to_other_device_stop_dialog_title)
- // TODO(b/332662551): Include device name in this string.
- setMessage(
- endMediaProjectionDialogHelper.getDialogMessage(
- state.projectionState,
- genericMessageResId = R.string.cast_screen_to_other_device_stop_dialog_message,
- specificAppMessageResId =
- R.string.cast_screen_to_other_device_stop_dialog_message_specific_app,
- )
- )
+ setTitle(R.string.cast_to_other_device_stop_dialog_title)
+ setMessage(getMessage())
// No custom on-click, because the dialog will automatically be dismissed when the
// button is clicked anyway.
setNegativeButton(R.string.close_dialog_button, /* onClick= */ null)
@@ -54,4 +49,41 @@ class EndCastScreenToOtherDeviceDialogDelegate(
}
}
}
+
+ private fun getMessage(): String {
+ return if (state.projectionState is MediaProjectionState.Projecting.SingleTask) {
+ val appBeingSharedName =
+ endMediaProjectionDialogHelper.getAppName(state.projectionState)
+ if (appBeingSharedName != null && state.deviceName != null) {
+ context.getString(
+ R.string.cast_to_other_device_stop_dialog_message_specific_app_with_device,
+ appBeingSharedName,
+ state.deviceName,
+ )
+ } else if (appBeingSharedName != null) {
+ context.getString(
+ R.string.cast_to_other_device_stop_dialog_message_specific_app,
+ appBeingSharedName,
+ )
+ } else if (state.deviceName != null) {
+ context.getString(
+ R.string.cast_to_other_device_stop_dialog_message_generic_with_device,
+ state.deviceName
+ )
+ } else {
+ context.getString(R.string.cast_to_other_device_stop_dialog_message_generic)
+ }
+ } else {
+ if (state.deviceName != null) {
+ context.getString(
+ R.string.cast_to_other_device_stop_dialog_message_entire_screen_with_device,
+ state.deviceName
+ )
+ } else {
+ context.getString(
+ R.string.cast_to_other_device_stop_dialog_message_entire_screen,
+ )
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndGenericCastToOtherDeviceDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndGenericCastToOtherDeviceDialogDelegate.kt
index afe67b489abb..7dc9b255badc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndGenericCastToOtherDeviceDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndGenericCastToOtherDeviceDialogDelegate.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.chips.casttootherdevice.ui.view
+import android.content.Context
import android.os.Bundle
import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.casttootherdevice.ui.viewmodel.CastToOtherDeviceChipViewModel.Companion.CAST_TO_OTHER_DEVICE_ICON
@@ -29,6 +30,8 @@ import com.android.systemui.statusbar.phone.SystemUIDialog
*/
class EndGenericCastToOtherDeviceDialogDelegate(
private val endMediaProjectionDialogHelper: EndMediaProjectionDialogHelper,
+ private val context: Context,
+ private val deviceName: String?,
private val stopAction: () -> Unit,
) : SystemUIDialog.Delegate {
override fun createDialog(): SystemUIDialog {
@@ -36,11 +39,19 @@ class EndGenericCastToOtherDeviceDialogDelegate(
}
override fun beforeCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+ val message =
+ if (deviceName != null) {
+ context.getString(
+ R.string.cast_to_other_device_stop_dialog_message_generic_with_device,
+ deviceName,
+ )
+ } else {
+ context.getString(R.string.cast_to_other_device_stop_dialog_message_generic)
+ }
with(dialog) {
setIcon(CAST_TO_OTHER_DEVICE_ICON)
setTitle(R.string.cast_to_other_device_stop_dialog_title)
- // TODO(b/332662551): Include device name in this string.
- setMessage(R.string.cast_to_other_device_stop_dialog_message)
+ setMessage(message)
// No custom on-click, because the dialog will automatically be dismissed when the
// button is clicked anyway.
setNegativeButton(R.string.close_dialog_button, /* onClick= */ null)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt
index 2eff33610754..4183cdd4369d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModel.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.chips.casttootherdevice.ui.viewmodel
+import android.content.Context
import androidx.annotation.DrawableRes
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.common.shared.model.ContentDescription
@@ -53,6 +54,7 @@ class CastToOtherDeviceChipViewModel
@Inject
constructor(
@Application private val scope: CoroutineScope,
+ private val context: Context,
private val mediaProjectionChipInteractor: MediaProjectionChipInteractor,
private val mediaRouterChipInteractor: MediaRouterChipInteractor,
private val systemClock: SystemClock,
@@ -115,7 +117,7 @@ constructor(
// This does mean that the audio-only casting chip will *never* show a
// timer, because audio-only casting never activates the MediaProjection
// APIs and those are the only cast APIs that show a timer.
- createIconOnlyCastChip()
+ createIconOnlyCastChip(routerModel.deviceName)
}
}
}
@@ -178,7 +180,7 @@ constructor(
)
}
- private fun createIconOnlyCastChip(): OngoingActivityChipModel.Shown {
+ private fun createIconOnlyCastChip(deviceName: String?): OngoingActivityChipModel.Shown {
return OngoingActivityChipModel.Shown.IconOnly(
icon =
Icon.Resource(
@@ -188,7 +190,7 @@ constructor(
),
colors = ColorsModel.Red,
createDialogLaunchOnClickListener(
- createGenericCastToOtherDeviceDialogDelegate(),
+ createGenericCastToOtherDeviceDialogDelegate(deviceName),
dialogTransitionAnimator,
),
)
@@ -199,13 +201,16 @@ constructor(
) =
EndCastScreenToOtherDeviceDialogDelegate(
endMediaProjectionDialogHelper,
+ context,
stopAction = this::stopProjecting,
state,
)
- private fun createGenericCastToOtherDeviceDialogDelegate() =
+ private fun createGenericCastToOtherDeviceDialogDelegate(deviceName: String?) =
EndGenericCastToOtherDeviceDialogDelegate(
endMediaProjectionDialogHelper,
+ context,
+ deviceName,
stopAction = this::stopMediaRouterCasting,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt
index cda17cecbeff..ce60fab3ea6b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/interactor/MediaProjectionChipInteractor.kt
@@ -74,7 +74,8 @@ constructor(
},
{ "State: Projecting(type=$str1 hostPackage=$str2)" }
)
- ProjectionChipModel.Projecting(type, state)
+ // TODO(b/351851835): Get the device name.
+ ProjectionChipModel.Projecting(type, state, deviceName = null)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/model/ProjectionChipModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/model/ProjectionChipModel.kt
index 85682f5eb8ff..a1a5e82e808e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/model/ProjectionChipModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/domain/model/ProjectionChipModel.kt
@@ -26,10 +26,16 @@ sealed class ProjectionChipModel {
/** There is no media being projected. */
data object NotProjecting : ProjectionChipModel()
- /** Media is currently being projected. */
+ /**
+ * Media is currently being projected.
+ *
+ * @property deviceName the name of the device receiving the projection, or null if the
+ * projection is to this device (as opposed to a different device).
+ */
data class Projecting(
val type: Type,
val projectionState: MediaProjectionState.Projecting,
+ val deviceName: String?,
) : ProjectionChipModel()
enum class Type {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelper.kt
index 402306a12144..600436557efb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelper.kt
@@ -16,13 +16,8 @@
package com.android.systemui.statusbar.chips.mediaprojection.ui.view
-import android.annotation.StringRes
import android.app.ActivityManager
-import android.content.Context
import android.content.pm.PackageManager
-import android.text.Html
-import android.text.Html.FROM_HTML_MODE_LEGACY
-import android.text.TextUtils
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.statusbar.phone.SystemUIDialog
@@ -35,63 +30,38 @@ class EndMediaProjectionDialogHelper
constructor(
private val dialogFactory: SystemUIDialog.Factory,
private val packageManager: PackageManager,
- private val context: Context
) {
/** Creates a new [SystemUIDialog] using the given delegate. */
fun createDialog(delegate: SystemUIDialog.Delegate): SystemUIDialog {
return dialogFactory.create(delegate)
}
- /** See other [getDialogMessage]. */
- fun getDialogMessage(
- state: MediaProjectionState.Projecting,
- @StringRes genericMessageResId: Int,
- @StringRes specificAppMessageResId: Int,
- ): CharSequence {
+ fun getAppName(state: MediaProjectionState.Projecting): CharSequence? {
val specificTaskInfo =
if (state is MediaProjectionState.Projecting.SingleTask) {
state.task
} else {
null
}
- return getDialogMessage(specificTaskInfo, genericMessageResId, specificAppMessageResId)
+ return getAppName(specificTaskInfo)
+ }
+
+ fun getAppName(specificTaskInfo: ActivityManager.RunningTaskInfo?): CharSequence? {
+ val packageName = specificTaskInfo?.baseIntent?.component?.packageName ?: return null
+ return getAppName(packageName)
}
/**
- * Returns the message to show in the dialog based on the specific media projection state.
- *
- * @param genericMessageResId a res ID for a more generic "end projection" message
- * @param specificAppMessageResId a res ID for an "end projection" message that also lets us
- * specify which app is currently being projected.
+ * Returns the human-readable application name for the given package, or null if it couldn't be
+ * found for any reason.
*/
- fun getDialogMessage(
- specificTaskInfo: ActivityManager.RunningTaskInfo?,
- @StringRes genericMessageResId: Int,
- @StringRes specificAppMessageResId: Int,
- ): CharSequence {
- if (specificTaskInfo == null) {
- return context.getString(genericMessageResId)
- }
- val packageName =
- specificTaskInfo.baseIntent.component?.packageName
- ?: return context.getString(genericMessageResId)
+ fun getAppName(packageName: String): CharSequence? {
return try {
val appInfo = packageManager.getApplicationInfo(packageName, 0)
- val appName = appInfo.loadLabel(packageManager)
- getSpecificAppMessageText(specificAppMessageResId, appName)
+ appInfo.loadLabel(packageManager)
} catch (e: PackageManager.NameNotFoundException) {
// TODO(b/332662551): Log this error.
- context.getString(genericMessageResId)
+ null
}
}
-
- private fun getSpecificAppMessageText(
- @StringRes specificAppMessageResId: Int,
- appName: CharSequence,
- ): CharSequence {
- // https://developer.android.com/guide/topics/resources/string-resource#StylingWithHTML
- val escapedAppName = TextUtils.htmlEncode(appName.toString())
- val text = context.getString(specificAppMessageResId, escapedAppName)
- return Html.fromHtml(text, FROM_HTML_MODE_LEGACY)
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/view/EndScreenRecordingDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/view/EndScreenRecordingDialogDelegate.kt
index 9adbff9d304a..1eca827d55c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/view/EndScreenRecordingDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/view/EndScreenRecordingDialogDelegate.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.chips.screenrecord.ui.view
import android.app.ActivityManager
+import android.content.Context
import android.os.Bundle
import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.mediaprojection.ui.view.EndMediaProjectionDialogHelper
@@ -26,6 +27,7 @@ import com.android.systemui.statusbar.phone.SystemUIDialog
/** A dialog that lets the user stop an ongoing screen recording. */
class EndScreenRecordingDialogDelegate(
private val endMediaProjectionDialogHelper: EndMediaProjectionDialogHelper,
+ val context: Context,
private val stopAction: () -> Unit,
private val recordedTask: ActivityManager.RunningTaskInfo?,
) : SystemUIDialog.Delegate {
@@ -35,16 +37,18 @@ class EndScreenRecordingDialogDelegate(
}
override fun beforeCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+ val appName = endMediaProjectionDialogHelper.getAppName(recordedTask)
+ val message =
+ if (appName != null) {
+ context.getString(R.string.screenrecord_stop_dialog_message_specific_app, appName)
+ } else {
+ context.getString(R.string.screenrecord_stop_dialog_message)
+ }
+
with(dialog) {
setIcon(ScreenRecordChipViewModel.ICON)
setTitle(R.string.screenrecord_stop_dialog_title)
- setMessage(
- endMediaProjectionDialogHelper.getDialogMessage(
- recordedTask,
- genericMessageResId = R.string.screenrecord_stop_dialog_message,
- specificAppMessageResId = R.string.screenrecord_stop_dialog_message_specific_app
- )
- )
+ setMessage(message)
// No custom on-click, because the dialog will automatically be dismissed when the
// button is clicked anyway.
setNegativeButton(R.string.close_dialog_button, /* onClick= */ null)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt
index 53679f1c0a6c..df25d57315ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModel.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.chips.screenrecord.ui.viewmodel
import android.app.ActivityManager
+import android.content.Context
import androidx.annotation.DrawableRes
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.common.shared.model.ContentDescription
@@ -47,6 +48,7 @@ class ScreenRecordChipViewModel
@Inject
constructor(
@Application private val scope: CoroutineScope,
+ private val context: Context,
private val interactor: ScreenRecordChipInteractor,
private val systemClock: SystemClock,
private val endMediaProjectionDialogHelper: EndMediaProjectionDialogHelper,
@@ -90,6 +92,7 @@ constructor(
): EndScreenRecordingDialogDelegate {
return EndScreenRecordingDialogDelegate(
endMediaProjectionDialogHelper,
+ context,
stopAction = interactor::stopRecording,
recordedTask,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/view/EndShareToAppDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/view/EndShareToAppDialogDelegate.kt
index 7e7ef402b226..564f20e4b596 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/view/EndShareToAppDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/view/EndShareToAppDialogDelegate.kt
@@ -16,7 +16,9 @@
package com.android.systemui.statusbar.chips.sharetoapp.ui.view
+import android.content.Context
import android.os.Bundle
+import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.mediaprojection.domain.model.ProjectionChipModel
import com.android.systemui.statusbar.chips.mediaprojection.ui.view.EndMediaProjectionDialogHelper
@@ -26,6 +28,7 @@ import com.android.systemui.statusbar.phone.SystemUIDialog
/** A dialog that lets the user stop an ongoing share-screen-to-app event. */
class EndShareToAppDialogDelegate(
private val endMediaProjectionDialogHelper: EndMediaProjectionDialogHelper,
+ private val context: Context,
private val stopAction: () -> Unit,
private val state: ProjectionChipModel.Projecting,
) : SystemUIDialog.Delegate {
@@ -37,13 +40,7 @@ class EndShareToAppDialogDelegate(
with(dialog) {
setIcon(SHARE_TO_APP_ICON)
setTitle(R.string.share_to_app_stop_dialog_title)
- setMessage(
- endMediaProjectionDialogHelper.getDialogMessage(
- state.projectionState,
- genericMessageResId = R.string.share_to_app_stop_dialog_message,
- specificAppMessageResId = R.string.share_to_app_stop_dialog_message_specific_app
- )
- )
+ setMessage(getMessage())
// No custom on-click, because the dialog will automatically be dismissed when the
// button is clicked anyway.
setNegativeButton(R.string.close_dialog_button, /* onClick= */ null)
@@ -52,4 +49,32 @@ class EndShareToAppDialogDelegate(
}
}
}
+
+ private fun getMessage(): String {
+ return if (state.projectionState is MediaProjectionState.Projecting.SingleTask) {
+ // If a single app is being shared, use the name of the app being shared in the dialog
+ val appBeingSharedName =
+ endMediaProjectionDialogHelper.getAppName(state.projectionState)
+ if (appBeingSharedName != null) {
+ context.getString(
+ R.string.share_to_app_stop_dialog_message_single_app_specific,
+ appBeingSharedName,
+ )
+ } else {
+ context.getString(R.string.share_to_app_stop_dialog_message_single_app_generic)
+ }
+ } else {
+ // Otherwise, use the name of the app *receiving* the share
+ val hostAppName =
+ endMediaProjectionDialogHelper.getAppName(state.projectionState.hostPackage)
+ if (hostAppName != null) {
+ context.getString(
+ R.string.share_to_app_stop_dialog_message_entire_screen_with_host_app,
+ hostAppName
+ )
+ } else {
+ context.getString(R.string.share_to_app_stop_dialog_message_entire_screen)
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt
index 8aef5a4e7629..c09772068093 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModel.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.chips.sharetoapp.ui.viewmodel
+import android.content.Context
import androidx.annotation.DrawableRes
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.common.shared.model.ContentDescription
@@ -48,6 +49,7 @@ class ShareToAppChipViewModel
@Inject
constructor(
@Application private val scope: CoroutineScope,
+ private val context: Context,
private val mediaProjectionChipInteractor: MediaProjectionChipInteractor,
private val systemClock: SystemClock,
private val dialogTransitionAnimator: DialogTransitionAnimator,
@@ -97,6 +99,7 @@ constructor(
private fun createShareToAppDialogDelegate(state: ProjectionChipModel.Projecting) =
EndShareToAppDialogDelegate(
endMediaProjectionDialogHelper,
+ context,
stopAction = this::stopProjecting,
state,
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/domian/interactor/MediaRouterChipInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/domian/interactor/MediaRouterChipInteractorTest.kt
index 8a6a50dd13fc..ecb1a6d44b22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/domian/interactor/MediaRouterChipInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/domian/interactor/MediaRouterChipInteractorTest.kt
@@ -70,7 +70,7 @@ class MediaRouterChipInteractorTest : SysuiTestCase() {
}
@Test
- fun mediaRouterCastingState_connectingDevice_casting() =
+ fun mediaRouterCastingState_connectingDevice_casting_withName() =
testScope.runTest {
val latest by collectLastValue(underTest.mediaRouterCastingState)
@@ -79,17 +79,18 @@ class MediaRouterChipInteractorTest : SysuiTestCase() {
CastDevice(
state = CastDevice.CastState.Connecting,
id = "id",
- name = "name",
+ name = "My Favorite Device",
description = "desc",
origin = CastDevice.CastOrigin.MediaRouter,
)
)
- assertThat(latest).isEqualTo(MediaRouterCastModel.Casting)
+ assertThat(latest)
+ .isEqualTo(MediaRouterCastModel.Casting(deviceName = "My Favorite Device"))
}
@Test
- fun mediaRouterCastingState_connectedDevice_casting() =
+ fun mediaRouterCastingState_connectedDevice_casting_withName() =
testScope.runTest {
val latest by collectLastValue(underTest.mediaRouterCastingState)
@@ -98,13 +99,14 @@ class MediaRouterChipInteractorTest : SysuiTestCase() {
CastDevice(
state = CastDevice.CastState.Connected,
id = "id",
- name = "name",
+ name = "My Second Favorite Device",
description = "desc",
origin = CastDevice.CastOrigin.MediaRouter,
)
)
- assertThat(latest).isEqualTo(MediaRouterCastModel.Casting)
+ assertThat(latest)
+ .isEqualTo(MediaRouterCastModel.Casting(deviceName = "My Second Favorite Device"))
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndCastScreenToOtherDeviceDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndCastScreenToOtherDeviceDialogDelegateTest.kt
index e9d6f0e5537a..c8397bdf47c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndCastScreenToOtherDeviceDialogDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndCastScreenToOtherDeviceDialogDelegateTest.kt
@@ -19,8 +19,10 @@ package com.android.systemui.statusbar.chips.casttootherdevice.ui.view
import android.content.ComponentName
import android.content.DialogInterface
import android.content.Intent
+import android.content.applicationContext
import android.content.packageManager
import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.kosmos.Kosmos
@@ -68,21 +70,87 @@ class EndCastScreenToOtherDeviceDialogDelegateTest : SysuiTestCase() {
underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
- verify(sysuiDialog).setTitle(R.string.cast_screen_to_other_device_stop_dialog_title)
+ verify(sysuiDialog).setTitle(R.string.cast_to_other_device_stop_dialog_title)
}
@Test
- fun message_entireScreen() {
- createAndSetDelegate(ENTIRE_SCREEN)
+ fun message_entireScreen_unknownDevice() {
+ createAndSetDelegate(ENTIRE_SCREEN, deviceName = null)
+
+ underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
+
+ verify(sysuiDialog)
+ .setMessage(
+ context.getString(R.string.cast_to_other_device_stop_dialog_message_entire_screen)
+ )
+ }
+
+ @Test
+ fun message_entireScreen_hasDevice() {
+ createAndSetDelegate(ENTIRE_SCREEN, deviceName = "My Favorite Device")
underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
verify(sysuiDialog)
- .setMessage(context.getString(R.string.cast_screen_to_other_device_stop_dialog_message))
+ .setMessage(
+ context.getString(
+ R.string.cast_to_other_device_stop_dialog_message_entire_screen_with_device,
+ "My Favorite Device",
+ )
+ )
}
@Test
- fun message_singleTask() {
+ fun message_singleTask_unknownAppName_unknownDevice() {
+ val baseIntent =
+ Intent().apply { this.component = ComponentName("fake.task.package", "cls") }
+ whenever(kosmos.packageManager.getApplicationInfo(eq("fake.task.package"), any<Int>()))
+ .thenThrow(PackageManager.NameNotFoundException())
+
+ createAndSetDelegate(
+ MediaProjectionState.Projecting.SingleTask(
+ HOST_PACKAGE,
+ createTask(taskId = 1, baseIntent = baseIntent)
+ ),
+ deviceName = null,
+ )
+
+ underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
+
+ verify(sysuiDialog)
+ .setMessage(
+ context.getString(R.string.cast_to_other_device_stop_dialog_message_generic)
+ )
+ }
+
+ @Test
+ fun message_singleTask_unknownAppName_hasDevice() {
+ val baseIntent =
+ Intent().apply { this.component = ComponentName("fake.task.package", "cls") }
+ whenever(kosmos.packageManager.getApplicationInfo(eq("fake.task.package"), any<Int>()))
+ .thenThrow(PackageManager.NameNotFoundException())
+
+ createAndSetDelegate(
+ MediaProjectionState.Projecting.SingleTask(
+ HOST_PACKAGE,
+ createTask(taskId = 1, baseIntent = baseIntent)
+ ),
+ deviceName = "My Favorite Device",
+ )
+
+ underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
+
+ verify(sysuiDialog)
+ .setMessage(
+ context.getString(
+ R.string.cast_to_other_device_stop_dialog_message_generic_with_device,
+ "My Favorite Device",
+ )
+ )
+ }
+
+ @Test
+ fun message_singleTask_hasAppName_unknownDevice() {
val baseIntent =
Intent().apply { this.component = ComponentName("fake.task.package", "cls") }
val appInfo = mock<ApplicationInfo>()
@@ -94,16 +162,48 @@ class EndCastScreenToOtherDeviceDialogDelegateTest : SysuiTestCase() {
MediaProjectionState.Projecting.SingleTask(
HOST_PACKAGE,
createTask(taskId = 1, baseIntent = baseIntent)
+ ),
+ deviceName = null,
+ )
+
+ underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
+
+ verify(sysuiDialog)
+ .setMessage(
+ context.getString(
+ R.string.cast_to_other_device_stop_dialog_message_specific_app,
+ "Fake Package",
+ )
)
+ }
+
+ @Test
+ fun message_singleTask_hasAppName_hasDevice() {
+ val baseIntent =
+ Intent().apply { this.component = ComponentName("fake.task.package", "cls") }
+ val appInfo = mock<ApplicationInfo>()
+ whenever(appInfo.loadLabel(kosmos.packageManager)).thenReturn("Fake Package")
+ whenever(kosmos.packageManager.getApplicationInfo(eq("fake.task.package"), any<Int>()))
+ .thenReturn(appInfo)
+
+ createAndSetDelegate(
+ MediaProjectionState.Projecting.SingleTask(
+ HOST_PACKAGE,
+ createTask(taskId = 1, baseIntent = baseIntent)
+ ),
+ deviceName = "My Favorite Device",
)
underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
- // It'd be nice to use R.string.cast_screen_to_other_device_stop_dialog_message_specific_app
- // directly, but it includes the <b> tags which aren't in the returned string.
- val result = argumentCaptor<CharSequence>()
- verify(sysuiDialog).setMessage(result.capture())
- assertThat(result.firstValue.toString()).isEqualTo("You will stop casting Fake Package")
+ verify(sysuiDialog)
+ .setMessage(
+ context.getString(
+ R.string.cast_to_other_device_stop_dialog_message_specific_app_with_device,
+ "Fake Package",
+ "My Favorite Device",
+ )
+ )
}
@Test
@@ -140,14 +240,19 @@ class EndCastScreenToOtherDeviceDialogDelegateTest : SysuiTestCase() {
assertThat(kosmos.fakeMediaProjectionRepository.stopProjectingInvoked).isTrue()
}
- private fun createAndSetDelegate(state: MediaProjectionState.Projecting) {
+ private fun createAndSetDelegate(
+ state: MediaProjectionState.Projecting,
+ deviceName: String? = null,
+ ) {
underTest =
EndCastScreenToOtherDeviceDialogDelegate(
kosmos.endMediaProjectionDialogHelper,
+ kosmos.applicationContext,
stopAction = kosmos.mediaProjectionChipInteractor::stopProjecting,
ProjectionChipModel.Projecting(
ProjectionChipModel.Type.CAST_TO_OTHER_DEVICE,
state,
+ deviceName,
),
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndGenericCastToOtherDeviceDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndGenericCastToOtherDeviceDialogDelegateTest.kt
index 0af423db7db4..e6101f500ad1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndGenericCastToOtherDeviceDialogDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/view/EndGenericCastToOtherDeviceDialogDelegateTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.chips.casttootherdevice.ui.view
import android.content.DialogInterface
+import android.content.applicationContext
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
@@ -65,12 +66,30 @@ class EndGenericCastToOtherDeviceDialogDelegateTest : SysuiTestCase() {
}
@Test
- fun message() {
- createAndSetDelegate()
+ fun message_unknownDevice() {
+ createAndSetDelegate(deviceName = null)
+
+ underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
+
+ verify(sysuiDialog)
+ .setMessage(
+ context.getString(R.string.cast_to_other_device_stop_dialog_message_generic)
+ )
+ }
+
+ @Test
+ fun message_hasDevice() {
+ createAndSetDelegate(deviceName = "My Favorite Device")
underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
- verify(sysuiDialog).setMessage(R.string.cast_to_other_device_stop_dialog_message)
+ verify(sysuiDialog)
+ .setMessage(
+ context.getString(
+ R.string.cast_to_other_device_stop_dialog_message_generic_with_device,
+ "My Favorite Device",
+ )
+ )
}
@Test
@@ -122,10 +141,12 @@ class EndGenericCastToOtherDeviceDialogDelegateTest : SysuiTestCase() {
assertThat(kosmos.fakeMediaRouterRepository.lastStoppedDevice).isEqualTo(device)
}
- private fun createAndSetDelegate() {
+ private fun createAndSetDelegate(deviceName: String? = null) {
underTest =
EndGenericCastToOtherDeviceDialogDelegate(
kosmos.endMediaProjectionDialogHelper,
+ kosmos.applicationContext,
+ deviceName,
stopAction = kosmos.mediaRouterChipInteractor::stopCasting,
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelperTest.kt
index f9ad5ac46b6c..ab935fe9b631 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelperTest.kt
@@ -27,7 +27,6 @@ import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testCase
import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.mediaprojection.taskswitcher.FakeActivityTaskManager.Companion.createTask
-import com.android.systemui.res.R
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
import com.google.common.truth.Truth.assertThat
@@ -56,19 +55,15 @@ class EndMediaProjectionDialogHelperTest : SysuiTestCase() {
}
@Test
- fun getDialogMessage_entireScreen_isGenericMessage() {
+ fun getAppName_stateVersion_entireScreen_returnsNull() {
val result =
- underTest.getDialogMessage(
- MediaProjectionState.Projecting.EntireScreen("host.package"),
- R.string.accessibility_home,
- R.string.cast_screen_to_other_device_stop_dialog_message_specific_app,
- )
+ underTest.getAppName(MediaProjectionState.Projecting.EntireScreen("host.package"))
- assertThat(result).isEqualTo(context.getString(R.string.accessibility_home))
+ assertThat(result).isNull()
}
@Test
- fun getDialogMessage_singleTask_cannotFindPackage_isGenericMessage() {
+ fun getAppName_stateVersion_singleTask_cannotFindPackage_returnsNull() {
val baseIntent =
Intent().apply { this.component = ComponentName("fake.task.package", "cls") }
whenever(kosmos.packageManager.getApplicationInfo(eq("fake.task.package"), any<Int>()))
@@ -77,21 +72,16 @@ class EndMediaProjectionDialogHelperTest : SysuiTestCase() {
val projectionState =
MediaProjectionState.Projecting.SingleTask(
"host.package",
- createTask(taskId = 1, baseIntent = baseIntent)
+ createTask(taskId = 1, baseIntent = baseIntent),
)
- val result =
- underTest.getDialogMessage(
- projectionState,
- R.string.accessibility_home,
- R.string.cast_screen_to_other_device_stop_dialog_message_specific_app,
- )
+ val result = underTest.getAppName(projectionState)
- assertThat(result).isEqualTo(context.getString(R.string.accessibility_home))
+ assertThat(result).isNull()
}
@Test
- fun getDialogMessage_singleTask_findsPackage_isSpecificMessageWithAppLabel() {
+ fun getAppName_stateVersion_singleTask_findsPackage_returnsName() {
val baseIntent =
Intent().apply { this.component = ComponentName("fake.task.package", "cls") }
val appInfo = mock<ApplicationInfo>()
@@ -102,93 +92,66 @@ class EndMediaProjectionDialogHelperTest : SysuiTestCase() {
val projectionState =
MediaProjectionState.Projecting.SingleTask(
"host.package",
- createTask(taskId = 1, baseIntent = baseIntent)
+ createTask(taskId = 1, baseIntent = baseIntent),
)
- val result =
- underTest.getDialogMessage(
- projectionState,
- R.string.accessibility_home,
- R.string.cast_screen_to_other_device_stop_dialog_message_specific_app,
- )
+ val result = underTest.getAppName(projectionState)
- // It'd be nice to use the R.string resources directly, but they include the <b> tags which
- // aren't in the returned string.
- assertThat(result.toString()).isEqualTo("You will stop casting Fake Package")
+ assertThat(result).isEqualTo("Fake Package")
}
@Test
- fun getDialogMessage_nullTask_isGenericMessage() {
- val result =
- underTest.getDialogMessage(
- specificTaskInfo = null,
- R.string.accessibility_home,
- R.string.cast_screen_to_other_device_stop_dialog_message_specific_app,
- )
+ fun getAppName_taskInfoVersion_null_returnsNull() {
+ val result = underTest.getAppName(specificTaskInfo = null)
- assertThat(result).isEqualTo(context.getString(R.string.accessibility_home))
+ assertThat(result).isNull()
}
@Test
- fun getDialogMessage_withTask_cannotFindPackage_isGenericMessage() {
+ fun getAppName_taskInfoVersion_cannotFindPackage_returnsNull() {
val baseIntent =
Intent().apply { this.component = ComponentName("fake.task.package", "cls") }
whenever(kosmos.packageManager.getApplicationInfo(eq("fake.task.package"), any<Int>()))
.thenThrow(PackageManager.NameNotFoundException())
- val task = createTask(taskId = 1, baseIntent = baseIntent)
- val result =
- underTest.getDialogMessage(
- task,
- R.string.accessibility_home,
- R.string.cast_screen_to_other_device_stop_dialog_message_specific_app,
- )
+ val result = underTest.getAppName(createTask(taskId = 1, baseIntent = baseIntent))
- assertThat(result).isEqualTo(context.getString(R.string.accessibility_home))
+ assertThat(result).isNull()
}
@Test
- fun getDialogMessage_withTask_findsPackage_isSpecificMessageWithAppLabel() {
+ fun getAppName_taskInfoVersion_findsPackage_returnsName() {
val baseIntent =
Intent().apply { this.component = ComponentName("fake.task.package", "cls") }
val appInfo = mock<ApplicationInfo>()
whenever(appInfo.loadLabel(kosmos.packageManager)).thenReturn("Fake Package")
whenever(kosmos.packageManager.getApplicationInfo(eq("fake.task.package"), any<Int>()))
.thenReturn(appInfo)
- val task = createTask(taskId = 1, baseIntent = baseIntent)
- val result =
- underTest.getDialogMessage(
- task,
- R.string.accessibility_home,
- R.string.cast_screen_to_other_device_stop_dialog_message_specific_app,
- )
+ val result = underTest.getAppName(createTask(taskId = 1, baseIntent = baseIntent))
- assertThat(result.toString()).isEqualTo("You will stop casting Fake Package")
+ assertThat(result).isEqualTo("Fake Package")
}
@Test
- fun getDialogMessage_appLabelHasSpecialCharacters_isEscaped() {
- val baseIntent =
- Intent().apply { this.component = ComponentName("fake.task.package", "cls") }
+ fun getAppName_packageNameVersion_cannotFindPackage_returnsNull() {
+ whenever(kosmos.packageManager.getApplicationInfo(eq("fake.task.package"), any<Int>()))
+ .thenThrow(PackageManager.NameNotFoundException())
+
+ val result = underTest.getAppName("fake.task.package")
+
+ assertThat(result).isNull()
+ }
+
+ @Test
+ fun getAppName_packageNameVersion_findsPackage_returnsName() {
val appInfo = mock<ApplicationInfo>()
- whenever(appInfo.loadLabel(kosmos.packageManager)).thenReturn("Fake & Package <Here>")
+ whenever(appInfo.loadLabel(kosmos.packageManager)).thenReturn("Fake Package")
whenever(kosmos.packageManager.getApplicationInfo(eq("fake.task.package"), any<Int>()))
.thenReturn(appInfo)
- val projectionState =
- MediaProjectionState.Projecting.SingleTask(
- "host.package",
- createTask(taskId = 1, baseIntent = baseIntent)
- )
-
- val result =
- underTest.getDialogMessage(
- projectionState,
- R.string.accessibility_home,
- R.string.cast_screen_to_other_device_stop_dialog_message_specific_app,
- )
+ val result = underTest.getAppName("fake.task.package")
- assertThat(result.toString()).isEqualTo("You will stop casting Fake & Package <Here>")
+ assertThat(result).isEqualTo("Fake Package")
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/view/EndScreenRecordingDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/view/EndScreenRecordingDialogDelegateTest.kt
index 7e667de3619c..bfb63ac66d3d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/view/EndScreenRecordingDialogDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/screenrecord/ui/view/EndScreenRecordingDialogDelegateTest.kt
@@ -20,6 +20,7 @@ import android.app.ActivityManager
import android.content.ComponentName
import android.content.DialogInterface
import android.content.Intent
+import android.content.applicationContext
import android.content.packageManager
import android.content.pm.ApplicationInfo
import androidx.test.filters.SmallTest
@@ -95,11 +96,13 @@ class EndScreenRecordingDialogDelegateTest : SysuiTestCase() {
underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
- // It'd be nice to use R.string.screenrecord_stop_dialog_message_specific_app directly, but
- // it includes the <b> tags which aren't in the returned string.
- val result = argumentCaptor<CharSequence>()
- verify(sysuiDialog).setMessage(result.capture())
- assertThat(result.firstValue.toString()).isEqualTo("You will stop recording Fake Package")
+ verify(sysuiDialog)
+ .setMessage(
+ context.getString(
+ R.string.screenrecord_stop_dialog_message_specific_app,
+ "Fake Package",
+ )
+ )
}
@Test
@@ -140,6 +143,7 @@ class EndScreenRecordingDialogDelegateTest : SysuiTestCase() {
underTest =
EndScreenRecordingDialogDelegate(
kosmos.endMediaProjectionDialogHelper,
+ kosmos.applicationContext,
stopAction = kosmos.screenRecordChipInteractor::stopRecording,
recordedTask,
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/view/EndShareToAppDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/view/EndShareToAppDialogDelegateTest.kt
index 63c29ac81b34..bfb57c51206a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/view/EndShareToAppDialogDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/sharetoapp/ui/view/EndShareToAppDialogDelegateTest.kt
@@ -19,8 +19,10 @@ package com.android.systemui.statusbar.chips.sharetoapp.ui.view
import android.content.ComponentName
import android.content.DialogInterface
import android.content.Intent
+import android.content.applicationContext
import android.content.packageManager
import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.kosmos.Kosmos
@@ -65,6 +67,8 @@ class EndShareToAppDialogDelegateTest : SysuiTestCase() {
@Test
fun title() {
createAndSetDelegate(ENTIRE_SCREEN)
+ whenever(kosmos.packageManager.getApplicationInfo(eq(HOST_PACKAGE), any<Int>()))
+ .thenThrow(PackageManager.NameNotFoundException())
underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
@@ -72,16 +76,60 @@ class EndShareToAppDialogDelegateTest : SysuiTestCase() {
}
@Test
- fun message_entireScreen() {
+ fun message_entireScreen_unknownHostPackage() {
createAndSetDelegate(ENTIRE_SCREEN)
+ whenever(kosmos.packageManager.getApplicationInfo(eq(HOST_PACKAGE), any<Int>()))
+ .thenThrow(PackageManager.NameNotFoundException())
underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
- verify(sysuiDialog).setMessage(context.getString(R.string.share_to_app_stop_dialog_message))
+ verify(sysuiDialog)
+ .setMessage(context.getString(R.string.share_to_app_stop_dialog_message_entire_screen))
}
@Test
- fun message_singleTask() {
+ fun message_entireScreen_hasHostPackage() {
+ createAndSetDelegate(ENTIRE_SCREEN)
+ val hostAppInfo = mock<ApplicationInfo>()
+ whenever(hostAppInfo.loadLabel(kosmos.packageManager)).thenReturn("Host Package")
+ whenever(kosmos.packageManager.getApplicationInfo(eq(HOST_PACKAGE), any<Int>()))
+ .thenReturn(hostAppInfo)
+
+ underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
+
+ verify(sysuiDialog)
+ .setMessage(
+ context.getString(
+ R.string.share_to_app_stop_dialog_message_entire_screen_with_host_app,
+ "Host Package",
+ )
+ )
+ }
+
+ @Test
+ fun message_singleTask_unknownAppName() {
+ val baseIntent =
+ Intent().apply { this.component = ComponentName("fake.task.package", "cls") }
+ whenever(kosmos.packageManager.getApplicationInfo(eq("fake.task.package"), any<Int>()))
+ .thenThrow(PackageManager.NameNotFoundException())
+
+ createAndSetDelegate(
+ MediaProjectionState.Projecting.SingleTask(
+ HOST_PACKAGE,
+ createTask(taskId = 1, baseIntent = baseIntent)
+ )
+ )
+
+ underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
+
+ verify(sysuiDialog)
+ .setMessage(
+ context.getString(R.string.share_to_app_stop_dialog_message_single_app_generic)
+ )
+ }
+
+ @Test
+ fun message_singleTask_hasAppName() {
val baseIntent =
Intent().apply { this.component = ComponentName("fake.task.package", "cls") }
val appInfo = mock<ApplicationInfo>()
@@ -98,11 +146,13 @@ class EndShareToAppDialogDelegateTest : SysuiTestCase() {
underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
- // It'd be nice to use R.string.share_to_app_stop_dialog_message_specific_app directly, but
- // it includes the <b> tags which aren't in the returned string.
- val result = argumentCaptor<CharSequence>()
- verify(sysuiDialog).setMessage(result.capture())
- assertThat(result.firstValue.toString()).isEqualTo("You will stop sharing Fake Package")
+ verify(sysuiDialog)
+ .setMessage(
+ context.getString(
+ R.string.share_to_app_stop_dialog_message_single_app_specific,
+ "Fake Package",
+ )
+ )
}
@Test
@@ -118,6 +168,8 @@ class EndShareToAppDialogDelegateTest : SysuiTestCase() {
fun positiveButton() =
kosmos.testScope.runTest {
createAndSetDelegate(ENTIRE_SCREEN)
+ whenever(kosmos.packageManager.getApplicationInfo(eq(HOST_PACKAGE), any<Int>()))
+ .thenThrow(PackageManager.NameNotFoundException())
underTest.beforeCreate(sysuiDialog, /* savedInstanceState= */ null)
@@ -143,8 +195,13 @@ class EndShareToAppDialogDelegateTest : SysuiTestCase() {
underTest =
EndShareToAppDialogDelegate(
kosmos.endMediaProjectionDialogHelper,
+ kosmos.applicationContext,
stopAction = kosmos.mediaProjectionChipInteractor::stopProjecting,
- ProjectionChipModel.Projecting(ProjectionChipModel.Type.SHARE_TO_APP, state),
+ ProjectionChipModel.Projecting(
+ ProjectionChipModel.Type.SHARE_TO_APP,
+ state,
+ deviceName = null,
+ ),
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelKosmos.kt
index a8de4607e4a2..144fe26ea230 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/casttootherdevice/ui/viewmodel/CastToOtherDeviceChipViewModelKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.chips.casttootherdevice.ui.viewmodel
+import android.content.applicationContext
import com.android.systemui.animation.mockDialogTransitionAnimator
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
@@ -28,6 +29,7 @@ val Kosmos.castToOtherDeviceChipViewModel: CastToOtherDeviceChipViewModel by
Kosmos.Fixture {
CastToOtherDeviceChipViewModel(
scope = applicationCoroutineScope,
+ context = applicationContext,
mediaProjectionChipInteractor = mediaProjectionChipInteractor,
mediaRouterChipInteractor = mediaRouterChipInteractor,
systemClock = fakeSystemClock,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelperKosmos.kt
index 4f82662fa673..1ed7a4702e2c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelperKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/mediaprojection/ui/view/EndMediaProjectionDialogHelperKosmos.kt
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.chips.mediaprojection.ui.view
-import android.content.applicationContext
import android.content.packageManager
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
@@ -26,6 +25,5 @@ val Kosmos.endMediaProjectionDialogHelper: EndMediaProjectionDialogHelper by
EndMediaProjectionDialogHelper(
dialogFactory = mockSystemUIDialogFactory,
packageManager = packageManager,
- context = applicationContext,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelKosmos.kt
index 99b7ec9c9f1a..1d06947a40da 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/screenrecord/ui/viewmodel/ScreenRecordChipViewModelKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.chips.screenrecord.ui.viewmodel
+import android.content.applicationContext
import com.android.systemui.animation.mockDialogTransitionAnimator
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
@@ -27,6 +28,7 @@ val Kosmos.screenRecordChipViewModel: ScreenRecordChipViewModel by
Kosmos.Fixture {
ScreenRecordChipViewModel(
scope = applicationCoroutineScope,
+ context = applicationContext,
interactor = screenRecordChipInteractor,
endMediaProjectionDialogHelper = endMediaProjectionDialogHelper,
dialogTransitionAnimator = mockDialogTransitionAnimator,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelKosmos.kt
index 535f81a7d63e..2e475a3c6885 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/sharetoapp/ui/viewmodel/ShareToAppChipViewModelKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.chips.sharetoapp.ui.viewmodel
+import android.content.applicationContext
import com.android.systemui.animation.mockDialogTransitionAnimator
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
@@ -27,6 +28,7 @@ val Kosmos.shareToAppChipViewModel: ShareToAppChipViewModel by
Kosmos.Fixture {
ShareToAppChipViewModel(
scope = applicationCoroutineScope,
+ context = applicationContext,
mediaProjectionChipInteractor = mediaProjectionChipInteractor,
systemClock = fakeSystemClock,
endMediaProjectionDialogHelper = endMediaProjectionDialogHelper,