From f2c0a6da1206c304e8c62fee87103757a0bd19b7 Mon Sep 17 00:00:00 2001 From: Caitlin Shkuratov Date: Wed, 3 Jul 2024 15:53:04 +0000 Subject: [SB][Screen Chips] Update dialog strings. Updates include: - Share-to-app: Include which app is receiving the screen share if you're sharing your entire screen - Cast-screen-to-other-device: Include name of device receiving the cast - Removes bolding of the app name - Better fallback strings - Minor text changes Bug: 332662551 Bug: 351851835 Flag: com.android.systemui.status_bar_screen_sharing_chips Test: Share-to-app, share single app -> dialog includes name of app being shared Test: Share-to-app, entire screen -> dialog includes just name of app receiving the share Test: Cast only audio to other device -> dialog includes device name Test: Cast screen to other device, single app -> dialog includes both name of app being shared and device name Test: Cast screen to other device, entire screen -> dialog includes device name Test: Screen recording -> minor text changes Change-Id: Id9710270bafef03d5f0c4e1cece124df8fd59755 --- packages/SystemUI/res/values/strings.xml | 42 ++++--- .../domain/interactor/MediaRouterChipInteractor.kt | 2 +- .../domain/model/MediaRouterCastModel.kt | 8 +- .../EndCastScreenToOtherDeviceDialogDelegate.kt | 52 +++++++-- .../EndGenericCastToOtherDeviceDialogDelegate.kt | 15 ++- .../ui/viewmodel/CastToOtherDeviceChipViewModel.kt | 13 ++- .../interactor/MediaProjectionChipInteractor.kt | 3 +- .../domain/model/ProjectionChipModel.kt | 8 +- .../ui/view/EndMediaProjectionDialogHelper.kt | 54 ++------- .../ui/view/EndScreenRecordingDialogDelegate.kt | 18 +-- .../ui/viewmodel/ScreenRecordChipViewModel.kt | 3 + .../ui/view/EndShareToAppDialogDelegate.kt | 39 +++++-- .../ui/viewmodel/ShareToAppChipViewModel.kt | 3 + .../interactor/MediaRouterChipInteractorTest.kt | 14 ++- ...EndCastScreenToOtherDeviceDialogDelegateTest.kt | 127 +++++++++++++++++++-- ...ndGenericCastToOtherDeviceDialogDelegateTest.kt | 29 ++++- .../ui/view/EndMediaProjectionDialogHelperTest.kt | 105 ++++++----------- .../view/EndScreenRecordingDialogDelegateTest.kt | 14 ++- .../ui/view/EndShareToAppDialogDelegateTest.kt | 75 ++++++++++-- .../CastToOtherDeviceChipViewModelKosmos.kt | 2 + .../view/EndMediaProjectionDialogHelperKosmos.kt | 2 - .../viewmodel/ScreenRecordChipViewModelKosmos.kt | 2 + .../ui/viewmodel/ShareToAppChipViewModelKosmos.kt | 2 + 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 @@ Error starting screen recording - Stop recording screen? - - You will stop recording your screen - - You will stop recording <b>%1$s</b> + Stop recording? + + You\'re currently recording your entire screen + + You\'re currently recording %1$s Stop recording @@ -333,25 +333,33 @@ Sharing screen Stop sharing screen? - - You will stop sharing your screen - - You will stop sharing <b>%1$s</b> + + You\'re currently sharing your entire screen with %1$s + + You\'re currently sharing your entire screen with an app + + You\'re currently sharing %1$s + + You\'re currently sharing an app Stop sharing Casting screen - - Stop casting screen? Stop casting? - - You will stop casting your screen - - You will stop casting <b>%1$s</b> - - You\'re currently casting + + You\'re currently casting your entire screen to %1$s + + You\'re currently casting your entire screen to a nearby device + + You\'re currently casting %1$s to %2$s + + You\'re currently casting %1$s to a nearby device + + You\'re currently casting to %1$s + + You\'re currently casting to a nearby device Stop casting 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())) + .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())) + .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() @@ -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() + whenever(appInfo.loadLabel(kosmos.packageManager)).thenReturn("Fake Package") + whenever(kosmos.packageManager.getApplicationInfo(eq("fake.task.package"), any())) + .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 tags which aren't in the returned string. - val result = argumentCaptor() - 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())) @@ -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() @@ -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 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())) .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() whenever(appInfo.loadLabel(kosmos.packageManager)).thenReturn("Fake Package") whenever(kosmos.packageManager.getApplicationInfo(eq("fake.task.package"), any())) .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())) + .thenThrow(PackageManager.NameNotFoundException()) + + val result = underTest.getAppName("fake.task.package") + + assertThat(result).isNull() + } + + @Test + fun getAppName_packageNameVersion_findsPackage_returnsName() { val appInfo = mock() - whenever(appInfo.loadLabel(kosmos.packageManager)).thenReturn("Fake & Package ") + whenever(appInfo.loadLabel(kosmos.packageManager)).thenReturn("Fake Package") whenever(kosmos.packageManager.getApplicationInfo(eq("fake.task.package"), any())) .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 ") + 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 tags which aren't in the returned string. - val result = argumentCaptor() - 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())) + .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())) + .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() + whenever(hostAppInfo.loadLabel(kosmos.packageManager)).thenReturn("Host Package") + whenever(kosmos.packageManager.getApplicationInfo(eq(HOST_PACKAGE), any())) + .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())) + .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() @@ -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 tags which aren't in the returned string. - val result = argumentCaptor() - 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())) + .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, -- cgit v1.2.3-59-g8ed1b