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

Commit 4f7d725c authored by Michael Mikhail's avatar Michael Mikhail
Browse files

Send binder calls in MediaResumeListener to background thread

Flag: EXEMPT bugfix
Bug: 364610391
Test: atest MediaResumeListenerTest
Change-Id: Ifc1f4af56d04fbd4d3c4e5ab2894dfe281b337ee
parent e2b6ed23
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ constructor(
            field?.disconnect()
            field = value
        }

    private var currentUserId: Int = context.userId

    @VisibleForTesting
@@ -89,7 +90,7 @@ constructor(
                if (Intent.ACTION_USER_UNLOCKED == intent.action) {
                    val userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1)
                    if (userId == currentUserId) {
                        loadMediaResumptionControls()
                        backgroundExecutor.execute { loadMediaResumptionControls() }
                    }
                }
            }
@@ -254,6 +255,7 @@ constructor(
            if (data.resumeAction == null && !data.hasCheckedForResume && isEligibleForResume) {
                // TODO also check for a media button receiver intended for restarting (b/154127084)
                // Set null action to prevent additional attempts to connect
                backgroundExecutor.execute {
                    mediaDataManager.setResumeAction(key, null)
                    Log.d(TAG, "Checking for service component for " + data.packageName)
                    val pm = context.packageManager
@@ -262,7 +264,6 @@ constructor(

                    val inf = resumeInfo?.filter { it.serviceInfo.packageName == data.packageName }
                    if (inf != null && inf.size > 0) {
                    backgroundExecutor.execute {
                        tryUpdateResumptionList(key, inf!!.get(0).componentInfo.componentName)
                    }
                }
+33 −26
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
        whenever(mockContext.packageManager).thenReturn(context.packageManager)
        whenever(mockContext.contentResolver).thenReturn(context.contentResolver)
        whenever(mockContext.userId).thenReturn(context.userId)
        whenever(mockContext.resources).thenReturn(context.resources)
        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(false)

        executor = FakeExecutor(clock)
@@ -210,7 +211,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
    @Test
    fun testOnLoad_checksForResume_noService() {
        // When media data is loaded that has not been checked yet, and does not have a MBS
        resumeListener.onMediaDataLoaded(KEY, null, data)
        onMediaDataLoaded(KEY, null, data)

        // Then we report back to the manager
        verify(mediaDataManager).setResumeAction(KEY, null)
@@ -223,8 +224,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
        whenever(resumeBrowser.testConnection()).thenAnswer { callbackCaptor.value.onError() }

        // When media data is loaded that has not been checked yet, and does not have a MBS
        resumeListener.onMediaDataLoaded(KEY, null, data)
        executor.runAllReady()
        onMediaDataLoaded(KEY, null, data)

        // Then we report back to the manager
        verify(mediaDataManager).setResumeAction(eq(KEY), eq(null))
@@ -234,7 +234,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
    fun testOnLoad_localCast_doesNotCheck() {
        // When media data is loaded that has not been checked yet, and is a local cast
        val dataCast = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
        resumeListener.onMediaDataLoaded(KEY, null, dataCast)
        onMediaDataLoaded(KEY, null, dataCast, false)

        // Then we do not take action
        verify(mediaDataManager, never()).setResumeAction(any(), any())
@@ -244,7 +244,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
    fun testOnload_remoteCast_doesNotCheck() {
        // When media data is loaded that has not been checked yet, and is a remote cast
        val dataRcn = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_REMOTE)
        resumeListener.onMediaDataLoaded(KEY, null, dataRcn)
        onMediaDataLoaded(KEY, null, dataRcn, resume = false)

        // Then we do not take action
        verify(mediaDataManager, never()).setResumeAction(any(), any())
@@ -257,7 +257,7 @@ class MediaResumeListenerTest : SysuiTestCase() {

        // When media data is loaded that has not been checked yet, and is a local cast
        val dataCast = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
        resumeListener.onMediaDataLoaded(KEY, null, dataCast)
        onMediaDataLoaded(KEY, null, dataCast)

        // Then we report back to the manager
        verify(mediaDataManager).setResumeAction(KEY, null)
@@ -270,7 +270,7 @@ class MediaResumeListenerTest : SysuiTestCase() {

        // When media data is loaded that has not been checked yet, and is a remote cast
        val dataRcn = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_REMOTE)
        resumeListener.onMediaDataLoaded(KEY, null, dataRcn)
        onMediaDataLoaded(KEY, null, dataRcn, false)

        // Then we do not take action
        verify(mediaDataManager, never()).setResumeAction(any(), any())
@@ -288,10 +288,9 @@ class MediaResumeListenerTest : SysuiTestCase() {

        // When media data is loaded that has not been checked yet, and does have a MBS
        val dataCopy = data.copy(resumeAction = null, hasCheckedForResume = false)
        resumeListener.onMediaDataLoaded(KEY, null, dataCopy)
        onMediaDataLoaded(KEY, null, dataCopy)

        // Then we test whether the service is valid
        executor.runAllReady()
        verify(mediaDataManager).setResumeAction(eq(KEY), eq(null))
        verify(resumeBrowser).testConnection()

@@ -307,7 +306,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
    fun testOnLoad_doesNotCheckAgain() {
        // When a media data is loaded that has been checked already
        var dataCopy = data.copy(hasCheckedForResume = true)
        resumeListener.onMediaDataLoaded(KEY, null, dataCopy)
        onMediaDataLoaded(KEY, null, dataCopy, resume = false)

        // Then we should not check it again
        verify(resumeBrowser, never()).testConnection()
@@ -320,17 +319,15 @@ class MediaResumeListenerTest : SysuiTestCase() {
        setUpMbsWithValidResolveInfo()
        resumeListener.onMediaDataLoaded(KEY, null, data)

        // We notify the manager to set a null action
        verify(mediaDataManager).setResumeAction(KEY, null)

        // If we then get another update from the app before the first check completes
        assertThat(executor.numPending()).isEqualTo(1)
        var dataWithCheck = data.copy(hasCheckedForResume = true)
        resumeListener.onMediaDataLoaded(KEY, null, dataWithCheck)

        // We do not try to start another check
        assertThat(executor.numPending()).isEqualTo(1)
        executor.runAllReady()
        verify(mediaDataManager).setResumeAction(KEY, null)
        verify(resumeBrowserFactory, times(1)).create(any(), any(), anyInt())
    }

    @Test
@@ -363,6 +360,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
        resumeListener.userUnlockReceiver.onReceive(context, intent)

        // Then we should attempt to find recent media for each saved component
        executor.runAllReady()
        verify(resumeBrowser, times(3)).findRecentMedia()

        // Then since the mock service found media, the manager should be informed
@@ -382,10 +380,9 @@ class MediaResumeListenerTest : SysuiTestCase() {

        // When media data is loaded that has not been checked yet, and does have a MBS
        val dataCopy = data.copy(resumeAction = null, hasCheckedForResume = false)
        resumeListener.onMediaDataLoaded(KEY, null, dataCopy)
        onMediaDataLoaded(KEY, null, dataCopy)

        // Then we test whether the service is valid and set the resume action
        executor.runAllReady()
        verify(mediaDataManager).setResumeAction(eq(KEY), eq(null))
        verify(resumeBrowser).testConnection()
        verify(mediaDataManager, times(2)).setResumeAction(eq(KEY), capture(actionCaptor))
@@ -455,6 +452,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
        resumeListener.userUnlockReceiver.onReceive(mockContext, intent)

        // We add its resume controls
        executor.runAllReady()
        verify(resumeBrowser).findRecentMedia()
        verify(mediaDataManager)
            .addResumptionControls(anyInt(), any(), any(), any(), any(), any(), eq(PACKAGE_NAME))
@@ -527,7 +525,7 @@ class MediaResumeListenerTest : SysuiTestCase() {

        // When media data is loaded that has not been checked yet, and does have a MBS
        val dataCopy = data.copy(resumeAction = null, hasCheckedForResume = false)
        resumeListener.onMediaDataLoaded(KEY, null, dataCopy)
        onMediaDataLoaded(KEY, null, dataCopy)

        // Then we store the new lastPlayed time
        verify(sharedPrefsEditor).putString(any(), (capture(componentCaptor)))
@@ -546,10 +544,9 @@ class MediaResumeListenerTest : SysuiTestCase() {
    fun testOnMediaDataLoaded_newKeyDifferent_oldMediaBrowserDisconnected() {
        setUpMbsWithValidResolveInfo()

        resumeListener.onMediaDataLoaded(key = KEY, oldKey = null, data)
        executor.runAllReady()
        onMediaDataLoaded(key = KEY, oldKey = null, data)

        resumeListener.onMediaDataLoaded(key = "newKey", oldKey = KEY, data)
        onMediaDataLoaded(key = "newKey", oldKey = KEY, data)

        verify(resumeBrowser).disconnect()
    }
@@ -561,8 +558,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
        // Set up mocks to return with an error
        whenever(resumeBrowser.testConnection()).thenAnswer { callbackCaptor.value.onError() }

        resumeListener.onMediaDataLoaded(key = KEY, oldKey = null, data)
        executor.runAllReady()
        onMediaDataLoaded(key = KEY, oldKey = null, data)

        // Ensure we disconnect the browser
        verify(resumeBrowser).disconnect()
@@ -579,8 +575,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
            callbackCaptor.value.addTrack(description, component, resumeBrowser)
        }

        resumeListener.onMediaDataLoaded(key = KEY, oldKey = null, data)
        executor.runAllReady()
        onMediaDataLoaded(key = KEY, oldKey = null, data)

        // Ensure we disconnect the browser
        verify(resumeBrowser).disconnect()
@@ -598,8 +593,7 @@ class MediaResumeListenerTest : SysuiTestCase() {

        // Load media data that will require us to get the resume action
        val dataCopy = data.copy(resumeAction = null, hasCheckedForResume = false)
        resumeListener.onMediaDataLoaded(KEY, null, dataCopy)
        executor.runAllReady()
        onMediaDataLoaded(KEY, null, dataCopy)
        verify(mediaDataManager, times(2)).setResumeAction(eq(KEY), capture(actionCaptor))

        // Set up our factory to return a new browser so we can verify we disconnected the old one
@@ -634,6 +628,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
        // When the first user unlocks and we query their recent media
        userCallbackCaptor.value.onUserChanged(firstUserId, context)
        resumeListener.userUnlockReceiver.onReceive(context, unlockIntent)
        executor.runAllReady()
        whenever(resumeBrowser.userId).thenReturn(userIdCaptor.value)
        verify(resumeBrowser, times(3)).findRecentMedia()

@@ -688,4 +683,16 @@ class MediaResumeListenerTest : SysuiTestCase() {
        whenever(pm.resolveServiceAsUser(any(), anyInt(), anyInt())).thenReturn(resolveInfo)
        whenever(pm.getApplicationLabel(any())).thenReturn(PACKAGE_NAME)
    }

    private fun onMediaDataLoaded(
        key: String,
        oldKey: String?,
        data: MediaData,
        resume: Boolean = true
    ) {
        resumeListener.onMediaDataLoaded(key, oldKey, data)
        if (resume) {
            assertThat(executor.runAllReady()).isEqualTo(1)
        }
    }
}