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

Commit 7b92fb7f authored by Robert Snoeberger's avatar Robert Snoeberger Committed by Automerger Merge Worker
Browse files

Merge "Update progress without binder calls" into rvc-dev am: 37793103 am: d97931fd

Change-Id: Ie89bda196be0097ff69cfdba0da141f48cdd4c57
parents 318530d0 d97931fd
Loading
Loading
Loading
Loading
+36 −8
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.media
import android.media.MediaMetadata
import android.media.session.MediaController
import android.media.session.PlaybackState
import android.os.SystemClock
import android.view.MotionEvent
import android.view.View
import android.widget.SeekBar
@@ -31,6 +32,38 @@ import com.android.systemui.util.concurrency.DelayableExecutor

private const val POSITION_UPDATE_INTERVAL_MILLIS = 100L

private fun PlaybackState.isInMotion(): Boolean {
    return this.state == PlaybackState.STATE_PLAYING ||
            this.state == PlaybackState.STATE_FAST_FORWARDING ||
            this.state == PlaybackState.STATE_REWINDING
}

/**
 * Gets the playback position while accounting for the time since the [PlaybackState] was last
 * retrieved.
 *
 * This method closely follows the implementation of
 * [MediaSessionRecord#getStateWithUpdatedPosition].
 */
private fun PlaybackState.computePosition(duration: Long): Long {
    var currentPosition = this.position
    if (this.isInMotion()) {
        val updateTime = this.getLastPositionUpdateTime()
        val currentTime = SystemClock.elapsedRealtime()
        if (updateTime > 0) {
            var position = (this.playbackSpeed * (currentTime - updateTime)).toLong() +
                    this.getPosition()
            if (duration >= 0 && position > duration) {
                position = duration.toLong()
            } else if (position < 0) {
                position = 0
            }
            currentPosition = position
        }
    }
    return currentPosition
}

/** ViewModel for seek bar in QS media player. */
class SeekBarViewModel(val bgExecutor: DelayableExecutor) {

@@ -98,7 +131,8 @@ class SeekBarViewModel(val bgExecutor: DelayableExecutor) {

    @AnyThread
    private fun checkPlaybackPosition(): Runnable = bgExecutor.executeDelayed({
        val currentPosition = controller?.playbackState?.position?.toInt()
        val duration = _data?.duration ?: -1
        val currentPosition = playbackState?.computePosition(duration.toLong())?.toInt()
        if (currentPosition != null && _data.elapsedTime != currentPosition) {
            _data = _data.copy(elapsedTime = currentPosition)
        }
@@ -109,13 +143,7 @@ class SeekBarViewModel(val bgExecutor: DelayableExecutor) {

    @WorkerThread
    private fun shouldPollPlaybackPosition(): Boolean {
        val state = playbackState?.state
        val moving = if (state == null) false else
                state == PlaybackState.STATE_PLAYING ||
                state == PlaybackState.STATE_BUFFERING ||
                state == PlaybackState.STATE_FAST_FORWARDING ||
                state == PlaybackState.STATE_REWINDING
        return moving && listening
        return listening && playbackState?.isInMotion() ?: false
    }

    /** Gets a listener to attach to the seek bar to handle seeking. */
+5 −12
Original line number Diff line number Diff line
@@ -362,28 +362,21 @@ public class SeekBarViewModelTest : SysuiTestCase() {

    @Test
    fun taskUpdatesProgress() {
        // GIVEN that the PlaybackState contins the current position
        val position = 200L
        // GIVEN that the PlaybackState contins the initial position
        val initialPosition = 0L
        val state = PlaybackState.Builder().run {
            setState(PlaybackState.STATE_PLAYING, position, 1f)
            setState(PlaybackState.STATE_PLAYING, initialPosition, 1f)
            build()
        }
        whenever(mockController.getPlaybackState()).thenReturn(state)
        viewModel.updateController(mockController, Color.RED)
        // AND the playback state advances
        val nextPosition = 300L
        val nextState = PlaybackState.Builder().run {
            setState(PlaybackState.STATE_PLAYING, nextPosition, 1f)
            build()
        }
        whenever(mockController.getPlaybackState()).thenReturn(nextState)
        // WHEN the task runs
        with(fakeExecutor) {
            advanceClockToNext()
            runAllReady()
        }
        // THEN elapsed time is captured
        assertThat(viewModel.progress.value!!.elapsedTime).isEqualTo(nextPosition.toInt())
        // THEN elapsed time has increased
        assertThat(viewModel.progress.value!!.elapsedTime).isGreaterThan(initialPosition.toInt())
    }

    @Test