Merge "Hook up media player resumption to UI" into rvc-dev am: df9b697804 am: c3a46cd1b0 am: 489a4e4282

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11801909

Change-Id: I62bfe8694f281dbe01384e125074adefd9372fd7
This commit is contained in:
Lucas Dupin
2020-06-16 02:20:14 +00:00
committed by Automerger Merge Worker
13 changed files with 249 additions and 95 deletions

View File

@@ -96,13 +96,13 @@ public class MediaControlPanel {
*/
@Inject
public MediaControlPanel(Context context, @Background Executor backgroundExecutor,
ActivityStarter activityStarter, MediaHostStatesManager mediaHostStatesManager,
ActivityStarter activityStarter, MediaViewController mediaViewController,
SeekBarViewModel seekBarViewModel) {
mContext = context;
mBackgroundExecutor = backgroundExecutor;
mActivityStarter = activityStarter;
mSeekBarViewModel = seekBarViewModel;
mMediaViewController = new MediaViewController(context, mediaHostStatesManager);
mMediaViewController = mediaViewController;
loadDimens();
}
@@ -365,14 +365,6 @@ public class MediaControlPanel {
return artwork;
}
/**
* Return the token for the current media session
* @return the token
*/
public MediaSession.Token getMediaSessionToken() {
return mToken;
}
/**
* Get the current media controller
* @return the controller
@@ -381,25 +373,6 @@ public class MediaControlPanel {
return mController;
}
/**
* Get the name of the package associated with the current media controller
* @return the package name, or null if no controller
*/
public String getMediaPlayerPackage() {
if (mController == null) {
return null;
}
return mController.getPackageName();
}
/**
* Check whether this player has an attached media session.
* @return whether there is a controller with a current media session.
*/
public boolean hasMediaSession() {
return mController != null && mController.getPlaybackState() != null;
}
/**
* Check whether the media controlled by this player is currently playing
* @return whether it is playing, or false if no controller information

View File

@@ -25,19 +25,65 @@ import android.media.session.MediaSession
data class MediaData(
val initialized: Boolean = false,
val backgroundColor: Int,
/**
* App name that will be displayed on the player.
*/
val app: String?,
/**
* Icon shown on player, close to app name.
*/
val appIcon: Drawable?,
/**
* Artist name.
*/
val artist: CharSequence?,
/**
* Song name.
*/
val song: CharSequence?,
/**
* Album artwork.
*/
val artwork: Icon?,
/**
* List of actions that can be performed on the player: prev, next, play, pause, etc.
*/
val actions: List<MediaAction>,
/**
* Same as above, but shown on smaller versions of the player, like in QQS or keyguard.
*/
val actionsToShowInCompact: List<Int>,
/**
* Package name of the app that's posting the media.
*/
val packageName: String,
/**
* Unique media session identifier.
*/
val token: MediaSession.Token?,
/**
* Action to perform when the player is tapped.
* This is unrelated to {@link #actions}.
*/
val clickIntent: PendingIntent?,
/**
* Where the media is playing: phone, headphones, ear buds, remote session.
*/
val device: MediaDeviceData?,
/**
* When active, a player will be displayed on keyguard and quick-quick settings.
* This is unrelated to the stream being playing or not, a player will not be active if
* timed out, or in resumption mode.
*/
var active: Boolean,
/**
* Action that should be performed to restart a non active session.
*/
var resumeAction: Runnable?,
val notificationKey: String = "INVALID",
/**
* Notification key for cancelling a media player after a timeout (when not using resumption.)
*/
val notificationKey: String? = null,
var hasCheckedForResume: Boolean = false
)

View File

@@ -67,7 +67,7 @@ private const val LUMINOSITY_THRESHOLD = 0.05f
private const val SATURATION_MULTIPLIER = 0.8f
private val LOADING = MediaData(false, 0, null, null, null, null, null,
emptyList(), emptyList(), "INVALID", null, null, null, null)
emptyList(), emptyList(), "INVALID", null, null, null, true, null)
fun isMediaNotification(sbn: StatusBarNotification): Boolean {
if (!sbn.notification.hasMediaSession()) {
@@ -88,12 +88,12 @@ fun isMediaNotification(sbn: StatusBarNotification): Boolean {
class MediaDataManager @Inject constructor(
private val context: Context,
private val mediaControllerFactory: MediaControllerFactory,
private val mediaTimeoutListener: MediaTimeoutListener,
private val notificationEntryManager: NotificationEntryManager,
private val mediaResumeListener: MediaResumeListener,
@Background private val backgroundExecutor: Executor,
@Main private val foregroundExecutor: Executor,
private val broadcastDispatcher: BroadcastDispatcher
broadcastDispatcher: BroadcastDispatcher,
mediaTimeoutListener: MediaTimeoutListener,
mediaResumeListener: MediaResumeListener
) {
private val listeners: MutableSet<Listener> = mutableSetOf()
@@ -131,7 +131,6 @@ class MediaDataManager @Inject constructor(
mediaTimeoutListener.timeoutCallback = { token: String, timedOut: Boolean ->
setTimedOut(token, timedOut) }
addListener(mediaTimeoutListener)
if (useMediaResumption) {
mediaResumeListener.addTrackToResumeCallback = { desc: MediaDescription,
resumeAction: Runnable, token: MediaSession.Token, appName: String,
@@ -215,7 +214,7 @@ class MediaDataManager @Inject constructor(
mediaEntries.put(packageName, resumeData)
}
backgroundExecutor.execute {
loadMediaDataInBg(desc, action, token, appName, appIntent, packageName)
loadMediaDataInBgForResumption(desc, action, token, appName, appIntent, packageName)
}
}
@@ -255,16 +254,21 @@ class MediaDataManager @Inject constructor(
fun removeListener(listener: Listener) = listeners.remove(listener)
private fun setTimedOut(token: String, timedOut: Boolean) {
if (!timedOut) {
return
}
mediaEntries[token]?.let {
notificationEntryManager.removeNotification(it.notificationKey, null /* ranking */,
UNDEFINED_DISMISS_REASON)
if (Utils.useMediaResumption(context)) {
if (it.active == !timedOut) {
return
}
it.active = !timedOut
onMediaDataLoaded(token, token, it)
} else {
notificationEntryManager.removeNotification(it.notificationKey, null /* ranking */,
UNDEFINED_DISMISS_REASON)
}
}
}
private fun loadMediaDataInBg(
private fun loadMediaDataInBgForResumption(
desc: MediaDescription,
resumeAction: Runnable,
token: MediaSession.Token,
@@ -272,11 +276,6 @@ class MediaDataManager @Inject constructor(
appIntent: PendingIntent,
packageName: String
) {
if (resumeAction == null) {
Log.e(TAG, "Resume action cannot be null")
return
}
if (TextUtils.isEmpty(desc.title)) {
Log.e(TAG, "Description incomplete")
return
@@ -298,8 +297,9 @@ class MediaDataManager @Inject constructor(
val mediaAction = getResumeMediaAction(resumeAction)
foregroundExecutor.execute {
onMediaDataLoaded(packageName, null, MediaData(true, Color.DKGRAY, appName,
null, desc.subtitle, desc.title, artworkIcon, listOf(mediaAction), listOf(0),
packageName, token, appIntent, null, resumeAction, packageName))
null, desc.subtitle, desc.title, artworkIcon, listOf(mediaAction), listOf(0),
packageName, token, appIntent, device = null, active = false,
resumeAction = resumeAction))
}
}
@@ -430,7 +430,8 @@ class MediaDataManager @Inject constructor(
foregroundExecutor.execute {
onMediaDataLoaded(key, oldKey, MediaData(true, bgColor, app, smallIconDrawable, artist,
song, artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token,
notif.contentIntent, null, resumeAction, key))
notif.contentIntent, null, active = true, resumeAction = resumeAction,
notificationKey = key))
}
}
@@ -528,13 +529,13 @@ class MediaDataManager @Inject constructor(
/**
* Are there any media notifications active?
*/
fun hasActiveMedia() = mediaEntries.any({ isActive(it.value) })
fun hasActiveMedia() = mediaEntries.any { it.value.active }
fun isActive(data: MediaData): Boolean {
if (data.token == null) {
fun isActive(token: MediaSession.Token?): Boolean {
if (token == null) {
return false
}
val controller = mediaControllerFactory.create(data.token)
val controller = mediaControllerFactory.create(token)
val state = controller?.playbackState?.state
return state != null && NotificationMediaManager.isActiveState(state)
}
@@ -542,7 +543,7 @@ class MediaDataManager @Inject constructor(
/**
* Are there any media entries, including resume controls?
*/
fun hasAnyMedia() = mediaEntries.isNotEmpty()
fun hasAnyMedia() = if (useMediaResumption) mediaEntries.isNotEmpty() else hasActiveMedia()
interface Listener {

View File

@@ -1,5 +1,6 @@
package com.android.systemui.media
import android.graphics.PointF
import android.graphics.Rect
import android.view.View
import android.view.View.OnAttachStateChangeListener
@@ -20,8 +21,6 @@ class MediaHost @Inject constructor(
var location: Int = -1
private set
var visibleChangedListener: ((Boolean) -> Unit)? = null
var visible: Boolean = false
private set
private val tmpLocationOnScreen: IntArray = intArrayOf(0, 0)
@@ -109,16 +108,17 @@ class MediaHost @Inject constructor(
}
private fun updateViewVisibility() {
if (showsOnlyActiveMedia) {
visible = mediaDataManager.hasActiveMedia()
visible = if (showsOnlyActiveMedia) {
mediaDataManager.hasActiveMedia()
} else {
visible = mediaDataManager.hasAnyMedia()
mediaDataManager.hasAnyMedia()
}
hostView.visibility = if (visible) View.VISIBLE else View.GONE
visibleChangedListener?.invoke(visible)
}
class MediaHostStateHolder @Inject constructor() : MediaHostState {
private var gonePivot: PointF = PointF()
override var measurementInput: MeasurementInput? = null
set(value) {
@@ -144,6 +144,25 @@ class MediaHost @Inject constructor(
}
}
override var visible: Boolean = true
set(value) {
if (field == value) {
return
}
field = value
changedListener?.invoke()
}
override fun getPivotX(): Float = gonePivot.x
override fun getPivotY(): Float = gonePivot.y
override fun setGonePivot(x: Float, y: Float) {
if (gonePivot.equals(x, y)) {
return
}
gonePivot.set(x, y)
changedListener?.invoke()
}
/**
* A listener for all changes. This won't be copied over when invoking [copy]
*/
@@ -157,6 +176,8 @@ class MediaHost @Inject constructor(
mediaHostState.expansion = expansion
mediaHostState.showsOnlyActiveMedia = showsOnlyActiveMedia
mediaHostState.measurementInput = measurementInput?.copy()
mediaHostState.visible = visible
mediaHostState.gonePivot.set(gonePivot)
return mediaHostState
}
@@ -173,6 +194,12 @@ class MediaHost @Inject constructor(
if (showsOnlyActiveMedia != other.showsOnlyActiveMedia) {
return false
}
if (visible != other.visible) {
return false
}
if (!gonePivot.equals(other.getPivotX(), other.getPivotY())) {
return false
}
return true
}
@@ -180,6 +207,8 @@ class MediaHost @Inject constructor(
var result = measurementInput?.hashCode() ?: 0
result = 31 * result + expansion.hashCode()
result = 31 * result + showsOnlyActiveMedia.hashCode()
result = 31 * result + if (visible) 1 else 2
result = 31 * result + gonePivot.hashCode()
return result
}
}
@@ -194,7 +223,8 @@ interface MediaHostState {
var measurementInput: MeasurementInput?
/**
* The expansion of the player, 0 for fully collapsed, 1 for fully expanded
* The expansion of the player, 0 for fully collapsed (up to 3 actions), 1 for fully expanded
* (up to 5 actions.)
*/
var expansion: Float
@@ -203,6 +233,30 @@ interface MediaHostState {
*/
var showsOnlyActiveMedia: Boolean
/**
* If the view should be VISIBLE or GONE.
*/
var visible: Boolean
/**
* Sets the pivot point when clipping the height or width.
* Clipping happens when animating visibility when we're visible in QS but not on QQS,
* for example.
*/
fun setGonePivot(x: Float, y: Float)
/**
* x position of pivot, from 0 to 1
* @see [setGonePivot]
*/
fun getPivotX(): Float
/**
* y position of pivot, from 0 to 1
* @see [setGonePivot]
*/
fun getPivotY(): Float
/**
* Get a copy of this view state, deepcopying all appropriate members
*/

View File

@@ -43,6 +43,11 @@ class MediaTimeoutListener @Inject constructor(
private val mediaListeners: MutableMap<String, PlaybackStateListener> = mutableMapOf()
/**
* Callback representing that a media object is now expired:
* @param token Media session unique identifier
* @param pauseTimeuot True when expired for {@code PAUSED_MEDIA_TIMEOUT}
*/
lateinit var timeoutCallback: (String, Boolean) -> Unit
override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) {
@@ -112,11 +117,11 @@ class MediaTimeoutListener @Inject constructor(
}
}
private fun expireMediaTimeout(mediaNotificationKey: String, reason: String) {
private fun expireMediaTimeout(mediaKey: String, reason: String) {
cancellation?.apply {
if (DEBUG) {
Log.v(TAG,
"media timeout cancelled for $mediaNotificationKey, reason: $reason")
"media timeout cancelled for $mediaKey, reason: $reason")
}
run()
}

View File

@@ -17,20 +17,22 @@
package com.android.systemui.media
import android.content.Context
import android.graphics.PointF
import androidx.constraintlayout.widget.ConstraintSet
import com.android.systemui.R
import com.android.systemui.util.animation.MeasurementOutput
import com.android.systemui.util.animation.TransitionLayout
import com.android.systemui.util.animation.TransitionLayoutController
import com.android.systemui.util.animation.TransitionViewState
import com.android.systemui.util.animation.MeasurementOutput
import javax.inject.Inject
/**
* A class responsible for controlling a single instance of a media player handling interactions
* with the view instance and keeping the media view states up to date.
*/
class MediaViewController(
class MediaViewController @Inject constructor(
context: Context,
val mediaHostStatesManager: MediaHostStatesManager
private val mediaHostStatesManager: MediaHostStatesManager
) {
private var firstRefresh: Boolean = true
@@ -44,7 +46,7 @@ class MediaViewController(
/**
* A map containing all viewStates for all locations of this mediaState
*/
private val mViewStates: MutableMap<MediaHostState, TransitionViewState?> = mutableMapOf()
private val viewStates: MutableMap<MediaHostState, TransitionViewState?> = mutableMapOf()
/**
* The ending location of the view where it ends when all animations and transitions have
@@ -68,6 +70,11 @@ class MediaViewController(
*/
private val tmpState = TransitionViewState()
/**
* Temporary variable to avoid unnecessary allocations.
*/
private val tmpPoint = PointF()
/**
* A callback for media state changes
*/
@@ -125,7 +132,7 @@ class MediaViewController(
* it's not available, it will recreate one by measuring, which may be expensive.
*/
private fun obtainViewState(state: MediaHostState): TransitionViewState? {
val viewState = mViewStates[state]
val viewState = viewStates[state]
if (viewState != null) {
// we already have cached this measurement, let's continue
return viewState
@@ -143,7 +150,7 @@ class MediaViewController(
// We don't want to cache interpolated or null states as this could quickly fill up
// our cache. We only cache the start and the end states since the interpolation
// is cheap
mViewStates[state.copy()] = result
viewStates[state.copy()] = result
} else {
// This is an interpolated state
val startState = state.copy().also { it.expansion = 0.0f }
@@ -153,11 +160,13 @@ class MediaViewController(
val startViewState = obtainViewState(startState) as TransitionViewState
val endState = state.copy().also { it.expansion = 1.0f }
val endViewState = obtainViewState(endState) as TransitionViewState
tmpPoint.set(startState.getPivotX(), startState.getPivotY())
result = TransitionViewState()
layoutController.getInterpolatedState(
startViewState,
endViewState,
state.expansion,
tmpPoint,
result)
}
} else {
@@ -213,11 +222,35 @@ class MediaViewController(
val shouldAnimate = animateNextStateChange && !applyImmediately
var startHostState = mediaHostStatesManager.mediaHostStates[startLocation]
var endHostState = mediaHostStatesManager.mediaHostStates[endLocation]
var swappedStartState = false
var swappedEndState = false
// if we're going from or to a non visible state, let's grab the visible one and animate
// the view being clipped instead.
if (endHostState?.visible != true) {
endHostState = startHostState
swappedEndState = true
}
if (startHostState?.visible != true) {
startHostState = endHostState
swappedStartState = true
}
if (startHostState == null || endHostState == null) {
return
}
var endViewState = obtainViewState(endHostState) ?: return
if (swappedEndState) {
endViewState = endViewState.copy()
endViewState.height = 0
}
// Obtain the view state that we'd want to be at the end
// The view might not be bound yet or has never been measured and in that case will be
// reset once the state is fully available
val endState = obtainViewStateForLocation(endLocation) ?: return
layoutController.setMeasureState(endState)
layoutController.setMeasureState(endViewState)
// If the view isn't bound, we can drop the animation, otherwise we'll executute it
animateNextStateChange = false
@@ -225,24 +258,43 @@ class MediaViewController(
return
}
val startState = obtainViewStateForLocation(startLocation)
var startViewState = obtainViewState(startHostState)
if (swappedStartState) {
startViewState = startViewState?.copy()
startViewState?.height = 0
}
val result: TransitionViewState?
if (transitionProgress == 1.0f || startState == null) {
result = endState
result = if (transitionProgress == 1.0f || startViewState == null) {
endViewState
} else if (transitionProgress == 0.0f) {
result = startState
startViewState
} else {
layoutController.getInterpolatedState(startState, endState, transitionProgress,
tmpState)
result = tmpState
if (swappedEndState || swappedStartState) {
tmpPoint.set(startHostState.getPivotX(), startHostState.getPivotY())
} else {
tmpPoint.set(0.0f, 0.0f)
}
layoutController.getInterpolatedState(startViewState, endViewState, transitionProgress,
tmpPoint, tmpState)
tmpState
}
layoutController.setState(result, applyImmediately, shouldAnimate, animationDuration,
animationDelay)
}
private fun obtainViewStateForLocation(location: Int): TransitionViewState? {
val mediaState = mediaHostStatesManager.mediaHostStates[location] ?: return null
return obtainViewState(mediaState)
/**
* Retrieves the [TransitionViewState] and [MediaHostState] of a [@MediaLocation].
* In the event of [location] not being visible, [locationWhenHidden] will be used instead.
*
* @param location Target
* @param locationWhenHidden Location that will be used when the target is not
* [MediaHost.visible]
* @return State require for executing a transition, and also the respective [MediaHost].
*/
private fun obtainViewStateForLocation(@MediaLocation location: Int): TransitionViewState? {
val mediaHostState = mediaHostStatesManager.mediaHostStates[location] ?: return null
return obtainViewState(mediaHostState)
}
/**
@@ -250,8 +302,7 @@ class MediaViewController(
* This updates the width the view will me measured with.
*/
fun onLocationPreChange(@MediaLocation newLocation: Int) {
val viewState = obtainViewStateForLocation(newLocation)
viewState?.let {
obtainViewStateForLocation(newLocation)?.let {
layoutController.setMeasureState(it)
}
}
@@ -271,7 +322,7 @@ class MediaViewController(
fun refreshState() {
if (!firstRefresh) {
// Let's clear all of our measurements and recreate them!
mViewStates.clear()
viewStates.clear()
setCurrentState(currentStartLocation, currentEndLocation, currentTransitionProgress,
applyImmediately = false)
}

View File

@@ -235,6 +235,8 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
protected void initMediaHostState() {
mMediaHost.setExpansion(1.0f);
mMediaHost.setShowsOnlyActiveMedia(false);
// Reveal player with some parallax (1.0f would also work)
mMediaHost.setGonePivot(0.0f, 0.8f);
mMediaHost.init(MediaHierarchyManager.LOCATION_QS);
}

View File

@@ -17,6 +17,7 @@
package com.android.systemui.util.animation
import android.content.Context
import android.graphics.PointF
import android.graphics.Rect
import android.util.AttributeSet
import android.view.View
@@ -151,6 +152,11 @@ class TransitionLayout @JvmOverloads constructor(
val layoutTop = top
setLeftTopRightBottom(layoutLeft, layoutTop, layoutLeft + currentState.width,
layoutTop + currentState.height)
val bounds = clipBounds ?: Rect()
bounds.set(left, top, right, bottom)
clipBounds = bounds
translationX = currentState.translation.x
translationY = currentState.translation.y
}
/**
@@ -234,11 +240,13 @@ class TransitionViewState {
var widgetStates: MutableMap<Int, WidgetState> = mutableMapOf()
var width: Int = 0
var height: Int = 0
val translation = PointF()
fun copy(reusedState: TransitionViewState? = null): TransitionViewState {
// we need a deep copy of this, so we can't use a data class
val copy = reusedState ?: TransitionViewState()
copy.width = width
copy.height = height
copy.translation.set(translation.x, translation.y)
for (entry in widgetStates) {
copy.widgetStates[entry.key] = entry.value.copy()
}
@@ -256,6 +264,7 @@ class TransitionViewState {
}
width = transitionLayout.measuredWidth
height = transitionLayout.measuredHeight
translation.set(0.0f, 0.0f)
}
}

View File

@@ -17,6 +17,7 @@
package com.android.systemui.util.animation
import android.animation.ValueAnimator
import android.graphics.PointF
import android.util.MathUtils
import com.android.systemui.Interpolators
@@ -43,6 +44,7 @@ open class TransitionLayoutController {
private var currentState = TransitionViewState()
private var animationStartState: TransitionViewState? = null
private var state = TransitionViewState()
private var pivot = PointF()
private var animator: ValueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f)
init {
@@ -63,6 +65,7 @@ open class TransitionLayoutController {
startState = animationStartState!!,
endState = state,
progress = animator.animatedFraction,
pivot = pivot,
resultState = currentState)
view.setState(currentState)
}
@@ -75,8 +78,10 @@ open class TransitionLayoutController {
startState: TransitionViewState,
endState: TransitionViewState,
progress: Float,
pivot: PointF,
resultState: TransitionViewState
) {
this.pivot.set(pivot)
val view = transitionLayout ?: return
val childCount = view.childCount
for (i in 0 until childCount) {
@@ -178,6 +183,8 @@ open class TransitionLayoutController {
progress).toInt()
height = MathUtils.lerp(startState.height.toFloat(), endState.height.toFloat(),
progress).toInt()
translation.x = (endState.width - width) * pivot.x
translation.y = (endState.height - height) * pivot.y
}
}

View File

@@ -31,6 +31,7 @@ import android.widget.ImageButton
import android.widget.ImageView
import android.widget.SeekBar
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintSet
import androidx.lifecycle.LiveData
import androidx.test.filters.SmallTest
import com.android.systemui.R
@@ -75,9 +76,9 @@ public class MediaControlPanelTest : SysuiTestCase() {
@Mock private lateinit var holder: PlayerViewHolder
@Mock private lateinit var view: TransitionLayout
@Mock private lateinit var mediaHostStatesManager: MediaHostStatesManager
@Mock private lateinit var seekBarViewModel: SeekBarViewModel
@Mock private lateinit var seekBarData: LiveData<SeekBarViewModel.Progress>
@Mock private lateinit var mediaViewController: MediaViewController
private lateinit var appIcon: ImageView
private lateinit var appName: TextView
private lateinit var albumView: ImageView
@@ -104,8 +105,10 @@ public class MediaControlPanelTest : SysuiTestCase() {
@Before
fun setUp() {
bgExecutor = FakeExecutor(FakeSystemClock())
whenever(mediaViewController.expandedLayout).thenReturn(mock(ConstraintSet::class.java))
whenever(mediaViewController.collapsedLayout).thenReturn(mock(ConstraintSet::class.java))
player = MediaControlPanel(context, bgExecutor, activityStarter, mediaHostStatesManager,
player = MediaControlPanel(context, bgExecutor, activityStarter, mediaViewController,
seekBarViewModel)
whenever(seekBarViewModel.progress).thenReturn(seekBarData)
@@ -172,7 +175,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
@Test
fun bindWhenUnattached() {
val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
emptyList(), PACKAGE, null, null, device, null)
emptyList(), PACKAGE, null, null, device, true, null)
player.bind(state)
assertThat(player.isPlaying()).isFalse()
}
@@ -181,7 +184,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
fun bindText() {
player.attach(holder)
val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
emptyList(), PACKAGE, session.getSessionToken(), null, device, null)
emptyList(), PACKAGE, session.getSessionToken(), null, device, true, null)
player.bind(state)
assertThat(appName.getText()).isEqualTo(APP)
assertThat(titleText.getText()).isEqualTo(TITLE)
@@ -192,7 +195,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
fun bindBackgroundColor() {
player.attach(holder)
val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
emptyList(), PACKAGE, session.getSessionToken(), null, device, null)
emptyList(), PACKAGE, session.getSessionToken(), null, device, true, null)
player.bind(state)
val list = ArgumentCaptor.forClass(ColorStateList::class.java)
verify(view).setBackgroundTintList(list.capture())
@@ -203,7 +206,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
fun bindDevice() {
player.attach(holder)
val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
emptyList(), PACKAGE, session.getSessionToken(), null, device, null)
emptyList(), PACKAGE, session.getSessionToken(), null, device, true, null)
player.bind(state)
assertThat(seamlessText.getText()).isEqualTo(DEVICE_NAME)
assertThat(seamless.isEnabled()).isTrue()
@@ -213,7 +216,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
fun bindDisabledDevice() {
player.attach(holder)
val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
emptyList(), PACKAGE, session.getSessionToken(), null, disabledDevice, null)
emptyList(), PACKAGE, session.getSessionToken(), null, disabledDevice, true, null)
player.bind(state)
assertThat(seamless.isEnabled()).isFalse()
assertThat(seamlessText.getText()).isEqualTo(context.getResources().getString(
@@ -224,7 +227,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
fun bindNullDevice() {
player.attach(holder)
val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
emptyList(), PACKAGE, session.getSessionToken(), null, null, null)
emptyList(), PACKAGE, session.getSessionToken(), null, null, true, null)
player.bind(state)
assertThat(seamless.isEnabled()).isTrue()
assertThat(seamlessText.getText()).isEqualTo(context.getResources().getString(

View File

@@ -79,7 +79,8 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
mManager.addListener(mListener);
mMediaData = new MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null,
new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, null, KEY, false);
new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, true, null, KEY,
false);
mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME);
}

View File

@@ -119,7 +119,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
setStyle(Notification.MediaStyle().setMediaSession(session.getSessionToken()))
}
mediaData = MediaData(true, 0, PACKAGE, null, null, SESSION_TITLE, null,
emptyList(), emptyList(), PACKAGE, session.sessionToken, null, null, null)
emptyList(), emptyList(), PACKAGE, session.sessionToken, clickIntent = null,
device = null, active = true, resumeAction = null)
}
@After

View File

@@ -93,7 +93,8 @@ class MediaTimeoutListenerTest : SysuiTestCase() {
}
session.setActive(true)
mediaData = MediaData(true, 0, PACKAGE, null, null, SESSION_TITLE, null,
emptyList(), emptyList(), PACKAGE, session.sessionToken, null, null, null)
emptyList(), emptyList(), PACKAGE, session.sessionToken, clickIntent = null,
device = null, active = true, resumeAction = null)
}
@Test