Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 98e02fa8 authored by Beth Thibodeau's avatar Beth Thibodeau Committed by Android (Google) Code Review
Browse files

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

parents 0e3093b2 070eff91
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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>
+6 −2
Original line number Diff line number Diff line
@@ -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)
+97 −1
Original line number Diff line number Diff line
@@ -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