Merge "Add placeholder when media control title is blank" into rvc-dev

This commit is contained in:
Beth Thibodeau
2023-06-16 00:15:31 +00:00
committed by Android (Google) Code Review
3 changed files with 105 additions and 3 deletions

View File

@@ -2797,6 +2797,8 @@
<string name="controls_media_resume">Resume</string>
<!-- Label for button to go to media control settings screen [CHAR_LIMIT=30] -->
<string name="controls_media_settings_button">Settings</string>
<!-- Placeholder title to inform user that an app has posted media controls [CHAR_LIMIT=NONE] -->
<string name="controls_media_empty_title"><xliff:g id="app_name" example="Foo Music App">%1$s</xliff:g> is running</string>
<!-- Error message indicating that a control timed out while waiting for an update [CHAR_LIMIT=30] -->
<string name="controls_error_timeout">Inactive, check app</string>

View File

@@ -364,12 +364,16 @@ class MediaDataManager(
// Song name
var song: CharSequence? = metadata.getString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE)
if (song == null) {
if (song.isNullOrBlank()) {
song = metadata.getString(MediaMetadata.METADATA_KEY_TITLE)
}
if (song == null) {
if (song.isNullOrBlank()) {
song = HybridGroupManager.resolveTitle(notif)
}
if (song.isNullOrBlank()) {
// For apps that don't include a title, add a placeholder
song = context.getString(R.string.controls_media_empty_title, app)
}
// Artist name
var artist: CharSequence? = metadata.getString(MediaMetadata.METADATA_KEY_ARTIST)

View File

@@ -10,11 +10,13 @@ import android.service.notification.StatusBarNotification
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.SbnBuilder
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -23,6 +25,8 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.mock
@@ -33,9 +37,11 @@ import org.mockito.Mockito.`when` as whenever
private const val KEY = "KEY"
private const val KEY_2 = "KEY_2"
private const val PACKAGE_NAME = "com.android.systemui"
private const val APP_NAME = "SystemUI"
private const val APP_NAME = "com.android.systemui.tests"
private const val SESSION_ARTIST = "artist"
private const val SESSION_TITLE = "title"
private const val SESSION_BLANK_TITLE = " "
private const val SESSION_EMPTY_TITLE = ""
private const val USER_ID = 0
private fun <T> anyObject(): T {
@@ -61,6 +67,7 @@ class MediaDataManagerTest : SysuiTestCase() {
@JvmField @Rule val mockito = MockitoJUnit.rule()
lateinit var mediaDataManager: MediaDataManager
lateinit var mediaNotification: StatusBarNotification
@Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData>
@Before
fun setup() {
@@ -143,6 +150,95 @@ class MediaDataManagerTest : SysuiTestCase() {
verify(listener).onMediaDataRemoved(eq(KEY))
}
@Test
fun testOnNotificationAdded_emptyTitle_hasPlaceholder() {
// When the manager has a notification with an empty title
val listener = mock(MediaDataManager.Listener::class.java)
mediaDataManager.addListener(listener)
whenever(controller.metadata)
.thenReturn(
metadataBuilder
.putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_EMPTY_TITLE)
.build()
)
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
// Then a media control is created with a placeholder title string
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
verify(listener)
.onMediaDataLoaded(
eq(KEY),
eq(null),
capture(mediaDataCaptor)
)
val placeholderTitle = context.getString(R.string.controls_media_empty_title, APP_NAME)
assertThat(mediaDataCaptor.value.song).isEqualTo(placeholderTitle)
}
@Test
fun testOnNotificationAdded_blankTitle_hasPlaceholder() {
// GIVEN that the manager has a notification with a blank title
val listener = mock(MediaDataManager.Listener::class.java)
mediaDataManager.addListener(listener)
whenever(controller.metadata)
.thenReturn(
metadataBuilder
.putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_BLANK_TITLE)
.build()
)
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
// Then a media control is created with a placeholder title string
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
verify(listener)
.onMediaDataLoaded(
eq(KEY),
eq(null),
capture(mediaDataCaptor)
)
val placeholderTitle = context.getString(R.string.controls_media_empty_title, APP_NAME)
assertThat(mediaDataCaptor.value.song).isEqualTo(placeholderTitle)
}
@Test
fun testOnNotificationAdded_emptyMetadata_usesNotificationTitle() {
// When the app sets the metadata title fields to empty strings, but does include a
// non-blank notification title
val listener = mock(MediaDataManager.Listener::class.java)
mediaDataManager.addListener(listener)
whenever(controller.metadata)
.thenReturn(
metadataBuilder
.putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_EMPTY_TITLE)
.putString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, SESSION_EMPTY_TITLE)
.build()
)
mediaNotification =
SbnBuilder().run {
setPkg(PACKAGE_NAME)
modifyNotification(context).also {
it.setSmallIcon(android.R.drawable.ic_media_pause)
it.setContentTitle(SESSION_TITLE)
it.setStyle(MediaStyle().apply { setMediaSession(session.sessionToken) })
}
build()
}
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
// Then the media control is added using the notification's title
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
verify(listener)
.onMediaDataLoaded(
eq(KEY),
eq(null),
capture(mediaDataCaptor)
)
assertThat(mediaDataCaptor.value.song).isEqualTo(SESSION_TITLE)
}
@Test
fun testOnNotificationRemoved_withResumption() {
// GIVEN that the manager has a notification with a resume action