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

Commit 286a0a6f authored by Nicolò Mazzucato's avatar Nicolò Mazzucato Committed by Android (Google) Code Review
Browse files

Merge "Make MainThreadUnfoldTransitionProgressProvider callback registration thread safe" into main

parents b2330897 727682d0
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.unfold.progress

import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
@@ -24,6 +26,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.unfold.TestUnfoldTransitionProvider
import com.android.systemui.utils.os.FakeHandler
import kotlin.test.Test
import kotlinx.coroutines.test.runTest
import org.junit.runner.RunWith

@RunWith(AndroidTestingRunner::class)
@@ -93,4 +96,13 @@ class MainThreadUnfoldTransitionProgressProviderTest : SysuiTestCase() {

        listener.assertNotStarted()
    }

    @Test
    fun addCallback_fromBackgroundThread_succeeds() = runTest {
        val bgHandler = Handler(HandlerThread("TestBgThread").apply { start() }.looper)
        bgHandler.runWithScissors({ progressProvider.addCallback(listener) }, 5000L)

        wrappedProgressProvider.onTransitionStarted()
        listener.assertStarted()
    }
}
+6 −9
Original line number Diff line number Diff line
@@ -24,12 +24,16 @@ import com.android.systemui.unfold.dagger.UnfoldMain
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import java.util.Collections.synchronizedMap

/**
 * [UnfoldTransitionProgressProvider] that forwards all progress to the main thread handler.
 *
 * This is needed when progress are calculated in the background, but some listeners need the
 * callbacks in the main thread.
 *
 * Note that this class assumes that the root provider has thread safe callback registration, as
 * they might be called from any thread.
 */
class MainThreadUnfoldTransitionProgressProvider
@AssistedInject
@@ -38,27 +42,20 @@ constructor(
    @Assisted private val rootProvider: UnfoldTransitionProgressProvider
) : UnfoldTransitionProgressProvider {

    private val listenerMap = mutableMapOf<TransitionProgressListener, TransitionProgressListener>()
    private val listenerMap: MutableMap<TransitionProgressListener, TransitionProgressListener> =
        synchronizedMap(mutableMapOf())

    override fun addCallback(listener: TransitionProgressListener) {
        assertMainThread()
        val proxy = TransitionProgressListerProxy(listener)
        rootProvider.addCallback(proxy)
        listenerMap[listener] = proxy
    }

    override fun removeCallback(listener: TransitionProgressListener) {
        assertMainThread()
        val proxy = listenerMap.remove(listener) ?: return
        rootProvider.removeCallback(proxy)
    }

    private fun assertMainThread() {
        check(mainHandler.looper.isCurrentThread) {
            "Should be called from the main thread, but this is ${Thread.currentThread()}"
        }
    }

    override fun destroy() {
        rootProvider.destroy()
    }