[Media TTT] Use the app's package name to fetch the icon content

description.

Fixes: 217418566
Test: manual -- verify contentDescription of icon is "System UI"
Test: media.taptotransfer tests
Change-Id: I59ef37d2ba064f1bc51f9d64c716360ba883d8fc
This commit is contained in:
Caitlin Cassidy
2022-02-08 18:58:28 +00:00
parent bfa7f8af0a
commit 2e21b11a25
9 changed files with 66 additions and 87 deletions

View File

@@ -101,8 +101,8 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>(
* This is in the common superclass since both the sender and the receiver show an icon.
*/
internal fun setIcon(chipState: T, currentChipView: ViewGroup) {
val appIconView = currentChipView.findViewById<CachingIconView>(R.id.app_icon)
appIconView.contentDescription = chipState.appIconContentDescription
val appIconView = currentChipView.requireViewById<CachingIconView>(R.id.app_icon)
appIconView.contentDescription = chipState.getAppName(context)
val appIcon = chipState.getAppIcon(context)
val visibility = if (appIcon != null) {

View File

@@ -25,12 +25,10 @@ import android.util.Log
* A superclass chip state that will be subclassed by the sender chip and receiver chip.
*
* @property appPackageName the package name of the app playing the media. Will be used to fetch the
* app icon.
* @property appIconContentDescription a string to use as the content description for the icon.
* app icon and app name.
*/
open class MediaTttChipState(
internal val appPackageName: String?,
internal val appIconContentDescription: String
) {
fun getAppIcon(context: Context): Drawable? {
appPackageName ?: return null
@@ -41,6 +39,19 @@ open class MediaTttChipState(
null
}
}
/** Returns the name of the app playing the media or null if we can't find it. */
fun getAppName(context: Context): String? {
appPackageName ?: return null
return try {
context.packageManager.getApplicationInfo(
appPackageName, PackageManager.ApplicationInfoFlags.of(0)
).loadLabel(context.packageManager).toString()
} catch (e: PackageManager.NameNotFoundException) {
Log.w(TAG, "Cannot find name for package $appPackageName", e)
null
}
}
}
private val TAG = MediaTttChipState::class.simpleName!!

View File

@@ -24,5 +24,4 @@ import com.android.systemui.media.taptotransfer.common.MediaTttChipState
*/
class ChipStateReceiver(
appPackageName: String?,
appIconContentDescription: String
) : MediaTttChipState(appPackageName, appIconContentDescription)
) : MediaTttChipState(appPackageName)

View File

@@ -62,7 +62,7 @@ class MediaTttChipControllerReceiver @Inject constructor(
) {
when(displayState) {
StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER ->
displayChip(ChipStateReceiver(routeInfo.packageName, routeInfo.name.toString()))
displayChip(ChipStateReceiver(routeInfo.packageName))
StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER -> removeChip()
else ->
Log.e(RECEIVER_TAG, "Unhandled MediaTransferReceiverState $displayState")
@@ -74,4 +74,4 @@ class MediaTttChipControllerReceiver @Inject constructor(
}
}
private const val RECEIVER_TAG = "MediaTapToTransferReceiver"
private const val RECEIVER_TAG = "MediaTapToTransferRcvr"

View File

@@ -30,9 +30,8 @@ import com.android.systemui.media.taptotransfer.common.MediaTttChipState
* contain additional information that is necessary for only that state.
*/
sealed class ChipStateSender(
appPackageName: String?,
appIconContentDescription: String
) : MediaTttChipState(appPackageName, appIconContentDescription) {
appPackageName: String?
) : MediaTttChipState(appPackageName) {
/** Returns a fully-formed string with the text that the chip should display. */
abstract fun getChipTextString(context: Context): String
@@ -60,9 +59,8 @@ sealed class ChipStateSender(
*/
class AlmostCloseToStartCast(
appPackageName: String?,
appIconContentDescription: String,
private val otherDeviceName: String,
) : ChipStateSender(appPackageName, appIconContentDescription) {
) : ChipStateSender(appPackageName) {
override fun getChipTextString(context: Context): String {
return context.getString(R.string.media_move_closer_to_start_cast, otherDeviceName)
}
@@ -77,9 +75,8 @@ class AlmostCloseToStartCast(
*/
class AlmostCloseToEndCast(
appPackageName: String?,
appIconContentDescription: String,
private val otherDeviceName: String,
) : ChipStateSender(appPackageName, appIconContentDescription) {
) : ChipStateSender(appPackageName) {
override fun getChipTextString(context: Context): String {
return context.getString(R.string.media_move_closer_to_end_cast, otherDeviceName)
}
@@ -93,9 +90,8 @@ class AlmostCloseToEndCast(
*/
class TransferToReceiverTriggered(
appPackageName: String?,
appIconContentDescription: String,
private val otherDeviceName: String
) : ChipStateSender(appPackageName, appIconContentDescription) {
) : ChipStateSender(appPackageName) {
override fun getChipTextString(context: Context): String {
return context.getString(R.string.media_transfer_playing_different_device, otherDeviceName)
}
@@ -109,8 +105,7 @@ class TransferToReceiverTriggered(
*/
class TransferToThisDeviceTriggered(
appPackageName: String?,
appIconContentDescription: String
) : ChipStateSender(appPackageName, appIconContentDescription) {
) : ChipStateSender(appPackageName) {
override fun getChipTextString(context: Context): String {
return context.getString(R.string.media_transfer_playing_this_device)
}
@@ -127,10 +122,9 @@ class TransferToThisDeviceTriggered(
*/
class TransferToReceiverSucceeded(
appPackageName: String?,
appIconContentDescription: String,
private val otherDeviceName: String,
val undoCallback: IUndoMediaTransferCallback? = null
) : ChipStateSender(appPackageName, appIconContentDescription) {
) : ChipStateSender(appPackageName) {
override fun getChipTextString(context: Context): String {
return context.getString(R.string.media_transfer_playing_different_device, otherDeviceName)
}
@@ -148,10 +142,7 @@ class TransferToReceiverSucceeded(
// but that may take too long to go through the binder and the user may be confused as
// to why the UI hasn't changed yet. So, we immediately change the UI here.
controllerSender.displayChip(
TransferToThisDeviceTriggered(
this.appPackageName,
this.appIconContentDescription
)
TransferToThisDeviceTriggered(this.appPackageName)
)
}
}
@@ -166,10 +157,9 @@ class TransferToReceiverSucceeded(
*/
class TransferToThisDeviceSucceeded(
appPackageName: String?,
appIconContentDescription: String,
private val otherDeviceName: String,
val undoCallback: IUndoMediaTransferCallback? = null
) : ChipStateSender(appPackageName, appIconContentDescription) {
) : ChipStateSender(appPackageName) {
override fun getChipTextString(context: Context): String {
return context.getString(R.string.media_transfer_playing_this_device)
}
@@ -189,7 +179,6 @@ class TransferToThisDeviceSucceeded(
controllerSender.displayChip(
TransferToReceiverTriggered(
this.appPackageName,
this.appIconContentDescription,
this.otherDeviceName
)
)
@@ -200,8 +189,7 @@ class TransferToThisDeviceSucceeded(
/** A state representing that a transfer has failed. */
class TransferFailed(
appPackageName: String?,
appIconContentDescription: String
) : ChipStateSender(appPackageName, appIconContentDescription) {
) : ChipStateSender(appPackageName) {
override fun getChipTextString(context: Context): String {
return context.getString(R.string.media_transfer_failed)
}

View File

@@ -64,47 +64,24 @@ class MediaTttChipControllerSender @Inject constructor(
routeInfo: MediaRoute2Info,
undoCallback: IUndoMediaTransferCallback?
) {
// TODO(b/217418566): This app icon content description is incorrect --
// routeInfo.name is the name of the device, not the name of the app.
val appIconContentDescription = routeInfo.name.toString()
val appPackageName = routeInfo.packageName
val otherDeviceName = routeInfo.name.toString()
val chipState = when(displayState) {
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST ->
AlmostCloseToStartCast(
appPackageName, appIconContentDescription, otherDeviceName
)
AlmostCloseToStartCast(appPackageName, otherDeviceName)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST ->
AlmostCloseToEndCast(
appPackageName, appIconContentDescription, otherDeviceName
)
AlmostCloseToEndCast(appPackageName, otherDeviceName)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED ->
TransferToReceiverTriggered(
appPackageName, appIconContentDescription, otherDeviceName
)
TransferToReceiverTriggered(appPackageName, otherDeviceName)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED ->
TransferToThisDeviceTriggered(
appPackageName, appIconContentDescription
)
TransferToThisDeviceTriggered(appPackageName)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED ->
TransferToReceiverSucceeded(
appPackageName,
appIconContentDescription,
otherDeviceName,
undoCallback
)
TransferToReceiverSucceeded(appPackageName, otherDeviceName, undoCallback)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED ->
TransferToThisDeviceSucceeded(
appPackageName,
appIconContentDescription,
otherDeviceName,
undoCallback
)
TransferToThisDeviceSucceeded(appPackageName, otherDeviceName, undoCallback)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED,
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED ->
TransferFailed(
appPackageName, appIconContentDescription
)
TransferFailed(appPackageName)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER -> {
removeChip()
null

View File

@@ -92,16 +92,16 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() {
fun setIcon_viewHasIconAndContentDescription() {
controllerCommon.displayChip(getState())
val chipView = getChipView()
val contentDescription = "test description"
val state = MediaTttChipState(PACKAGE_NAME, contentDescription)
val state = MediaTttChipState(PACKAGE_NAME)
controllerCommon.setIcon(state, chipView)
assertThat(chipView.getAppIconView().drawable).isEqualTo(state.getAppIcon(context))
assertThat(chipView.getAppIconView().contentDescription).isEqualTo(contentDescription)
assertThat(chipView.getAppIconView().contentDescription)
.isEqualTo(state.getAppName(context))
}
private fun getState() = MediaTttChipState(PACKAGE_NAME, APP_ICON_CONTENT_DESCRIPTION)
private fun getState() = MediaTttChipState(PACKAGE_NAME)
private fun getChipView(): ViewGroup {
val viewCaptor = ArgumentCaptor.forClass(View::class.java)
@@ -123,4 +123,3 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() {
}
private const val PACKAGE_NAME = "com.android.systemui"
private const val APP_ICON_CONTENT_DESCRIPTION = "Content description"

View File

@@ -17,7 +17,6 @@
package com.android.systemui.media.taptotransfer.receiver
import android.app.StatusBarManager
import android.graphics.drawable.Icon
import android.media.MediaRoute2Info
import android.view.View
import android.view.ViewGroup
@@ -98,13 +97,13 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() {
@Test
fun displayChip_chipContainsIcon() {
val drawable = Icon.createWithResource(context, R.drawable.ic_cake).loadDrawable(context)
val contentDescription = "Test description"
val state = ChipStateReceiver(PACKAGE_NAME)
controllerReceiver.displayChip(ChipStateReceiver(PACKAGE_NAME, contentDescription))
controllerReceiver.displayChip(state)
assertThat(getChipView().getAppIconView().drawable).isEqualTo(drawable)
assertThat(getChipView().getAppIconView().contentDescription).isEqualTo(contentDescription)
assertThat(getChipView().getAppIconView().drawable).isEqualTo(state.getAppIcon(context))
assertThat(getChipView().getAppIconView().contentDescription)
.isEqualTo(state.getAppName(context))
}
private fun getChipView(): ViewGroup {

View File

@@ -193,7 +193,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(state.getAppIcon(context))
assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_ICON_CONTENT_DESC)
assertThat(chipView.getAppIconView().contentDescription)
.isEqualTo(state.getAppName(context))
assertThat(chipView.getChipText()).isEqualTo(state.getChipTextString(context))
assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.GONE)
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
@@ -207,7 +208,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(state.getAppIcon(context))
assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_ICON_CONTENT_DESC)
assertThat(chipView.getAppIconView().contentDescription)
.isEqualTo(state.getAppName(context))
assertThat(chipView.getChipText()).isEqualTo(state.getChipTextString(context))
assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.GONE)
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
@@ -221,7 +223,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(state.getAppIcon(context))
assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_ICON_CONTENT_DESC)
assertThat(chipView.getAppIconView().contentDescription)
.isEqualTo(state.getAppName(context))
assertThat(chipView.getChipText()).isEqualTo(state.getChipTextString(context))
assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.VISIBLE)
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
@@ -235,7 +238,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(state.getAppIcon(context))
assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_ICON_CONTENT_DESC)
assertThat(chipView.getAppIconView().contentDescription)
.isEqualTo(state.getAppName(context))
assertThat(chipView.getChipText()).isEqualTo(state.getChipTextString(context))
assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.VISIBLE)
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
@@ -249,7 +253,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(state.getAppIcon(context))
assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_ICON_CONTENT_DESC)
assertThat(chipView.getAppIconView().contentDescription)
.isEqualTo(state.getAppName(context))
assertThat(chipView.getChipText()).isEqualTo(state.getChipTextString(context))
assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.GONE)
assertThat(chipView.getFailureIcon().visibility).isEqualTo(View.GONE)
@@ -310,7 +315,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(state.getAppIcon(context))
assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_ICON_CONTENT_DESC)
assertThat(chipView.getAppIconView().contentDescription)
.isEqualTo(state.getAppName(context))
assertThat(chipView.getChipText()).isEqualTo(state.getChipTextString(context))
assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.GONE)
assertThat(chipView.getFailureIcon().visibility).isEqualTo(View.GONE)
@@ -371,7 +377,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
val chipView = getChipView()
assertThat(chipView.getAppIconView().drawable).isEqualTo(state.getAppIcon(context))
assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_ICON_CONTENT_DESC)
assertThat(chipView.getAppIconView().contentDescription)
.isEqualTo(state.getAppName(context))
assertThat(chipView.getChipText()).isEqualTo(state.getChipTextString(context))
assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.GONE)
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
@@ -444,38 +451,37 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
/** Helper method providing default parameters to not clutter up the tests. */
private fun almostCloseToStartCast() =
AlmostCloseToStartCast(PACKAGE_NAME, APP_ICON_CONTENT_DESC, DEVICE_NAME)
AlmostCloseToStartCast(PACKAGE_NAME, DEVICE_NAME)
/** Helper method providing default parameters to not clutter up the tests. */
private fun almostCloseToEndCast() =
AlmostCloseToEndCast(PACKAGE_NAME, APP_ICON_CONTENT_DESC, DEVICE_NAME)
AlmostCloseToEndCast(PACKAGE_NAME, DEVICE_NAME)
/** Helper method providing default parameters to not clutter up the tests. */
private fun transferToReceiverTriggered() =
TransferToReceiverTriggered(PACKAGE_NAME, APP_ICON_CONTENT_DESC, DEVICE_NAME)
TransferToReceiverTriggered(PACKAGE_NAME, DEVICE_NAME)
/** Helper method providing default parameters to not clutter up the tests. */
private fun transferToThisDeviceTriggered() =
TransferToThisDeviceTriggered(PACKAGE_NAME, APP_ICON_CONTENT_DESC)
TransferToThisDeviceTriggered(PACKAGE_NAME)
/** Helper method providing default parameters to not clutter up the tests. */
private fun transferToReceiverSucceeded(undoCallback: IUndoMediaTransferCallback? = null) =
TransferToReceiverSucceeded(
PACKAGE_NAME, APP_ICON_CONTENT_DESC, DEVICE_NAME, undoCallback
PACKAGE_NAME, DEVICE_NAME, undoCallback
)
/** Helper method providing default parameters to not clutter up the tests. */
private fun transferToThisDeviceSucceeded(undoCallback: IUndoMediaTransferCallback? = null) =
TransferToThisDeviceSucceeded(
PACKAGE_NAME, APP_ICON_CONTENT_DESC, DEVICE_NAME, undoCallback
PACKAGE_NAME, DEVICE_NAME, undoCallback
)
/** Helper method providing default parameters to not clutter up the tests. */
private fun transferFailed() = TransferFailed(PACKAGE_NAME, APP_ICON_CONTENT_DESC)
private fun transferFailed() = TransferFailed(PACKAGE_NAME)
}
private const val DEVICE_NAME = "My Tablet"
private const val APP_ICON_CONTENT_DESC = "Content description"
private const val PACKAGE_NAME = "com.android.systemui"
private val routeInfo = MediaRoute2Info.Builder("id", "Test Name")