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

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

Merge "Fix resumable session players" into tm-qpr-dev

parents fb933d46 17bd2d8b
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -1343,13 +1343,9 @@ class MediaDataManager(
    fun onNotificationRemoved(key: String) {
        Assert.isMainThread()
        val removed = mediaEntries.remove(key) ?: return
        val isEligibleForResume =
            removed.isLocalSession() ||
                (mediaFlags.isRemoteResumeAllowed() &&
                    removed.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
        if (keyguardUpdateMonitor.isUserInLockdown(removed.userId)) {
            logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId)
        } else if (useMediaResumption && removed.resumeAction != null && isEligibleForResume) {
        } else if (isAbleToResume(removed)) {
            convertToResumePlayer(key, removed)
        } else if (mediaFlags.isRetainingPlayersEnabled()) {
            handlePossibleRemoval(key, removed, notificationRemoved = true)
@@ -1369,6 +1365,14 @@ class MediaDataManager(
        handlePossibleRemoval(key, updated)
    }

    private fun isAbleToResume(data: MediaData): Boolean {
        val isEligibleForResume =
            data.isLocalSession() ||
                (mediaFlags.isRemoteResumeAllowed() &&
                    data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
        return useMediaResumption && data.resumeAction != null && isEligibleForResume
    }

    /**
     * Convert to resume state if the player is no longer valid and active, then notify listeners
     * that the data was updated. Does not convert to resume state if the player is still valid, or
@@ -1391,8 +1395,9 @@ class MediaDataManager(
            if (DEBUG) Log.d(TAG, "Session destroyed but using notification actions $key")
            mediaEntries.put(key, removed)
            notifyMediaDataLoaded(key, key, removed)
        } else if (removed.active) {
            // This player was still active - it didn't last long enough to time out: remove
        } else if (removed.active && !isAbleToResume(removed)) {
            // This player was still active - it didn't last long enough to time out,
            // and its app doesn't normally support resume: remove
            if (DEBUG) Log.d(TAG, "Removing still-active player $key")
            notifyMediaDataRemoved(key)
            logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId)
+35 −1
Original line number Diff line number Diff line
@@ -2031,7 +2031,7 @@ class MediaDataManagerTest : SysuiTestCase() {
    }

    @Test
    fun testRetain_sessionPlayer_destroyedWhileActive_fullyRemoved() {
    fun testRetain_sessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
        whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(true)
        whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
        addPlaybackStateAction()
@@ -2050,6 +2050,40 @@ class MediaDataManagerTest : SysuiTestCase() {
            .onMediaDataLoaded(eq(PACKAGE_NAME), any(), any(), anyBoolean(), anyInt(), anyBoolean())
    }

    @Test
    fun testRetain_sessionPlayer_canResume_destroyedWhileActive_setToResume() {
        whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(true)
        whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
        addPlaybackStateAction()

        // When a media control using session actions and that does allow resumption is added,
        addNotificationAndLoad()
        val dataResumable = mediaDataCaptor.value.copy(resumeAction = Runnable {})
        mediaDataManager.onMediaDataLoaded(KEY, null, dataResumable)

        // And then the session is destroyed without timing out first
        sessionCallbackCaptor.value.invoke(KEY)

        // It is converted to a resume player
        verify(listener)
            .onMediaDataLoaded(
                eq(PACKAGE_NAME),
                eq(KEY),
                capture(mediaDataCaptor),
                eq(true),
                eq(0),
                eq(false)
            )
        assertThat(mediaDataCaptor.value.resumption).isTrue()
        assertThat(mediaDataCaptor.value.active).isFalse()
        verify(logger)
            .logActiveConvertedToResume(
                anyInt(),
                eq(PACKAGE_NAME),
                eq(mediaDataCaptor.value.instanceId)
            )
    }

    @Test
    fun testSessionDestroyed_noNotificationKey_stillRemoved() {
        whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(true)