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

Commit af2340cf authored by Michael Mikhail's avatar Michael Mikhail
Browse files

Make sure that invoking handlers is on main thread.

For new media architecture, we need to escape back to main dispatcher
before invoking handlers when registering callbacks.

Flag: ACONFIG com.android.systemui.media_controls_refactor DISABLED
Bug: 328207006
Test: Build.
Test: atest SeekBarViewModelTest
Change-Id: I2b7cf031007625b465d8d10b37e508946ae45ae6
parent 3f548c00
Loading
Loading
Loading
Loading
+23 −3
Original line number Diff line number Diff line
@@ -33,12 +33,19 @@ import androidx.core.view.GestureDetectorCompat
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.android.systemui.classifier.Classifier.MEDIA_SEEKBAR
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.NotificationMediaManager
import com.android.systemui.util.concurrency.RepeatableExecutor
import javax.inject.Inject
import kotlin.math.abs
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

private const val POSITION_UPDATE_INTERVAL_MILLIS = 100L
private const val MIN_FLING_VELOCITY_SCALE_FACTOR = 10
@@ -81,8 +88,11 @@ private fun PlaybackState.computePosition(duration: Long): Long {
class SeekBarViewModel
@Inject
constructor(
    @Application private val applicationScope: CoroutineScope,
    @Main private val mainDispatcher: CoroutineDispatcher,
    @Background private val bgExecutor: RepeatableExecutor,
    private val falsingManager: FalsingManager,
    private val mediaFlags: MediaFlags,
) {
    private var _data =
        Progress(
@@ -108,9 +118,19 @@ constructor(
    private var controller: MediaController? = null
        set(value) {
            if (field?.sessionToken != value?.sessionToken) {
                if (!mediaFlags.isMediaControlsRefactorEnabled()) {
                    field?.unregisterCallback(callback)
                    value?.registerCallback(callback)
                    field = value
                } else {
                    applicationScope.launch {
                        withContext(mainDispatcher) {
                            field?.unregisterCallback(callback)
                            value?.registerCallback(callback)
                            field = value
                        }
                    }
                }
            }
        }
    private var playbackState: PlaybackState? = null
+16 −1
Original line number Diff line number Diff line
@@ -29,7 +29,12 @@ import androidx.arch.core.executor.TaskExecutor
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.Classifier
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.media.controls.util.mediaFlags
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.testKosmos
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.concurrency.FakeRepeatableExecutor
import com.android.systemui.util.time.FakeSystemClock
@@ -56,6 +61,7 @@ import org.mockito.junit.MockitoJUnit
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class SeekBarViewModelTest : SysuiTestCase() {
    val kosmos = testKosmos()

    private lateinit var viewModel: SeekBarViewModel
    private lateinit var fakeExecutor: FakeExecutor
@@ -75,6 +81,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
    @Mock private lateinit var mockTransport: MediaController.TransportControls
    @Mock private lateinit var falsingManager: FalsingManager
    @Mock private lateinit var mockBar: SeekBar
    @Mock private lateinit var mediaFlags: MediaFlags
    private val token1 = MediaSession.Token(1, null)
    private val token2 = MediaSession.Token(2, null)

@@ -83,10 +90,18 @@ public class SeekBarViewModelTest : SysuiTestCase() {
    @Before
    fun setUp() {
        fakeExecutor = FakeExecutor(FakeSystemClock())
        viewModel = SeekBarViewModel(FakeRepeatableExecutor(fakeExecutor), falsingManager)
        viewModel =
            SeekBarViewModel(
                kosmos.applicationCoroutineScope,
                kosmos.testDispatcher,
                FakeRepeatableExecutor(fakeExecutor),
                falsingManager,
                mediaFlags,
            )
        viewModel.logSeek = {}
        whenever(mockController.sessionToken).thenReturn(token1)
        whenever(mockBar.context).thenReturn(context)
        whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(false)

        // LiveData to run synchronously
        ArchTaskExecutor.getInstance().setDelegate(taskExecutor)