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

Commit d7307b44 authored by Bart Sears's avatar Bart Sears Committed by Automerger Merge Worker
Browse files

Merge "Revert "Cancel notification if media title is invalid"" into udc-dev am: 293b520f

parents 9efce74d 293b520f
Loading
Loading
Loading
Loading
+19 −47
Original line number Diff line number Diff line
@@ -43,7 +43,6 @@ import android.media.session.PlaybackState
import android.net.Uri
import android.os.Parcelable
import android.os.Process
import android.os.RemoteException
import android.os.UserHandle
import android.provider.Settings
import android.service.notification.StatusBarNotification
@@ -53,7 +52,6 @@ import android.util.Log
import android.util.Pair as APair
import androidx.media.utils.MediaConstants
import com.android.internal.logging.InstanceId
import com.android.internal.statusbar.IStatusBarService
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.Dumpable
import com.android.systemui.R
@@ -139,8 +137,6 @@ internal val EMPTY_SMARTSPACE_MEDIA_DATA =
        expiryTimeMs = 0,
    )

const val MEDIA_TITLE_ERROR_MESSAGE = "Invalid media data: title is null or blank."

fun isMediaNotification(sbn: StatusBarNotification): Boolean {
    return sbn.notification.isMediaNotification()
}
@@ -185,7 +181,6 @@ class MediaDataManager(
    private val logger: MediaUiEventLogger,
    private val smartspaceManager: SmartspaceManager,
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    private val statusBarService: IStatusBarService,
) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener {

    companion object {
@@ -257,7 +252,6 @@ class MediaDataManager(
        mediaFlags: MediaFlags,
        logger: MediaUiEventLogger,
        smartspaceManager: SmartspaceManager,
        statusBarService: IStatusBarService,
        keyguardUpdateMonitor: KeyguardUpdateMonitor,
    ) : this(
        context,
@@ -283,7 +277,6 @@ class MediaDataManager(
        logger,
        smartspaceManager,
        keyguardUpdateMonitor,
        statusBarService,
    )

    private val appChangeReceiver =
@@ -385,21 +378,21 @@ class MediaDataManager(

    fun onNotificationAdded(key: String, sbn: StatusBarNotification) {
        if (useQsMediaPlayer && isMediaNotification(sbn)) {
            var isNewlyActiveEntry = false
            var logEvent = false
            Assert.isMainThread()
            val oldKey = findExistingEntry(key, sbn.packageName)
            if (oldKey == null) {
                val instanceId = logger.getNewInstanceId()
                val temp = LOADING.copy(packageName = sbn.packageName, instanceId = instanceId)
                mediaEntries.put(key, temp)
                isNewlyActiveEntry = true
                logEvent = true
            } else if (oldKey != key) {
                // Resume -> active conversion; move to new key
                val oldData = mediaEntries.remove(oldKey)!!
                isNewlyActiveEntry = true
                logEvent = true
                mediaEntries.put(key, oldData)
            }
            loadMediaData(key, sbn, oldKey, isNewlyActiveEntry)
            loadMediaData(key, sbn, oldKey, logEvent)
        } else {
            onNotificationRemoved(key)
        }
@@ -482,9 +475,9 @@ class MediaDataManager(
        key: String,
        sbn: StatusBarNotification,
        oldKey: String?,
        isNewlyActiveEntry: Boolean = false,
        logEvent: Boolean = false
    ) {
        backgroundExecutor.execute { loadMediaDataInBg(key, sbn, oldKey, isNewlyActiveEntry) }
        backgroundExecutor.execute { loadMediaDataInBg(key, sbn, oldKey, logEvent) }
    }

    /** Add a listener for changes in this class */
@@ -608,12 +601,10 @@ class MediaDataManager(
        }
    }

    private fun removeEntry(key: String, logEvent: Boolean = true) {
    private fun removeEntry(key: String) {
        mediaEntries.remove(key)?.let {
            if (logEvent) {
            logger.logMediaRemoved(it.appUid, it.packageName, it.instanceId)
        }
        }
        notifyMediaDataRemoved(key)
    }

@@ -760,7 +751,7 @@ class MediaDataManager(
        key: String,
        sbn: StatusBarNotification,
        oldKey: String?,
        isNewlyActiveEntry: Boolean = false,
        logEvent: Boolean = false
    ) {
        val token =
            sbn.notification.extras.getParcelable(
@@ -774,34 +765,6 @@ class MediaDataManager(
        val metadata = mediaController.metadata
        val notif: Notification = sbn.notification

        // Song name
        var song: CharSequence? = metadata?.getString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE)
        if (song == null) {
            song = metadata?.getString(MediaMetadata.METADATA_KEY_TITLE)
        }
        if (song == null) {
            song = HybridGroupManager.resolveTitle(notif)
        }
        // Media data must have a title.
        if (song.isNullOrBlank()) {
            try {
                statusBarService.onNotificationError(
                    sbn.packageName,
                    sbn.tag,
                    sbn.id,
                    sbn.uid,
                    sbn.initialPid,
                    MEDIA_TITLE_ERROR_MESSAGE,
                    sbn.user.identifier
                )
            } catch (e: RemoteException) {
                Log.e(TAG, "cancelNotification failed: $e")
            }
            // Only add log for media removed if active media is updated with invalid title.
            foregroundExecutor.execute { removeEntry(key, !isNewlyActiveEntry) }
            return
        }

        val appInfo =
            notif.extras.getParcelable(
                Notification.EXTRA_BUILDER_APPLICATION_INFO,
@@ -830,6 +793,15 @@ class MediaDataManager(
        // App Icon
        val smallIcon = sbn.notification.smallIcon

        // Song name
        var song: CharSequence? = metadata?.getString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE)
        if (song == null) {
            song = metadata?.getString(MediaMetadata.METADATA_KEY_TITLE)
        }
        if (song == null) {
            song = HybridGroupManager.resolveTitle(notif)
        }

        // Explicit Indicator
        var isExplicit = false
        if (mediaFlags.isExplicitIndicatorEnabled()) {
@@ -901,7 +873,7 @@ class MediaDataManager(
        val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId()
        val appUid = appInfo?.uid ?: Process.INVALID_UID

        if (isNewlyActiveEntry) {
        if (logEvent) {
            logSingleVsMultipleMediaAdded(appUid, sbn.packageName, instanceId)
            logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation)
        } else if (playbackLocation != currentEntry?.playbackLocation) {
+11 −129
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@ import android.testing.TestableLooper.RunWithLooper
import androidx.media.utils.MediaConstants
import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId
import com.android.internal.statusbar.IStatusBarService
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.InstanceIdSequenceFake
import com.android.systemui.R
@@ -131,7 +130,6 @@ class MediaDataManagerTest : SysuiTestCase() {
    @Mock lateinit var activityStarter: ActivityStarter
    @Mock lateinit var smartspaceManager: SmartspaceManager
    @Mock lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
    @Mock lateinit var statusBarService: IStatusBarService
    lateinit var smartspaceMediaDataProvider: SmartspaceMediaDataProvider
    @Mock lateinit var mediaSmartspaceTarget: SmartspaceTarget
    @Mock private lateinit var mediaRecommendationItem: SmartspaceAction
@@ -194,8 +192,7 @@ class MediaDataManagerTest : SysuiTestCase() {
                mediaFlags = mediaFlags,
                logger = logger,
                smartspaceManager = smartspaceManager,
                keyguardUpdateMonitor = keyguardUpdateMonitor,
                statusBarService = statusBarService,
                keyguardUpdateMonitor = keyguardUpdateMonitor
            )
        verify(tunerService)
            .addTunable(capture(tunableCaptor), eq(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION))
@@ -520,136 +517,19 @@ class MediaDataManagerTest : SysuiTestCase() {
    }

    @Test
    fun testOnNotificationAdded_emptyTitle_notLoaded() {
        // GIVEN that the manager has a notification with an empty title.
    fun testOnNotificationRemoved_emptyTitle_notConverted() {
        // GIVEN that the manager has a notification with a resume action and empty title.
        whenever(controller.metadata)
            .thenReturn(
                metadataBuilder
                    .putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_EMPTY_TITLE)
                    .build()
            )
        mediaDataManager.onNotificationAdded(KEY, mediaNotification)

        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
        verify(statusBarService)
            .onNotificationError(
                eq(PACKAGE_NAME),
                eq(mediaNotification.tag),
                eq(mediaNotification.id),
                eq(mediaNotification.uid),
                eq(mediaNotification.initialPid),
                eq(MEDIA_TITLE_ERROR_MESSAGE),
                eq(mediaNotification.user.identifier)
            )
        verify(listener, never())
            .onMediaDataLoaded(
                eq(KEY),
                eq(null),
                capture(mediaDataCaptor),
                eq(true),
                eq(0),
                eq(false)
            )
        verify(logger, never()).logResumeMediaAdded(anyInt(), eq(PACKAGE_NAME), any())
        verify(logger, never()).logMediaRemoved(anyInt(), eq(PACKAGE_NAME), any())
    }

    @Test
    fun testOnNotificationAdded_blankTitle_notLoaded() {
        // GIVEN that the manager has a notification with a blank title.
        whenever(controller.metadata)
            .thenReturn(
                metadataBuilder
                    .putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_BLANK_TITLE)
                    .build()
            )
        mediaDataManager.onNotificationAdded(KEY, mediaNotification)

        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
        verify(statusBarService)
            .onNotificationError(
                eq(PACKAGE_NAME),
                eq(mediaNotification.tag),
                eq(mediaNotification.id),
                eq(mediaNotification.uid),
                eq(mediaNotification.initialPid),
                eq(MEDIA_TITLE_ERROR_MESSAGE),
                eq(mediaNotification.user.identifier)
            )
        verify(listener, never())
            .onMediaDataLoaded(
                eq(KEY),
                eq(null),
                capture(mediaDataCaptor),
                eq(true),
                eq(0),
                eq(false)
            )
        verify(logger, never()).logResumeMediaAdded(anyInt(), eq(PACKAGE_NAME), any())
        verify(logger, never()).logMediaRemoved(anyInt(), eq(PACKAGE_NAME), any())
    }

    @Test
    fun testOnNotificationUpdated_invalidTitle_logMediaRemoved() {
        addNotificationAndLoad()
        val data = mediaDataCaptor.value

        verify(listener)
            .onMediaDataLoaded(
                eq(KEY),
                eq(null),
                capture(mediaDataCaptor),
                eq(true),
                eq(0),
                eq(false)
            )

        reset(listener)
        whenever(controller.metadata)
            .thenReturn(
                metadataBuilder
                    .putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_BLANK_TITLE)
                    .build()
            )
        mediaDataManager.onNotificationAdded(KEY, mediaNotification)
        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
        verify(statusBarService)
            .onNotificationError(
                eq(PACKAGE_NAME),
                eq(mediaNotification.tag),
                eq(mediaNotification.id),
                eq(mediaNotification.uid),
                eq(mediaNotification.initialPid),
                eq(MEDIA_TITLE_ERROR_MESSAGE),
                eq(mediaNotification.user.identifier)
            )
        verify(listener, never())
            .onMediaDataLoaded(
                eq(KEY),
                eq(null),
                capture(mediaDataCaptor),
                eq(true),
                eq(0),
                eq(false)
            )
        verify(logger).logMediaRemoved(anyInt(), eq(PACKAGE_NAME), eq(data.instanceId))
    }

    @Test
    fun testOnNotificationRemoved_emptyTitle_notConverted() {
        // GIVEN that the manager has a notification with a resume action and empty title.
        addNotificationAndLoad()
        val data = mediaDataCaptor.value
        val instanceId = data.instanceId
        assertThat(data.resumption).isFalse()
        mediaDataManager.onMediaDataLoaded(
            KEY,
            null,
            data.copy(song = SESSION_EMPTY_TITLE, resumeAction = Runnable {})
        )
        mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))

        // WHEN the notification is removed
        reset(listener)
@@ -674,15 +554,17 @@ class MediaDataManagerTest : SysuiTestCase() {
    @Test
    fun testOnNotificationRemoved_blankTitle_notConverted() {
        // GIVEN that the manager has a notification with a resume action and blank title.
        whenever(controller.metadata)
            .thenReturn(
                metadataBuilder
                    .putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_BLANK_TITLE)
                    .build()
            )
        addNotificationAndLoad()
        val data = mediaDataCaptor.value
        val instanceId = data.instanceId
        assertThat(data.resumption).isFalse()
        mediaDataManager.onMediaDataLoaded(
            KEY,
            null,
            data.copy(song = SESSION_BLANK_TITLE, resumeAction = Runnable {})
        )
        mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))

        // WHEN the notification is removed
        reset(listener)