summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2020-04-08 05:23:37 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-04-08 05:23:37 +0000
commit0dcd72e1de2dc5d25fc746ae55bf9f9400c7149c (patch)
tree88057863a66674ebf7ef6fb4eb37bc2789176fa4
parent13c689cb12db196b667e314d27861215813a4cc6 (diff)
parent13bc4269d6c73e2dc51d8d873009ae31049ef674 (diff)
Merge "Close LS media player when session is destroyed" into rvc-dev
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardMediaPlayer.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControllerFactory.java45
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardMediaPlayerTest.kt43
3 files changed, 102 insertions, 9 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMediaPlayer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMediaPlayer.java
index d1544346a25a..af5196f92bcb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMediaPlayer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMediaPlayer.java
@@ -24,6 +24,8 @@ import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.media.MediaMetadata;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
@@ -40,6 +42,7 @@ import androidx.palette.graphics.Palette;
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.media.MediaControllerFactory;
import com.android.systemui.statusbar.notification.MediaNotificationProcessor;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.stack.MediaHeaderView;
@@ -71,10 +74,11 @@ public class KeyguardMediaPlayer {
private KeyguardMediaObserver mObserver;
@Inject
- public KeyguardMediaPlayer(Context context, @Background Executor backgroundExecutor) {
+ public KeyguardMediaPlayer(Context context, MediaControllerFactory factory,
+ @Background Executor backgroundExecutor) {
mContext = context;
mBackgroundExecutor = backgroundExecutor;
- mViewModel = new KeyguardMediaViewModel(context);
+ mViewModel = new KeyguardMediaViewModel(context, factory);
}
/** Binds media controls to a view hierarchy. */
@@ -139,14 +143,16 @@ public class KeyguardMediaPlayer {
private static final class KeyguardMediaViewModel {
private final Context mContext;
+ private final MediaControllerFactory mMediaControllerFactory;
private final MutableLiveData<KeyguardMedia> mMedia = new MutableLiveData<>();
private final Object mActionsLock = new Object();
private List<PendingIntent> mActions;
private float mAlbumArtRadius;
private int mAlbumArtSize;
- KeyguardMediaViewModel(Context context) {
+ KeyguardMediaViewModel(Context context, MediaControllerFactory factory) {
mContext = context;
+ mMediaControllerFactory = factory;
loadDimens();
}
@@ -162,6 +168,17 @@ public class KeyguardMediaPlayer {
public void updateControls(NotificationEntry entry, Icon appIcon,
MediaMetadata mediaMetadata) {
+ // Check the playback state of the media controller. If it is null, then the session was
+ // probably destroyed. Don't update in this case.
+ final MediaSession.Token token = entry.getSbn().getNotification().extras
+ .getParcelable(Notification.EXTRA_MEDIA_SESSION);
+ final MediaController controller = token != null
+ ? mMediaControllerFactory.create(token) : null;
+ if (controller != null && controller.getPlaybackState() == null) {
+ clearControls();
+ return;
+ }
+
// Foreground and Background colors computed from album art
Notification notif = entry.getSbn().getNotification();
int fgColor = notif.color;
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControllerFactory.java b/packages/SystemUI/src/com/android/systemui/media/MediaControllerFactory.java
new file mode 100644
index 000000000000..71bc7c20c026
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControllerFactory.java
@@ -0,0 +1,45 @@
+/*
+ * 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.systemui.media;
+
+import android.content.Context;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+
+import javax.inject.Inject;
+
+/**
+ * Testable wrapper around {@link MediaController} constructor.
+ */
+public class MediaControllerFactory {
+
+ private final Context mContext;
+
+ @Inject
+ public MediaControllerFactory(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Creates a new MediaController from a session's token.
+ *
+ * @param token The token for the session. This value must never be null.
+ */
+ public MediaController create(MediaSession.Token token) {
+ return new MediaController(mContext, token);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMediaPlayerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMediaPlayerTest.kt
index 072bc446fd21..4bcf917fa95d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMediaPlayerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMediaPlayerTest.kt
@@ -16,8 +16,12 @@
package com.android.keyguard
+import android.app.Notification
import android.graphics.drawable.Icon
import android.media.MediaMetadata
+import android.media.session.MediaController
+import android.media.session.MediaSession
+import android.media.session.PlaybackState
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.View
@@ -28,7 +32,9 @@ import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.media.MediaControllerFactory
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -38,6 +44,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.any
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
@@ -48,9 +55,12 @@ import org.mockito.Mockito.`when` as whenever
public class KeyguardMediaPlayerTest : SysuiTestCase() {
private lateinit var keyguardMediaPlayer: KeyguardMediaPlayer
+ @Mock private lateinit var mockMediaFactory: MediaControllerFactory
+ @Mock private lateinit var mockMediaController: MediaController
+ private lateinit var playbackState: PlaybackState
private lateinit var fakeExecutor: FakeExecutor
private lateinit var mediaMetadata: MediaMetadata.Builder
- private lateinit var entry: NotificationEntryBuilder
+ private lateinit var entry: NotificationEntry
@Mock private lateinit var mockView: View
private lateinit var songView: TextView
private lateinit var artistView: TextView
@@ -70,8 +80,16 @@ public class KeyguardMediaPlayerTest : SysuiTestCase() {
@Before
public fun setup() {
+ playbackState = PlaybackState.Builder().run {
+ build()
+ }
+ mockMediaController = mock(MediaController::class.java)
+ whenever(mockMediaController.getPlaybackState()).thenReturn(playbackState)
+ mockMediaFactory = mock(MediaControllerFactory::class.java)
+ whenever(mockMediaFactory.create(any())).thenReturn(mockMediaController)
+
fakeExecutor = FakeExecutor(FakeSystemClock())
- keyguardMediaPlayer = KeyguardMediaPlayer(context, fakeExecutor)
+ keyguardMediaPlayer = KeyguardMediaPlayer(context, mockMediaFactory, fakeExecutor)
mockIcon = mock(Icon::class.java)
mockView = mock(View::class.java)
@@ -81,7 +99,9 @@ public class KeyguardMediaPlayerTest : SysuiTestCase() {
whenever<TextView>(mockView.findViewById(R.id.header_artist)).thenReturn(artistView)
mediaMetadata = MediaMetadata.Builder()
- entry = NotificationEntryBuilder()
+ entry = NotificationEntryBuilder().build()
+ entry.getSbn().getNotification().extras.putParcelable(Notification.EXTRA_MEDIA_SESSION,
+ MediaSession.Token(1, null))
ArchTaskExecutor.getInstance().setDelegate(taskExecutor)
@@ -109,7 +129,7 @@ public class KeyguardMediaPlayerTest : SysuiTestCase() {
@Test
public fun testUpdateControls() {
- keyguardMediaPlayer.updateControls(entry.build(), mockIcon, mediaMetadata.build())
+ keyguardMediaPlayer.updateControls(entry, mockIcon, mediaMetadata.build())
FakeExecutor.exhaustExecutors(fakeExecutor)
verify(mockView).setVisibility(View.VISIBLE)
}
@@ -122,11 +142,22 @@ public class KeyguardMediaPlayerTest : SysuiTestCase() {
}
@Test
+ public fun testUpdateControlsNullPlaybackState() {
+ // GIVEN that the playback state is null (ie. the media session was destroyed)
+ whenever(mockMediaController.getPlaybackState()).thenReturn(null)
+ // WHEN updated
+ keyguardMediaPlayer.updateControls(entry, mockIcon, mediaMetadata.build())
+ FakeExecutor.exhaustExecutors(fakeExecutor)
+ // THEN the controls are cleared (ie. visibility is set to GONE)
+ verify(mockView).setVisibility(View.GONE)
+ }
+
+ @Test
public fun testSongName() {
val song: String = "Song"
mediaMetadata.putText(MediaMetadata.METADATA_KEY_TITLE, song)
- keyguardMediaPlayer.updateControls(entry.build(), mockIcon, mediaMetadata.build())
+ keyguardMediaPlayer.updateControls(entry, mockIcon, mediaMetadata.build())
assertThat(fakeExecutor.runAllReady()).isEqualTo(1)
assertThat(songView.getText()).isEqualTo(song)
@@ -137,7 +168,7 @@ public class KeyguardMediaPlayerTest : SysuiTestCase() {
val artist: String = "Artist"
mediaMetadata.putText(MediaMetadata.METADATA_KEY_ARTIST, artist)
- keyguardMediaPlayer.updateControls(entry.build(), mockIcon, mediaMetadata.build())
+ keyguardMediaPlayer.updateControls(entry, mockIcon, mediaMetadata.build())
assertThat(fakeExecutor.runAllReady()).isEqualTo(1)
assertThat(artistView.getText()).isEqualTo(artist)