Merge "Separate updating views from deriving state" into rvc-dev am: e174ee831e am: 0f94ce41bb
Change-Id: I61d65cfff3fda3663079634715f755c67dccc737
This commit is contained in:
33
packages/SystemUI/src/com/android/keyguard/KeyguardMedia.kt
Normal file
33
packages/SystemUI/src/com/android/keyguard/KeyguardMedia.kt
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.keyguard
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
|
||||
import java.util.List
|
||||
|
||||
/** State for lock screen media controls. */
|
||||
data class KeyguardMedia(
|
||||
val foregroundColor: Int,
|
||||
val backgroundColor: Int,
|
||||
val app: String?,
|
||||
val appIcon: Drawable?,
|
||||
val artist: String?,
|
||||
val song: String?,
|
||||
val artwork: Drawable?,
|
||||
val actionIcons: List<Drawable>
|
||||
)
|
||||
@@ -32,6 +32,9 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
|
||||
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.palette.graphics.Palette;
|
||||
|
||||
import com.android.internal.util.ContrastColorUtil;
|
||||
@@ -64,39 +67,47 @@ public class KeyguardMediaPlayer {
|
||||
|
||||
private final Context mContext;
|
||||
private final Executor mBackgroundExecutor;
|
||||
private float mAlbumArtRadius;
|
||||
private int mAlbumArtSize;
|
||||
private View mMediaNotifView;
|
||||
private final KeyguardMediaViewModel mViewModel;
|
||||
private KeyguardMediaObserver mObserver;
|
||||
|
||||
@Inject
|
||||
public KeyguardMediaPlayer(Context context, @Background Executor backgroundExecutor) {
|
||||
mContext = context;
|
||||
mBackgroundExecutor = backgroundExecutor;
|
||||
loadDimens();
|
||||
mViewModel = new KeyguardMediaViewModel(context);
|
||||
}
|
||||
|
||||
/** Binds media controls to a view hierarchy. */
|
||||
public void bindView(View v) {
|
||||
if (mMediaNotifView != null) {
|
||||
if (mObserver != null) {
|
||||
throw new IllegalStateException("cannot bind views, already bound");
|
||||
}
|
||||
mMediaNotifView = v;
|
||||
loadDimens();
|
||||
mViewModel.loadDimens();
|
||||
mObserver = new KeyguardMediaObserver(v);
|
||||
// Control buttons
|
||||
for (int i = 0; i < ACTION_IDS.length; i++) {
|
||||
ImageButton button = v.findViewById(ACTION_IDS[i]);
|
||||
if (button == null) {
|
||||
continue;
|
||||
}
|
||||
final int index = i;
|
||||
button.setOnClickListener(unused -> mViewModel.onActionClick(index));
|
||||
}
|
||||
mViewModel.getKeyguardMedia().observeForever(mObserver);
|
||||
}
|
||||
|
||||
/** Unbinds media controls. */
|
||||
public void unbindView() {
|
||||
if (mMediaNotifView == null) {
|
||||
if (mObserver == null) {
|
||||
throw new IllegalStateException("cannot unbind views, nothing bound");
|
||||
}
|
||||
mMediaNotifView = null;
|
||||
mViewModel.getKeyguardMedia().removeObserver(mObserver);
|
||||
mObserver = null;
|
||||
}
|
||||
|
||||
/** Clear the media controls because there isn't an active session. */
|
||||
public void clearControls() {
|
||||
if (mMediaNotifView != null) {
|
||||
mMediaNotifView.setVisibility(View.GONE);
|
||||
}
|
||||
mBackgroundExecutor.execute(mViewModel::clearControls);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,159 +121,244 @@ public class KeyguardMediaPlayer {
|
||||
*/
|
||||
public void updateControls(NotificationEntry entry, Icon appIcon,
|
||||
MediaMetadata mediaMetadata) {
|
||||
if (mMediaNotifView == null) {
|
||||
if (mObserver == null) {
|
||||
throw new IllegalStateException("cannot update controls, views not bound");
|
||||
}
|
||||
if (mediaMetadata == null) {
|
||||
mMediaNotifView.setVisibility(View.GONE);
|
||||
Log.d(TAG, "media metadata was null");
|
||||
Log.d(TAG, "media metadata was null, closing media controls");
|
||||
// Note that clearControls() executes on the same background executor, so there
|
||||
// shouldn't be an issue with an outdated update running after clear. However, if stale
|
||||
// controls are observed then consider removing any enqueued updates.
|
||||
clearControls();
|
||||
return;
|
||||
}
|
||||
mMediaNotifView.setVisibility(View.VISIBLE);
|
||||
mBackgroundExecutor.execute(() -> mViewModel.updateControls(entry, appIcon, mediaMetadata));
|
||||
}
|
||||
|
||||
Notification notif = entry.getSbn().getNotification();
|
||||
/** ViewModel for KeyguardMediaControls. */
|
||||
private static final class KeyguardMediaViewModel {
|
||||
|
||||
// Computed foreground and background color based on album art.
|
||||
int fgColor = notif.color;
|
||||
int bgColor = entry.getRow() == null ? -1 : entry.getRow().getCurrentBackgroundTint();
|
||||
Bitmap artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
|
||||
if (artworkBitmap == null) {
|
||||
artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
|
||||
}
|
||||
if (artworkBitmap != null) {
|
||||
// If we have art, get colors from that
|
||||
Palette p = MediaNotificationProcessor.generateArtworkPaletteBuilder(artworkBitmap)
|
||||
.generate();
|
||||
Palette.Swatch swatch = MediaNotificationProcessor.findBackgroundSwatch(p);
|
||||
bgColor = swatch.getRgb();
|
||||
fgColor = MediaNotificationProcessor.selectForegroundColor(bgColor, p);
|
||||
}
|
||||
// Make sure colors will be legible
|
||||
boolean isDark = !ContrastColorUtil.isColorLight(bgColor);
|
||||
fgColor = ContrastColorUtil.resolveContrastColor(mContext, fgColor, bgColor,
|
||||
isDark);
|
||||
fgColor = ContrastColorUtil.ensureTextContrast(fgColor, bgColor, isDark);
|
||||
private final Context mContext;
|
||||
private final MutableLiveData<KeyguardMedia> mMedia = new MutableLiveData<>();
|
||||
private final Object mActionsLock = new Object();
|
||||
private List<PendingIntent> mActions;
|
||||
private float mAlbumArtRadius;
|
||||
private int mAlbumArtSize;
|
||||
|
||||
// Album art
|
||||
ImageView albumView = mMediaNotifView.findViewById(R.id.album_art);
|
||||
if (albumView != null) {
|
||||
// Resize art in a background thread
|
||||
final Bitmap bm = artworkBitmap;
|
||||
mBackgroundExecutor.execute(() -> processAlbumArt(bm, albumView));
|
||||
KeyguardMediaViewModel(Context context) {
|
||||
mContext = context;
|
||||
loadDimens();
|
||||
}
|
||||
|
||||
// App icon
|
||||
ImageView appIconView = mMediaNotifView.findViewById(R.id.icon);
|
||||
if (appIconView != null) {
|
||||
Drawable iconDrawable = appIcon.loadDrawable(mContext);
|
||||
iconDrawable.setTint(fgColor);
|
||||
appIconView.setImageDrawable(iconDrawable);
|
||||
/** Close the media player because there isn't an active session. */
|
||||
public void clearControls() {
|
||||
synchronized (mActionsLock) {
|
||||
mActions = null;
|
||||
}
|
||||
mMedia.postValue(null);
|
||||
}
|
||||
|
||||
// App name
|
||||
TextView appName = mMediaNotifView.findViewById(R.id.app_name);
|
||||
if (appName != null) {
|
||||
/** Update the media player with information about the active session. */
|
||||
public void updateControls(NotificationEntry entry, Icon appIcon,
|
||||
MediaMetadata mediaMetadata) {
|
||||
|
||||
// Foreground and Background colors computed from album art
|
||||
Notification notif = entry.getSbn().getNotification();
|
||||
int fgColor = notif.color;
|
||||
int bgColor = entry.getRow() == null ? -1 : entry.getRow().getCurrentBackgroundTint();
|
||||
Bitmap artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
|
||||
if (artworkBitmap == null) {
|
||||
artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
|
||||
}
|
||||
if (artworkBitmap != null) {
|
||||
// If we have art, get colors from that
|
||||
Palette p = MediaNotificationProcessor.generateArtworkPaletteBuilder(artworkBitmap)
|
||||
.generate();
|
||||
Palette.Swatch swatch = MediaNotificationProcessor.findBackgroundSwatch(p);
|
||||
bgColor = swatch.getRgb();
|
||||
fgColor = MediaNotificationProcessor.selectForegroundColor(bgColor, p);
|
||||
}
|
||||
// Make sure colors will be legible
|
||||
boolean isDark = !ContrastColorUtil.isColorLight(bgColor);
|
||||
fgColor = ContrastColorUtil.resolveContrastColor(mContext, fgColor, bgColor,
|
||||
isDark);
|
||||
fgColor = ContrastColorUtil.ensureTextContrast(fgColor, bgColor, isDark);
|
||||
|
||||
// Album art
|
||||
RoundedBitmapDrawable artwork = null;
|
||||
if (artworkBitmap != null) {
|
||||
Bitmap original = artworkBitmap.copy(Bitmap.Config.ARGB_8888, true);
|
||||
Bitmap scaled = Bitmap.createScaledBitmap(original, mAlbumArtSize, mAlbumArtSize,
|
||||
false);
|
||||
artwork = RoundedBitmapDrawableFactory.create(mContext.getResources(), scaled);
|
||||
artwork.setCornerRadius(mAlbumArtRadius);
|
||||
}
|
||||
|
||||
// App name
|
||||
Notification.Builder builder = Notification.Builder.recoverBuilder(mContext, notif);
|
||||
String appNameString = builder.loadHeaderAppName();
|
||||
appName.setText(appNameString);
|
||||
appName.setTextColor(fgColor);
|
||||
String app = builder.loadHeaderAppName();
|
||||
|
||||
// App Icon
|
||||
Drawable appIconDrawable = appIcon.loadDrawable(mContext);
|
||||
|
||||
// Song name
|
||||
String song = mediaMetadata.getString(MediaMetadata.METADATA_KEY_TITLE);
|
||||
|
||||
// Artist name
|
||||
String artist = mediaMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
|
||||
|
||||
// Control buttons
|
||||
List<Drawable> actionIcons = new ArrayList<>();
|
||||
final List<PendingIntent> intents = new ArrayList<>();
|
||||
Notification.Action[] actions = notif.actions;
|
||||
final int[] actionsToShow = notif.extras.getIntArray(
|
||||
Notification.EXTRA_COMPACT_ACTIONS);
|
||||
|
||||
Context packageContext = entry.getSbn().getPackageContext(mContext);
|
||||
for (int i = 0; i < ACTION_IDS.length; i++) {
|
||||
if (actionsToShow != null && actions != null && i < actionsToShow.length
|
||||
&& actionsToShow[i] < actions.length) {
|
||||
final int idx = actionsToShow[i];
|
||||
actionIcons.add(actions[idx].getIcon().loadDrawable(packageContext));
|
||||
intents.add(actions[idx].actionIntent);
|
||||
} else {
|
||||
actionIcons.add(null);
|
||||
intents.add(null);
|
||||
}
|
||||
}
|
||||
synchronized (mActionsLock) {
|
||||
mActions = intents;
|
||||
}
|
||||
|
||||
KeyguardMedia data = new KeyguardMedia(fgColor, bgColor, app, appIconDrawable, artist,
|
||||
song, artwork, actionIcons);
|
||||
mMedia.postValue(data);
|
||||
}
|
||||
|
||||
// Song name
|
||||
TextView titleText = mMediaNotifView.findViewById(R.id.header_title);
|
||||
if (titleText != null) {
|
||||
String songName = mediaMetadata.getString(MediaMetadata.METADATA_KEY_TITLE);
|
||||
titleText.setText(songName);
|
||||
titleText.setTextColor(fgColor);
|
||||
/** Gets state for the lock screen media controls. */
|
||||
public LiveData<KeyguardMedia> getKeyguardMedia() {
|
||||
return mMedia;
|
||||
}
|
||||
|
||||
// Artist name
|
||||
TextView artistText = mMediaNotifView.findViewById(R.id.header_artist);
|
||||
if (artistText != null) {
|
||||
String artistName = mediaMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
|
||||
artistText.setText(artistName);
|
||||
artistText.setTextColor(fgColor);
|
||||
}
|
||||
|
||||
// Background color
|
||||
if (mMediaNotifView instanceof MediaHeaderView) {
|
||||
MediaHeaderView head = (MediaHeaderView) mMediaNotifView;
|
||||
head.setBackgroundColor(bgColor);
|
||||
}
|
||||
|
||||
// Control buttons
|
||||
final List<Icon> icons = new ArrayList<>();
|
||||
final List<PendingIntent> intents = new ArrayList<>();
|
||||
Notification.Action[] actions = notif.actions;
|
||||
final int[] actionsToShow = notif.extras.getIntArray(Notification.EXTRA_COMPACT_ACTIONS);
|
||||
|
||||
for (int i = 0; i < ACTION_IDS.length; i++) {
|
||||
if (actionsToShow != null && actions != null && i < actionsToShow.length
|
||||
&& actionsToShow[i] < actions.length) {
|
||||
final int idx = actionsToShow[i];
|
||||
icons.add(actions[idx].getIcon());
|
||||
intents.add(actions[idx].actionIntent);
|
||||
} else {
|
||||
icons.add(null);
|
||||
intents.add(null);
|
||||
/**
|
||||
* Handle user clicks on media control buttons (actions).
|
||||
*
|
||||
* @param index position of the button that was clicked.
|
||||
*/
|
||||
public void onActionClick(int index) {
|
||||
PendingIntent intent = null;
|
||||
// This might block the ui thread to wait for the lock. Currently, however, the
|
||||
// lock is held by the bg thread to assign a member, which should be fast. An
|
||||
// alternative could be to add the intents to the state and let the observer set
|
||||
// the onClick listeners.
|
||||
synchronized (mActionsLock) {
|
||||
if (mActions != null && index < mActions.size()) {
|
||||
intent = mActions.get(index);
|
||||
}
|
||||
}
|
||||
if (intent != null) {
|
||||
try {
|
||||
intent.send();
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
Log.d(TAG, "failed to send action intent", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Context packageContext = entry.getSbn().getPackageContext(mContext);
|
||||
for (int i = 0; i < ACTION_IDS.length; i++) {
|
||||
ImageButton button = mMediaNotifView.findViewById(ACTION_IDS[i]);
|
||||
if (button == null) {
|
||||
continue;
|
||||
void loadDimens() {
|
||||
mAlbumArtRadius = mContext.getResources().getDimension(R.dimen.qs_media_corner_radius);
|
||||
mAlbumArtSize = (int) mContext.getResources().getDimension(
|
||||
R.dimen.qs_media_album_size);
|
||||
}
|
||||
}
|
||||
|
||||
/** Observer for state changes of lock screen media controls. */
|
||||
private static final class KeyguardMediaObserver implements Observer<KeyguardMedia> {
|
||||
|
||||
private final View mRootView;
|
||||
private final MediaHeaderView mMediaHeaderView;
|
||||
private final ImageView mAlbumView;
|
||||
private final ImageView mAppIconView;
|
||||
private final TextView mAppNameView;
|
||||
private final TextView mTitleView;
|
||||
private final TextView mArtistView;
|
||||
private final List<ImageButton> mButtonViews = new ArrayList<>();
|
||||
|
||||
KeyguardMediaObserver(View v) {
|
||||
mRootView = v;
|
||||
mMediaHeaderView = v instanceof MediaHeaderView ? (MediaHeaderView) v : null;
|
||||
mAlbumView = v.findViewById(R.id.album_art);
|
||||
mAppIconView = v.findViewById(R.id.icon);
|
||||
mAppNameView = v.findViewById(R.id.app_name);
|
||||
mTitleView = v.findViewById(R.id.header_title);
|
||||
mArtistView = v.findViewById(R.id.header_artist);
|
||||
for (int i = 0; i < ACTION_IDS.length; i++) {
|
||||
mButtonViews.add(v.findViewById(ACTION_IDS[i]));
|
||||
}
|
||||
Icon icon = icons.get(i);
|
||||
if (icon == null) {
|
||||
button.setVisibility(View.GONE);
|
||||
} else {
|
||||
button.setVisibility(View.VISIBLE);
|
||||
button.setImageDrawable(icon.loadDrawable(packageContext));
|
||||
button.setImageTintList(ColorStateList.valueOf(fgColor));
|
||||
final PendingIntent intent = intents.get(i);
|
||||
if (intent != null) {
|
||||
button.setOnClickListener(v -> {
|
||||
try {
|
||||
intent.send();
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
Log.d(TAG, "failed to send action intent", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Updates lock screen media player views when state changes. */
|
||||
@Override
|
||||
public void onChanged(KeyguardMedia data) {
|
||||
if (data == null) {
|
||||
mRootView.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
mRootView.setVisibility(View.VISIBLE);
|
||||
|
||||
// Background color
|
||||
if (mMediaHeaderView != null) {
|
||||
mMediaHeaderView.setBackgroundColor(data.getBackgroundColor());
|
||||
}
|
||||
|
||||
// Album art
|
||||
if (mAlbumView != null) {
|
||||
mAlbumView.setImageDrawable(data.getArtwork());
|
||||
mAlbumView.setVisibility(data.getArtwork() == null ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
// App icon
|
||||
if (mAppIconView != null) {
|
||||
Drawable iconDrawable = data.getAppIcon();
|
||||
iconDrawable.setTint(data.getForegroundColor());
|
||||
mAppIconView.setImageDrawable(iconDrawable);
|
||||
}
|
||||
|
||||
// App name
|
||||
if (mAppNameView != null) {
|
||||
String appNameString = data.getApp();
|
||||
mAppNameView.setText(appNameString);
|
||||
mAppNameView.setTextColor(data.getForegroundColor());
|
||||
}
|
||||
|
||||
// Song name
|
||||
if (mTitleView != null) {
|
||||
mTitleView.setText(data.getSong());
|
||||
mTitleView.setTextColor(data.getForegroundColor());
|
||||
}
|
||||
|
||||
// Artist name
|
||||
if (mArtistView != null) {
|
||||
mArtistView.setText(data.getArtist());
|
||||
mArtistView.setTextColor(data.getForegroundColor());
|
||||
}
|
||||
|
||||
// Control buttons
|
||||
for (int i = 0; i < ACTION_IDS.length; i++) {
|
||||
ImageButton button = mButtonViews.get(i);
|
||||
if (button == null) {
|
||||
continue;
|
||||
}
|
||||
Drawable icon = data.getActionIcons().get(i);
|
||||
if (icon == null) {
|
||||
button.setVisibility(View.GONE);
|
||||
button.setImageDrawable(null);
|
||||
} else {
|
||||
button.setVisibility(View.VISIBLE);
|
||||
button.setImageDrawable(icon);
|
||||
button.setImageTintList(ColorStateList.valueOf(data.getForegroundColor()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process album art for layout
|
||||
* @param albumArt bitmap to use for album art
|
||||
* @param albumView view to hold the album art
|
||||
*/
|
||||
private void processAlbumArt(Bitmap albumArt, ImageView albumView) {
|
||||
RoundedBitmapDrawable roundedDrawable = null;
|
||||
if (albumArt != null) {
|
||||
Bitmap original = albumArt.copy(Bitmap.Config.ARGB_8888, true);
|
||||
Bitmap scaled = Bitmap.createScaledBitmap(original, mAlbumArtSize, mAlbumArtSize,
|
||||
false);
|
||||
roundedDrawable = RoundedBitmapDrawableFactory.create(mContext.getResources(), scaled);
|
||||
roundedDrawable.setCornerRadius(mAlbumArtRadius);
|
||||
} else {
|
||||
Log.e(TAG, "No album art available");
|
||||
}
|
||||
|
||||
// Now that it's resized, update the UI
|
||||
final RoundedBitmapDrawable result = roundedDrawable;
|
||||
albumView.post(() -> {
|
||||
albumView.setImageDrawable(result);
|
||||
albumView.setVisibility(result == null ? View.GONE : View.VISIBLE);
|
||||
});
|
||||
}
|
||||
|
||||
private void loadDimens() {
|
||||
mAlbumArtRadius = mContext.getResources().getDimension(R.dimen.qs_media_corner_radius);
|
||||
mAlbumArtSize = (int) mContext.getResources().getDimension(
|
||||
R.dimen.qs_media_album_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.arch.core.executor.ArchTaskExecutor
|
||||
import androidx.arch.core.executor.TaskExecutor
|
||||
import androidx.test.filters.SmallTest
|
||||
|
||||
import com.android.systemui.R
|
||||
@@ -50,25 +52,46 @@ public class KeyguardMediaPlayerTest : SysuiTestCase() {
|
||||
private lateinit var mediaMetadata: MediaMetadata.Builder
|
||||
private lateinit var entry: NotificationEntryBuilder
|
||||
@Mock private lateinit var mockView: View
|
||||
private lateinit var textView: TextView
|
||||
private lateinit var songView: TextView
|
||||
private lateinit var artistView: TextView
|
||||
@Mock private lateinit var mockIcon: Icon
|
||||
|
||||
private val taskExecutor: TaskExecutor = object : TaskExecutor() {
|
||||
public override fun executeOnDiskIO(runnable: Runnable) {
|
||||
runnable.run()
|
||||
}
|
||||
public override fun postToMainThread(runnable: Runnable) {
|
||||
runnable.run()
|
||||
}
|
||||
public override fun isMainThread(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public fun setup() {
|
||||
fakeExecutor = FakeExecutor(FakeSystemClock())
|
||||
keyguardMediaPlayer = KeyguardMediaPlayer(context, fakeExecutor)
|
||||
mockView = mock(View::class.java)
|
||||
textView = TextView(context)
|
||||
mockIcon = mock(Icon::class.java)
|
||||
|
||||
mockView = mock(View::class.java)
|
||||
songView = TextView(context)
|
||||
artistView = TextView(context)
|
||||
whenever<TextView>(mockView.findViewById(R.id.header_title)).thenReturn(songView)
|
||||
whenever<TextView>(mockView.findViewById(R.id.header_artist)).thenReturn(artistView)
|
||||
|
||||
mediaMetadata = MediaMetadata.Builder()
|
||||
entry = NotificationEntryBuilder()
|
||||
|
||||
ArchTaskExecutor.getInstance().setDelegate(taskExecutor)
|
||||
|
||||
keyguardMediaPlayer.bindView(mockView)
|
||||
}
|
||||
|
||||
@After
|
||||
public fun tearDown() {
|
||||
keyguardMediaPlayer.unbindView()
|
||||
ArchTaskExecutor.getInstance().setDelegate(null)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -87,34 +110,36 @@ public class KeyguardMediaPlayerTest : SysuiTestCase() {
|
||||
@Test
|
||||
public fun testUpdateControls() {
|
||||
keyguardMediaPlayer.updateControls(entry.build(), mockIcon, mediaMetadata.build())
|
||||
FakeExecutor.exhaustExecutors(fakeExecutor)
|
||||
verify(mockView).setVisibility(View.VISIBLE)
|
||||
}
|
||||
|
||||
@Test
|
||||
public fun testClearControls() {
|
||||
keyguardMediaPlayer.clearControls()
|
||||
FakeExecutor.exhaustExecutors(fakeExecutor)
|
||||
verify(mockView).setVisibility(View.GONE)
|
||||
}
|
||||
|
||||
@Test
|
||||
public fun testSongName() {
|
||||
whenever<TextView>(mockView.findViewById(R.id.header_title)).thenReturn(textView)
|
||||
val song: String = "Song"
|
||||
mediaMetadata.putText(MediaMetadata.METADATA_KEY_TITLE, song)
|
||||
|
||||
keyguardMediaPlayer.updateControls(entry.build(), mockIcon, mediaMetadata.build())
|
||||
|
||||
assertThat(textView.getText()).isEqualTo(song)
|
||||
assertThat(fakeExecutor.runAllReady()).isEqualTo(1)
|
||||
assertThat(songView.getText()).isEqualTo(song)
|
||||
}
|
||||
|
||||
@Test
|
||||
public fun testArtistName() {
|
||||
whenever<TextView>(mockView.findViewById(R.id.header_artist)).thenReturn(textView)
|
||||
val artist: String = "Artist"
|
||||
mediaMetadata.putText(MediaMetadata.METADATA_KEY_ARTIST, artist)
|
||||
|
||||
keyguardMediaPlayer.updateControls(entry.build(), mockIcon, mediaMetadata.build())
|
||||
|
||||
assertThat(textView.getText()).isEqualTo(artist)
|
||||
assertThat(fakeExecutor.runAllReady()).isEqualTo(1)
|
||||
assertThat(artistView.getText()).isEqualTo(artist)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user