Merge changes Id6078a02,I4c6e92ed,Iee440308 into rvc-dev am: d5e4aa1ad7

Change-Id: I6b23277f9dd1de64f409a1cd11502c1978d9fe08
This commit is contained in:
Lucas Dupin
2020-05-15 16:29:38 +00:00
committed by Automerger Merge Worker
11 changed files with 85 additions and 99 deletions

View File

@@ -49,6 +49,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
android:fontFamily="@*android:string/config_bodyFontFamily" android:fontFamily="@*android:string/config_bodyFontFamily"
android:textColor="@color/media_primary_text"
android:gravity="left" android:gravity="left"
android:textSize="14sp" /> android:textSize="14sp" />
@@ -58,6 +59,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:fontFamily="@*android:string/config_bodyFontFamily" android:fontFamily="@*android:string/config_bodyFontFamily"
android:textColor="@color/media_primary_text"
android:gravity="right" android:gravity="right"
android:textSize="14sp" /> android:textSize="14sp" />
</FrameLayout> </FrameLayout>
@@ -116,6 +118,7 @@
android:layout_width="@dimen/qs_seamless_icon_size" android:layout_width="@dimen/qs_seamless_icon_size"
android:layout_height="@dimen/qs_seamless_icon_size" android:layout_height="@dimen/qs_seamless_icon_size"
android:layout_marginRight="8dp" android:layout_marginRight="8dp"
android:tint="@color/media_primary_text"
android:src="@*android:drawable/ic_media_seamless" /> android:src="@*android:drawable/ic_media_seamless" />
<TextView <TextView
@@ -125,6 +128,7 @@
android:fontFamily="@*android:string/config_bodyFontFamily" android:fontFamily="@*android:string/config_bodyFontFamily"
android:singleLine="true" android:singleLine="true"
android:text="@*android:string/ext_media_seamless_action" android:text="@*android:string/ext_media_seamless_action"
android:textColor="@color/media_primary_text"
android:textSize="14sp" /> android:textSize="14sp" />
</LinearLayout> </LinearLayout>
@@ -138,11 +142,15 @@
android:maxHeight="3dp" android:maxHeight="3dp"
android:paddingTop="16dp" android:paddingTop="16dp"
android:paddingBottom="16dp" android:paddingBottom="16dp"
android:thumbTint="@color/media_primary_text"
android:progressTint="@color/media_seekbar_progress"
android:progressBackgroundTint="@color/media_disabled"
android:splitTrack="false" /> android:splitTrack="false" />
<!-- App name --> <!-- App name -->
<TextView <TextView
android:id="@+id/app_name" android:id="@+id/app_name"
android:textColor="@color/media_primary_text"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:singleLine="true" android:singleLine="true"
@@ -155,6 +163,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@*android:string/config_headlineFontFamilyMedium" android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
android:singleLine="true" android:singleLine="true"
android:textColor="@color/media_primary_text"
android:textSize="18sp" /> android:textSize="18sp" />
<!-- Artist name --> <!-- Artist name -->
@@ -164,10 +173,12 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@*android:string/config_bodyFontFamily" android:fontFamily="@*android:string/config_bodyFontFamily"
android:singleLine="true" android:singleLine="true"
android:textColor="@color/media_primary_text"
android:textSize="14sp" /> android:textSize="14sp" />
<com.android.internal.widget.CachingIconView <com.android.internal.widget.CachingIconView
android:id="@+id/icon" android:id="@+id/icon"
android:tint="@color/media_primary_text"
android:layout_width="16dp" android:layout_width="16dp"
android:layout_height="16dp" /> android:layout_height="16dp" />

View File

@@ -36,6 +36,7 @@
android:layout_height="18dp" android:layout_height="18dp"
android:id="@+id/remove_icon" android:id="@+id/remove_icon"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:tint="@color/media_primary_text"
android:src="@drawable/ic_clear"/> android:src="@drawable/ic_clear"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -43,6 +44,7 @@
android:id="@+id/remove_text" android:id="@+id/remove_text"
android:fontFamily="@*android:string/config_headlineFontFamilyMedium" android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
android:singleLine="true" android:singleLine="true"
android:textColor="@color/media_primary_text"
android:text="@string/controls_media_close_session" /> android:text="@string/controls_media_close_session" />
</LinearLayout> </LinearLayout>
<TextView <TextView
@@ -54,5 +56,6 @@
android:layout_gravity="end|bottom" android:layout_gravity="end|bottom"
android:gravity="bottom" android:gravity="bottom"
android:fontFamily="@*android:string/config_headlineFontFamilyMedium" android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
android:textColor="@android:color/white"
android:text="@string/cancel" /> android:text="@string/cancel" />
</LinearLayout> </LinearLayout>

View File

@@ -239,6 +239,11 @@
<color name="magnification_border_color">#FF9900</color> <color name="magnification_border_color">#FF9900</color>
<!-- media -->
<color name="media_primary_text">@android:color/white</color>
<color name="media_seekbar_progress">#c0ffffff</color>
<color name="media_disabled">#80ffffff</color>
<!-- controls --> <!-- controls -->
<color name="control_primary_text">#E6FFFFFF</color> <color name="control_primary_text">#E6FFFFFF</color>
<color name="control_secondary_text">#99FFFFFF</color> <color name="control_secondary_text">#99FFFFFF</color>

View File

@@ -622,6 +622,7 @@
<style name="MediaPlayer.Button" parent="@android:style/Widget.Material.Button.Borderless.Small"> <style name="MediaPlayer.Button" parent="@android:style/Widget.Material.Button.Borderless.Small">
<item name="android:background">@null</item> <item name="android:background">@null</item>
<item name="android:tint">@android:color/white</item>
</style> </style>
<!-- Used to style charging animation AVD animation --> <!-- Used to style charging animation AVD animation -->

View File

@@ -26,6 +26,7 @@ import android.content.pm.ResolveInfo;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.GradientDrawable;
@@ -98,7 +99,6 @@ public class MediaControlPanel {
private PlayerViewHolder mViewHolder; private PlayerViewHolder mViewHolder;
private MediaSession.Token mToken; private MediaSession.Token mToken;
private MediaController mController; private MediaController mController;
private int mForegroundColor;
private int mBackgroundColor; private int mBackgroundColor;
private MediaDevice mDevice; private MediaDevice mDevice;
protected ComponentName mServiceComponent; protected ComponentName mServiceComponent;
@@ -243,7 +243,6 @@ public class MediaControlPanel {
return; return;
} }
MediaSession.Token token = data.getToken(); MediaSession.Token token = data.getToken();
mForegroundColor = data.getForegroundColor();
mBackgroundColor = data.getBackgroundColor(); mBackgroundColor = data.getBackgroundColor();
if (mToken == null || !mToken.equals(token)) { if (mToken == null || !mToken.equals(token)) {
if (mQSMediaBrowser != null) { if (mQSMediaBrowser != null) {
@@ -304,24 +303,19 @@ public class MediaControlPanel {
// App icon // App icon
ImageView appIcon = mViewHolder.getAppIcon(); ImageView appIcon = mViewHolder.getAppIcon();
Drawable iconDrawable = data.getAppIcon().mutate(); appIcon.setImageDrawable(data.getAppIcon());
iconDrawable.setTint(mForegroundColor);
appIcon.setImageDrawable(iconDrawable);
// Song name // Song name
TextView titleText = mViewHolder.getTitleText(); TextView titleText = mViewHolder.getTitleText();
titleText.setText(data.getSong()); titleText.setText(data.getSong());
titleText.setTextColor(data.getForegroundColor());
// App title // App title
TextView appName = mViewHolder.getAppName(); TextView appName = mViewHolder.getAppName();
appName.setText(data.getApp()); appName.setText(data.getApp());
appName.setTextColor(mForegroundColor);
// Artist name // Artist name
TextView artistText = mViewHolder.getArtistText(); TextView artistText = mViewHolder.getArtistText();
artistText.setText(data.getArtist()); artistText.setText(data.getArtist());
artistText.setTextColor(mForegroundColor);
// Transfer chip // Transfer chip
if (mLocalMediaManager != null) { if (mLocalMediaManager != null) {
@@ -329,6 +323,10 @@ public class MediaControlPanel {
setVisibleAndAlpha(collapsedSet, R.id.media_seamless, true /*visible */); setVisibleAndAlpha(collapsedSet, R.id.media_seamless, true /*visible */);
setVisibleAndAlpha(expandedSet, R.id.media_seamless, true /*visible */); setVisibleAndAlpha(expandedSet, R.id.media_seamless, true /*visible */);
updateDevice(mLocalMediaManager.getCurrentConnectedDevice()); updateDevice(mLocalMediaManager.getCurrentConnectedDevice());
if (mViewHolder.getBackground().getBackground() instanceof IlluminationDrawable) {
((IlluminationDrawable) mViewHolder.getBackground().getBackground())
.setupTouch(mViewHolder.getSeamless(), mViewHolder.getPlayer());
}
mViewHolder.getSeamless().setOnClickListener(v -> { mViewHolder.getSeamless().setOnClickListener(v -> {
final Intent intent = new Intent() final Intent intent = new Intent()
.setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT) .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
@@ -358,7 +356,6 @@ public class MediaControlPanel {
MediaAction mediaAction = actionIcons.get(i); MediaAction mediaAction = actionIcons.get(i);
button.setImageDrawable(mediaAction.getDrawable()); button.setImageDrawable(mediaAction.getDrawable());
button.setContentDescription(mediaAction.getContentDescription()); button.setContentDescription(mediaAction.getContentDescription());
button.setImageTintList(ColorStateList.valueOf(mForegroundColor));
PendingIntent actionIntent = mediaAction.getIntent(); PendingIntent actionIntent = mediaAction.getIntent();
if (mViewHolder.getBackground().getBackground() instanceof IlluminationDrawable) { if (mViewHolder.getBackground().getBackground() instanceof IlluminationDrawable) {
@@ -389,8 +386,7 @@ public class MediaControlPanel {
// Seek Bar // Seek Bar
final MediaController controller = getController(); final MediaController controller = getController();
mBackgroundExecutor.execute( mBackgroundExecutor.execute(() -> mSeekBarViewModel.updateController(controller));
() -> mSeekBarViewModel.updateController(controller, data.getForegroundColor()));
// Set up long press menu // Set up long press menu
// TODO: b/156036025 bring back media guts // TODO: b/156036025 bring back media guts
@@ -541,32 +537,27 @@ public class MediaControlPanel {
if (mViewHolder == null) { if (mViewHolder == null) {
return; return;
} }
ColorStateList fgTintList = ColorStateList.valueOf(mForegroundColor); ImageView iconView = mViewHolder.getSeamlessIcon();
TextView deviceName = mViewHolder.getSeamlessText();
// Update the outline color // Update the outline color
LinearLayout viewLayout = (LinearLayout) mViewHolder.getSeamless(); LinearLayout viewLayout = (LinearLayout) mViewHolder.getSeamless();
RippleDrawable bkgDrawable = (RippleDrawable) viewLayout.getBackground(); RippleDrawable bkgDrawable = (RippleDrawable) viewLayout.getBackground();
GradientDrawable rect = (GradientDrawable) bkgDrawable.getDrawable(0); GradientDrawable rect = (GradientDrawable) bkgDrawable.getDrawable(0);
rect.setStroke(2, mForegroundColor); rect.setStroke(2, deviceName.getCurrentTextColor());
rect.setColor(mBackgroundColor); rect.setColor(Color.TRANSPARENT);
ImageView iconView = mViewHolder.getSeamlessIcon();
TextView deviceName = mViewHolder.getSeamlessText();
deviceName.setTextColor(fgTintList);
if (mIsRemotePlayback) { if (mIsRemotePlayback) {
mViewHolder.getSeamless().setEnabled(false); mViewHolder.getSeamless().setEnabled(false);
mViewHolder.getSeamless().setAlpha(0.38f); mViewHolder.getSeamless().setAlpha(0.38f);
iconView.setImageResource(R.drawable.ic_hardware_speaker); iconView.setImageResource(R.drawable.ic_hardware_speaker);
iconView.setVisibility(View.VISIBLE); iconView.setVisibility(View.VISIBLE);
iconView.setImageTintList(fgTintList);
deviceName.setText(R.string.media_seamless_remote_device); deviceName.setText(R.string.media_seamless_remote_device);
} else if (device != null) { } else if (device != null) {
mViewHolder.getSeamless().setEnabled(true); mViewHolder.getSeamless().setEnabled(true);
mViewHolder.getSeamless().setAlpha(1f); mViewHolder.getSeamless().setAlpha(1f);
Drawable icon = device.getIcon(); Drawable icon = device.getIcon();
iconView.setVisibility(View.VISIBLE); iconView.setVisibility(View.VISIBLE);
iconView.setImageTintList(fgTintList);
if (icon instanceof AdaptiveIcon) { if (icon instanceof AdaptiveIcon) {
AdaptiveIcon aIcon = (AdaptiveIcon) icon; AdaptiveIcon aIcon = (AdaptiveIcon) icon;
@@ -639,7 +630,6 @@ public class MediaControlPanel {
mQSMediaBrowser.restart(); mQSMediaBrowser.restart();
}); });
btn.setImageDrawable(mContext.getResources().getDrawable(R.drawable.lb_ic_play)); btn.setImageDrawable(mContext.getResources().getDrawable(R.drawable.lb_ic_play));
btn.setImageTintList(ColorStateList.valueOf(mForegroundColor));
setVisibleAndAlpha(expandedSet, ACTION_IDS[0], true /*visible */); setVisibleAndAlpha(expandedSet, ACTION_IDS[0], true /*visible */);
setVisibleAndAlpha(collapsedSet, ACTION_IDS[0], true /*visible */); setVisibleAndAlpha(collapsedSet, ACTION_IDS[0], true /*visible */);

View File

@@ -24,7 +24,6 @@ import android.media.session.MediaSession
/** State of a media view. */ /** State of a media view. */
data class MediaData( data class MediaData(
val initialized: Boolean = false, val initialized: Boolean = false,
val foregroundColor: Int,
val backgroundColor: Int, val backgroundColor: Int,
val app: String?, val app: String?,
val appIcon: Drawable?, val appIcon: Drawable?,

View File

@@ -21,6 +21,7 @@ import android.content.ContentResolver
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Color
import android.graphics.ImageDecoder import android.graphics.ImageDecoder
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon import android.graphics.drawable.Icon
@@ -30,7 +31,7 @@ import android.net.Uri
import android.service.notification.StatusBarNotification import android.service.notification.StatusBarNotification
import android.text.TextUtils import android.text.TextUtils
import android.util.Log import android.util.Log
import com.android.internal.util.ContrastColorUtil import com.android.internal.graphics.ColorUtils
import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.statusbar.notification.MediaNotificationProcessor import com.android.systemui.statusbar.notification.MediaNotificationProcessor
@@ -40,7 +41,6 @@ import java.io.IOException
import java.util.concurrent.Executor import java.util.concurrent.Executor
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
import kotlin.collections.LinkedHashMap
// URI fields to try loading album art from // URI fields to try loading album art from
private val ART_URIS = arrayOf( private val ART_URIS = arrayOf(
@@ -50,8 +50,11 @@ private val ART_URIS = arrayOf(
) )
private const val TAG = "MediaDataManager" private const val TAG = "MediaDataManager"
private const val DEFAULT_LUMINOSITY = 0.25f
private const val LUMINOSITY_THRESHOLD = 0.05f
private const val SATURATION_MULTIPLIER = 0.8f
private val LOADING = MediaData(false, 0, 0, null, null, null, null, null, private val LOADING = MediaData(false, 0, null, null, null, null, null,
emptyList(), emptyList(), null, null, null) emptyList(), emptyList(), null, null, null)
/** /**
@@ -107,8 +110,7 @@ class MediaDataManager @Inject constructor(
// Foreground and Background colors computed from album art // Foreground and Background colors computed from album art
val notif: Notification = sbn.notification val notif: Notification = sbn.notification
var fgColor = notif.color var bgColor = Color.WHITE
var bgColor = -1
var artworkBitmap = metadata.getBitmap(MediaMetadata.METADATA_KEY_ART) var artworkBitmap = metadata.getBitmap(MediaMetadata.METADATA_KEY_ART)
if (artworkBitmap == null) { if (artworkBitmap == null) {
artworkBitmap = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART) artworkBitmap = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART)
@@ -142,13 +144,22 @@ class MediaDataManager @Inject constructor(
.generate() .generate()
val swatch = MediaNotificationProcessor.findBackgroundSwatch(p) val swatch = MediaNotificationProcessor.findBackgroundSwatch(p)
bgColor = swatch.rgb bgColor = swatch.rgb
fgColor = MediaNotificationProcessor.selectForegroundColor(bgColor, p)
} }
// Make sure colors will be legible // Adapt background color, so it's always subdued and text is legible
val isDark = !ContrastColorUtil.isColorLight(bgColor) val tmpHsl = floatArrayOf(0f, 0f, 0f)
fgColor = ContrastColorUtil.resolveContrastColor(context, fgColor, bgColor, ColorUtils.colorToHSL(bgColor, tmpHsl)
isDark)
fgColor = ContrastColorUtil.ensureTextContrast(fgColor, bgColor, isDark) val l = tmpHsl[2]
// Colors with very low luminosity can have any saturation. This means that changing the
// luminosity can make a black become red. Let's remove the saturation of very light or
// very dark colors to avoid this issue.
if (l < LUMINOSITY_THRESHOLD || l > 1f - LUMINOSITY_THRESHOLD) {
tmpHsl[1] = 0f
}
tmpHsl[1] *= SATURATION_MULTIPLIER
tmpHsl[2] = DEFAULT_LUMINOSITY
bgColor = ColorUtils.HSLToColor(tmpHsl)
// App name // App name
val builder = Notification.Builder.recoverBuilder(context, notif) val builder = Notification.Builder.recoverBuilder(context, notif)
@@ -189,8 +200,8 @@ class MediaDataManager @Inject constructor(
} }
foregroundExcecutor.execute { foregroundExcecutor.execute {
onMediaDataLoaded(key, MediaData(true, fgColor, bgColor, app, smallIconDrawable, artist, onMediaDataLoaded(key, MediaData(true, bgColor, app, smallIconDrawable, artist, song,
song, artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token, artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token,
notif.contentIntent)) notif.contentIntent))
} }
} }

View File

@@ -17,6 +17,7 @@
package com.android.systemui.media package com.android.systemui.media
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Color
import android.text.format.DateUtils import android.text.format.DateUtils
import android.view.View import android.view.View
import android.widget.SeekBar import android.widget.SeekBar
@@ -46,18 +47,6 @@ class SeekBarObserver(view: View) : Observer<SeekBarViewModel.Progress> {
/** Updates seek bar views when the data model changes. */ /** Updates seek bar views when the data model changes. */
@UiThread @UiThread
override fun onChanged(data: SeekBarViewModel.Progress) { override fun onChanged(data: SeekBarViewModel.Progress) {
data.color?.let {
var tintList = ColorStateList.valueOf(it)
seekBarView.setThumbTintList(tintList)
tintList = tintList.withAlpha(192) // 75%
seekBarView.setProgressTintList(tintList)
tintList = tintList.withAlpha(128) // 50%
seekBarView.setProgressBackgroundTintList(tintList)
elapsedTimeView.setTextColor(it)
totalTimeView.setTextColor(it)
}
if (!data.enabled) { if (!data.enabled) {
seekBarView.setEnabled(false) seekBarView.setEnabled(false)
seekBarView.getThumb().setAlpha(0) seekBarView.getThumb().setAlpha(0)

View File

@@ -67,7 +67,7 @@ private fun PlaybackState.computePosition(duration: Long): Long {
/** ViewModel for seek bar in QS media player. */ /** ViewModel for seek bar in QS media player. */
class SeekBarViewModel(val bgExecutor: DelayableExecutor) { class SeekBarViewModel(val bgExecutor: DelayableExecutor) {
private var _data = Progress(false, false, null, null, null) private var _data = Progress(false, false, null, null)
set(value) { set(value) {
field = value field = value
_progress.postValue(value) _progress.postValue(value)
@@ -100,10 +100,9 @@ class SeekBarViewModel(val bgExecutor: DelayableExecutor) {
/** /**
* Updates media information. * Updates media information.
* @param mediaController controller for media session * @param mediaController controller for media session
* @param color foreground color for UI elements
*/ */
@WorkerThread @WorkerThread
fun updateController(mediaController: MediaController?, color: Int) { fun updateController(mediaController: MediaController?) {
controller = mediaController controller = mediaController
playbackState = controller?.playbackState playbackState = controller?.playbackState
val mediaMetadata = controller?.metadata val mediaMetadata = controller?.metadata
@@ -113,7 +112,7 @@ class SeekBarViewModel(val bgExecutor: DelayableExecutor) {
val enabled = if (playbackState == null || val enabled = if (playbackState == null ||
playbackState?.getState() == PlaybackState.STATE_NONE || playbackState?.getState() == PlaybackState.STATE_NONE ||
(duration != null && duration <= 0)) false else true (duration != null && duration <= 0)) false else true
_data = Progress(enabled, seekAvailable, position, duration, color) _data = Progress(enabled, seekAvailable, position, duration)
if (shouldPollPlaybackPosition()) { if (shouldPollPlaybackPosition()) {
checkPlaybackPosition() checkPlaybackPosition()
} }
@@ -191,7 +190,6 @@ class SeekBarViewModel(val bgExecutor: DelayableExecutor) {
val enabled: Boolean, val enabled: Boolean,
val seekAvailable: Boolean, val seekAvailable: Boolean,
val elapsedTime: Int?, val elapsedTime: Int?,
val duration: Int?, val duration: Int?
val color: Int?
) )
} }

View File

@@ -16,19 +16,15 @@
package com.android.systemui.media package com.android.systemui.media
import android.graphics.Color
import android.content.res.ColorStateList
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import android.testing.TestableLooper import android.testing.TestableLooper
import android.view.View import android.view.View
import android.widget.SeekBar import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -65,7 +61,7 @@ public class SeekBarObserverTest : SysuiTestCase() {
fun seekBarGone() { fun seekBarGone() {
// WHEN seek bar is disabled // WHEN seek bar is disabled
val isEnabled = false val isEnabled = false
val data = SeekBarViewModel.Progress(isEnabled, false, null, null, null) val data = SeekBarViewModel.Progress(isEnabled, false, null, null)
observer.onChanged(data) observer.onChanged(data)
// THEN seek bar shows just a line with no text // THEN seek bar shows just a line with no text
assertThat(seekBarView.isEnabled()).isFalse() assertThat(seekBarView.isEnabled()).isFalse()
@@ -78,7 +74,7 @@ public class SeekBarObserverTest : SysuiTestCase() {
fun seekBarVisible() { fun seekBarVisible() {
// WHEN seek bar is enabled // WHEN seek bar is enabled
val isEnabled = true val isEnabled = true
val data = SeekBarViewModel.Progress(isEnabled, true, 3000, 12000, -1) val data = SeekBarViewModel.Progress(isEnabled, true, 3000, 12000)
observer.onChanged(data) observer.onChanged(data)
// THEN seek bar is visible // THEN seek bar is visible
assertThat(seekBarView.getVisibility()).isEqualTo(View.VISIBLE) assertThat(seekBarView.getVisibility()).isEqualTo(View.VISIBLE)
@@ -89,7 +85,7 @@ public class SeekBarObserverTest : SysuiTestCase() {
@Test @Test
fun seekBarProgress() { fun seekBarProgress() {
// WHEN seek bar progress is about half // WHEN seek bar progress is about half
val data = SeekBarViewModel.Progress(true, true, 3000, 120000, -1) val data = SeekBarViewModel.Progress(true, true, 3000, 120000)
observer.onChanged(data) observer.onChanged(data)
// THEN seek bar is visible // THEN seek bar is visible
assertThat(seekBarView.progress).isEqualTo(100) assertThat(seekBarView.progress).isEqualTo(100)
@@ -102,7 +98,7 @@ public class SeekBarObserverTest : SysuiTestCase() {
fun seekBarDisabledWhenSeekNotAvailable() { fun seekBarDisabledWhenSeekNotAvailable() {
// WHEN seek is not available // WHEN seek is not available
val isSeekAvailable = false val isSeekAvailable = false
val data = SeekBarViewModel.Progress(true, isSeekAvailable, 3000, 120000, -1) val data = SeekBarViewModel.Progress(true, isSeekAvailable, 3000, 120000)
observer.onChanged(data) observer.onChanged(data)
// THEN seek bar is not enabled // THEN seek bar is not enabled
assertThat(seekBarView.isEnabled()).isFalse() assertThat(seekBarView.isEnabled()).isFalse()
@@ -112,20 +108,9 @@ public class SeekBarObserverTest : SysuiTestCase() {
fun seekBarEnabledWhenSeekNotAvailable() { fun seekBarEnabledWhenSeekNotAvailable() {
// WHEN seek is available // WHEN seek is available
val isSeekAvailable = true val isSeekAvailable = true
val data = SeekBarViewModel.Progress(true, isSeekAvailable, 3000, 120000, -1) val data = SeekBarViewModel.Progress(true, isSeekAvailable, 3000, 120000)
observer.onChanged(data) observer.onChanged(data)
// THEN seek bar is not enabled // THEN seek bar is not enabled
assertThat(seekBarView.isEnabled()).isTrue() assertThat(seekBarView.isEnabled()).isTrue()
} }
@Test
fun seekBarColor() {
// WHEN data included color
val data = SeekBarViewModel.Progress(true, true, 3000, 120000, Color.RED)
observer.onChanged(data)
// THEN seek bar is colored
val red = ColorStateList.valueOf(Color.RED)
assertThat(elapsedTimeView.getTextColors()).isEqualTo(red)
assertThat(totalTimeView.getTextColors()).isEqualTo(red)
}
} }

View File

@@ -79,12 +79,6 @@ public class SeekBarViewModelTest : SysuiTestCase() {
ArchTaskExecutor.getInstance().setDelegate(null) ArchTaskExecutor.getInstance().setDelegate(null)
} }
@Test
fun updateColor() {
viewModel.updateController(mockController, Color.RED)
assertThat(viewModel.progress.value!!.color).isEqualTo(Color.RED)
}
@Test @Test
fun updateDurationWithPlayback() { fun updateDurationWithPlayback() {
// GIVEN that the duration is contained within the metadata // GIVEN that the duration is contained within the metadata
@@ -101,7 +95,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
// WHEN the controller is updated // WHEN the controller is updated
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// THEN the duration is extracted // THEN the duration is extracted
assertThat(viewModel.progress.value!!.duration).isEqualTo(duration) assertThat(viewModel.progress.value!!.duration).isEqualTo(duration)
assertThat(viewModel.progress.value!!.enabled).isTrue() assertThat(viewModel.progress.value!!.enabled).isTrue()
@@ -117,7 +111,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
} }
whenever(mockController.getMetadata()).thenReturn(metadata) whenever(mockController.getMetadata()).thenReturn(metadata)
// WHEN the controller is updated // WHEN the controller is updated
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// THEN the duration is extracted // THEN the duration is extracted
assertThat(viewModel.progress.value!!.duration).isEqualTo(duration) assertThat(viewModel.progress.value!!.duration).isEqualTo(duration)
assertThat(viewModel.progress.value!!.enabled).isFalse() assertThat(viewModel.progress.value!!.enabled).isFalse()
@@ -139,7 +133,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
// WHEN the controller is updated // WHEN the controller is updated
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// THEN the seek bar is disabled // THEN the seek bar is disabled
assertThat(viewModel.progress.value!!.enabled).isFalse() assertThat(viewModel.progress.value!!.enabled).isFalse()
} }
@@ -160,7 +154,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
// WHEN the controller is updated // WHEN the controller is updated
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// THEN the seek bar is disabled // THEN the seek bar is disabled
assertThat(viewModel.progress.value!!.enabled).isFalse() assertThat(viewModel.progress.value!!.enabled).isFalse()
} }
@@ -175,7 +169,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
// WHEN the controller is updated // WHEN the controller is updated
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// THEN elapsed time is captured // THEN elapsed time is captured
assertThat(viewModel.progress.value!!.elapsedTime).isEqualTo(200.toInt()) assertThat(viewModel.progress.value!!.elapsedTime).isEqualTo(200.toInt())
} }
@@ -189,7 +183,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
// WHEN the controller is updated // WHEN the controller is updated
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// THEN seek is available // THEN seek is available
assertThat(viewModel.progress.value!!.seekAvailable).isTrue() assertThat(viewModel.progress.value!!.seekAvailable).isTrue()
} }
@@ -203,7 +197,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
// WHEN the controller is updated // WHEN the controller is updated
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// THEN seek is not available // THEN seek is not available
assertThat(viewModel.progress.value!!.seekAvailable).isFalse() assertThat(viewModel.progress.value!!.seekAvailable).isFalse()
} }
@@ -211,7 +205,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
@Test @Test
fun handleSeek() { fun handleSeek() {
whenever(mockController.getTransportControls()).thenReturn(mockTransport) whenever(mockController.getTransportControls()).thenReturn(mockTransport)
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// WHEN user input is dispatched // WHEN user input is dispatched
val pos = 42L val pos = 42L
viewModel.onSeek(pos) viewModel.onSeek(pos)
@@ -223,7 +217,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
@Test @Test
fun handleProgressChangedUser() { fun handleProgressChangedUser() {
whenever(mockController.getTransportControls()).thenReturn(mockTransport) whenever(mockController.getTransportControls()).thenReturn(mockTransport)
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// WHEN user starts dragging the seek bar // WHEN user starts dragging the seek bar
val pos = 42 val pos = 42
viewModel.seekBarListener.onProgressChanged(SeekBar(context), pos, true) viewModel.seekBarListener.onProgressChanged(SeekBar(context), pos, true)
@@ -235,7 +229,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
@Test @Test
fun handleProgressChangedOther() { fun handleProgressChangedOther() {
whenever(mockController.getTransportControls()).thenReturn(mockTransport) whenever(mockController.getTransportControls()).thenReturn(mockTransport)
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// WHEN user starts dragging the seek bar // WHEN user starts dragging the seek bar
val pos = 42 val pos = 42
viewModel.seekBarListener.onProgressChanged(SeekBar(context), pos, false) viewModel.seekBarListener.onProgressChanged(SeekBar(context), pos, false)
@@ -247,7 +241,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
@Test @Test
fun handleStartTrackingTouch() { fun handleStartTrackingTouch() {
whenever(mockController.getTransportControls()).thenReturn(mockTransport) whenever(mockController.getTransportControls()).thenReturn(mockTransport)
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// WHEN user starts dragging the seek bar // WHEN user starts dragging the seek bar
val pos = 42 val pos = 42
val bar = SeekBar(context).apply { val bar = SeekBar(context).apply {
@@ -262,7 +256,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
@Test @Test
fun handleStopTrackingTouch() { fun handleStopTrackingTouch() {
whenever(mockController.getTransportControls()).thenReturn(mockTransport) whenever(mockController.getTransportControls()).thenReturn(mockTransport)
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// WHEN user ends drag // WHEN user ends drag
val pos = 42 val pos = 42
val bar = SeekBar(context).apply { val bar = SeekBar(context).apply {
@@ -283,7 +277,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
// WHEN the controller is updated // WHEN the controller is updated
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// THEN a task is queued // THEN a task is queued
assertThat(fakeExecutor.numPending()).isEqualTo(1) assertThat(fakeExecutor.numPending()).isEqualTo(1)
} }
@@ -297,7 +291,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
// WHEN updated // WHEN updated
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// THEN an update task is not queued // THEN an update task is not queued
assertThat(fakeExecutor.numPending()).isEqualTo(0) assertThat(fakeExecutor.numPending()).isEqualTo(0)
} }
@@ -317,7 +311,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
// WHEN updated // WHEN updated
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// THEN an update task is queued // THEN an update task is queued
assertThat(fakeExecutor.numPending()).isEqualTo(1) assertThat(fakeExecutor.numPending()).isEqualTo(1)
} }
@@ -337,7 +331,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
// WHEN updated // WHEN updated
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// THEN an update task is not queued // THEN an update task is not queued
assertThat(fakeExecutor.numPending()).isEqualTo(0) assertThat(fakeExecutor.numPending()).isEqualTo(0)
} }
@@ -350,7 +344,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
build() build()
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// WHEN the next task runs // WHEN the next task runs
with(fakeExecutor) { with(fakeExecutor) {
advanceClockToNext() advanceClockToNext()
@@ -369,7 +363,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
build() build()
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// WHEN the task runs // WHEN the task runs
with(fakeExecutor) { with(fakeExecutor) {
advanceClockToNext() advanceClockToNext()
@@ -393,7 +387,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
build() build()
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// WHEN start listening // WHEN start listening
viewModel.listening = true viewModel.listening = true
// THEN an update task is queued // THEN an update task is queued
@@ -415,7 +409,7 @@ public class SeekBarViewModelTest : SysuiTestCase() {
} }
whenever(mockController.getPlaybackState()).thenReturn(state) whenever(mockController.getPlaybackState()).thenReturn(state)
// AND the controller has been updated // AND the controller has been updated
viewModel.updateController(mockController, Color.RED) viewModel.updateController(mockController)
// WHEN the controller is cleared on the event when the session is destroyed // WHEN the controller is cleared on the event when the session is destroyed
viewModel.clearController() viewModel.clearController()
with(fakeExecutor) { with(fakeExecutor) {