From 9d9696adc0bdd2d44a1d48457cca1872517f77b0 Mon Sep 17 00:00:00 2001 From: Caitlin Cassidy Date: Tue, 15 Mar 2022 18:59:49 +0000 Subject: [PATCH] [Media TTT] Use the cast icon as a fallback if we can't get the app icon for some reason. Fixes: 213577806 Test: manual: see bug for screenshots Test: media.taptotransfer tests Change-Id: I15c194dc8736a6fdc598eba7759ce11ea96734d1 --- .../common/MediaTttChipControllerCommon.kt | 64 ++++++++++--------- .../MediaTttChipControllerCommonTest.kt | 47 ++++++++++++++ 2 files changed, 80 insertions(+), 31 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt index 71cacac7f4dfe..3d5b3a3f70dfe 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt @@ -32,6 +32,7 @@ import android.view.View import android.view.ViewGroup import android.view.WindowManager import com.android.internal.widget.CachingIconView +import com.android.settingslib.Utils import com.android.systemui.R import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.gesture.TapGestureDetector @@ -150,40 +151,36 @@ abstract class MediaTttChipControllerCommon( appNameOverride: CharSequence? = null, ) { val appIconView = currentChipView.requireViewById(R.id.app_icon) - appIconView.contentDescription = appNameOverride ?: getAppName(appPackageName) - - val appIcon = appIconDrawableOverride ?: getAppIcon(appPackageName) - val visibility = if (appIcon != null) { - View.VISIBLE - } else { - View.GONE - } - appIconView.setImageDrawable(appIcon) - appIconView.visibility = visibility + val appInfo = getAppInfo(appPackageName) + appIconView.contentDescription = appNameOverride ?: appInfo.appName + appIconView.setImageDrawable(appIconDrawableOverride ?: appInfo.appIcon) } - /** Returns the icon of the app playing the media or null if we can't find it. */ - private fun getAppIcon(appPackageName: String?): Drawable? { - appPackageName ?: return null - return try { - context.packageManager.getApplicationIcon(appPackageName) - } catch (e: PackageManager.NameNotFoundException) { - Log.w(TAG, "Cannot find icon for package $appPackageName", e) - null - } - } - - /** Returns the name of the app playing the media or null if we can't find it. */ - private fun getAppName(appPackageName: String?): 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 + /** + * Returns the app name and icon of the app playing media, or a default name and icon if we + * can't find the app name/icon. + */ + private fun getAppInfo(appPackageName: String?): AppInfo { + if (appPackageName != null) { + try { + return AppInfo( + appName = context.packageManager.getApplicationInfo( + appPackageName, PackageManager.ApplicationInfoFlags.of(0) + ).loadLabel(context.packageManager).toString(), + appIcon = context.packageManager.getApplicationIcon(appPackageName) + ) + } catch (e: PackageManager.NameNotFoundException) { + Log.w(TAG, "Cannot find package $appPackageName", e) + } } + return AppInfo( + appName = context.getString(R.string.media_output_dialog_unknown_launch_app_name), + appIcon = context.resources.getDrawable(R.drawable.ic_cast).apply { + this.setTint( + Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary) + ) + } + ) } private fun onScreenTapped(e: MotionEvent) { @@ -205,3 +202,8 @@ object MediaTttRemovalReason { const val REASON_TIMEOUT = "TIMEOUT" const val REASON_SCREEN_TAP = "SCREEN_TAP" } + +private data class AppInfo( + val appName: String, + val appIcon: Drawable +) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt index ccce5778c150f..962d78c129f95 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt @@ -80,6 +80,9 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { appIconFromPackageName = context.getDrawable(R.drawable.ic_cake)!! whenever(packageManager.getApplicationIcon(PACKAGE_NAME)).thenReturn(appIconFromPackageName) whenever(applicationInfo.loadLabel(packageManager)).thenReturn(APP_NAME) + whenever(packageManager.getApplicationInfo( + any(), any() + )).thenThrow(PackageManager.NameNotFoundException()) whenever(packageManager.getApplicationInfo( eq(PACKAGE_NAME), any() )).thenReturn(applicationInfo) @@ -189,6 +192,28 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { verify(windowManager, never()).removeView(any()) } + + @Test + fun displayChip_nullAppIconDrawableAndNullPackageName_stillHasIcon() { + controllerCommon.displayChip(getState()) + val chipView = getChipView() + + controllerCommon.setIcon(chipView, appPackageName = null, appIconDrawableOverride = null) + + assertThat(chipView.getAppIconView().drawable).isNotNull() + } + + @Test + fun displayChip_nullAppIconDrawableAndInvalidPackageName_stillHasIcon() { + controllerCommon.displayChip(getState()) + val chipView = getChipView() + + controllerCommon.setIcon( + chipView, appPackageName = "fakePackageName", appIconDrawableOverride = null + ) + + assertThat(chipView.getAppIconView().drawable).isNotNull() + } @Test fun setIcon_nullAppIconDrawable_iconIsFromPackageName() { @@ -211,6 +236,28 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { assertThat(chipView.getAppIconView().drawable).isEqualTo(drawable) } + @Test + fun displayChip_nullAppNameAndNullPackageName_stillHasContentDescription() { + controllerCommon.displayChip(getState()) + val chipView = getChipView() + + controllerCommon.setIcon(chipView, appPackageName = null, appNameOverride = null) + + assertThat(chipView.getAppIconView().contentDescription.toString()).isNotEmpty() + } + + @Test + fun displayChip_nullAppNameAndInvalidPackageName_stillHasContentDescription() { + controllerCommon.displayChip(getState()) + val chipView = getChipView() + + controllerCommon.setIcon( + chipView, appPackageName = "fakePackageName", appNameOverride = null + ) + + assertThat(chipView.getAppIconView().contentDescription.toString()).isNotEmpty() + } + @Test fun displayChip_nullAppName_iconContentDescriptionIsFromPackageName() { controllerCommon.displayChip(getState())