diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt index 1004e257c7503..3251ab2e4d508 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt @@ -156,6 +156,12 @@ class MediaCarouselController @Inject constructor( } } + /** + * Update MediaCarouselScrollHandler.visibleToUser to reflect media card container visibility. + * It will be called when the container is out of view. + */ + lateinit var updateUserVisibility: () -> Unit + init { mediaFrame = inflateMediaCarousel() mediaCarousel = mediaFrame.requireViewById(R.id.media_carousel_scroller) @@ -177,6 +183,12 @@ class MediaCarouselController @Inject constructor( keysNeedRemoval.forEach { removePlayer(it) } keysNeedRemoval.clear() + // Update user visibility so that no extra impression will be logged when + // activeMediaIndex resets to 0 + if (this::updateUserVisibility.isInitialized) { + updateUserVisibility() + } + // Let's reset our scroll position mediaCarouselScrollHandler.scrollToStart() } @@ -187,16 +199,24 @@ class MediaCarouselController @Inject constructor( key: String, oldKey: String?, data: MediaData, - immediately: Boolean + immediately: Boolean, + isSsReactivated: Boolean ) { if (addOrUpdatePlayer(key, oldKey, data)) { MediaPlayerData.getMediaPlayer(key, null)?.let { logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, /* isRecommendationCard */ false, - it.surfaceForSmartspaceLogging) + it.surfaceForSmartspaceLogging, + rank = MediaPlayerData.getMediaPlayerIndex(key)) } } + if (mediaCarouselScrollHandler.visibleToUser && + isSsReactivated && !mediaCarouselScrollHandler.qsExpanded) { + // It could happen that reactived media player isn't visible to user because + // of it is a resumption card. + logSmartspaceImpression(mediaCarouselScrollHandler.qsExpanded) + } val canRemove = data.isPlaying?.let { !it } ?: data.isClearable && !data.active if (canRemove && !Utils.useMediaResumption(context)) { // This view isn't playing, let's remove this! This happens e.g when @@ -224,10 +244,17 @@ class MediaCarouselController @Inject constructor( logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, /* isRecommendationCard */ true, - it.surfaceForSmartspaceLogging) - } - if (mediaCarouselScrollHandler.visibleToUser) { - logSmartspaceImpression() + it.surfaceForSmartspaceLogging, + rank = MediaPlayerData.getMediaPlayerIndex(key)) + + if (mediaCarouselScrollHandler.visibleToUser && + mediaCarouselScrollHandler.visibleMediaIndex == + MediaPlayerData.getMediaPlayerIndex(key)) { + logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN + it.mInstanceId, + /* isRecommendationCard */ true, + it.surfaceForSmartspaceLogging) + } } } else { onSmartspaceMediaDataRemoved(data.targetId, immediately = true) @@ -644,17 +671,17 @@ class MediaCarouselController @Inject constructor( } /** - * Log the user impression for media card. + * Log the user impression for media card at visibleMediaIndex. */ - fun logSmartspaceImpression() { + fun logSmartspaceImpression(qsExpanded: Boolean) { val visibleMediaIndex = mediaCarouselScrollHandler.visibleMediaIndex if (MediaPlayerData.players().size > visibleMediaIndex) { val mediaControlPanel = MediaPlayerData.players().elementAt(visibleMediaIndex) - val isMediaActive = - MediaPlayerData.playerKeys().elementAt(visibleMediaIndex).data?.active + val hasActiveMediaOrRecommendationCard = + MediaPlayerData.hasActiveMediaOrRecommendationCard() val isRecommendationCard = mediaControlPanel.recommendationViewHolder != null - if (!isRecommendationCard && !isMediaActive) { - // Media control card time out or swiped away + if (!hasActiveMediaOrRecommendationCard && !qsExpanded) { + // Skip logging if on LS or QQS, and there is no active media card return } logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN @@ -672,6 +699,13 @@ class MediaCarouselController @Inject constructor( surface: Int, rank: Int = mediaCarouselScrollHandler.visibleMediaIndex ) { + // Only log media resume card when Smartspace data is available + if (!isRecommendationCard && + !mediaManager.smartspaceMediaData.isActive && + MediaPlayerData.smartspaceMediaData == null) { + return + } + /* ktlint-disable max-line-length */ SysUiStatsLog.write(SysUiStatsLog.SMARTSPACE_CARD_REPORTED, eventId, @@ -770,6 +804,16 @@ internal object MediaPlayerData { return mediaData.get(key)?.let { mediaPlayers.get(it) } } + fun getMediaPlayerIndex(key: String): Int { + val sortKey = mediaData.get(key) + mediaPlayers.entries.forEachIndexed { index, e -> + if (e.key == sortKey) { + return index + } + } + return -1 + } + fun removeMediaPlayer(key: String) = mediaData.remove(key)?.let { if (it.isSsMediaRec) { smartspaceMediaData = null @@ -808,4 +852,15 @@ internal object MediaPlayerData { mediaData.clear() mediaPlayers.clear() } + + /* Returns true if there is active media player card or recommendation card */ + fun hasActiveMediaOrRecommendationCard(): Boolean { + if (smartspaceMediaData != null && smartspaceMediaData?.isActive!!) { + return true + } + if (firstActiveMediaIndex() != -1) { + return true + } + return false + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt index eb3549789c19b..b0d4cb1c98187 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt @@ -62,7 +62,7 @@ class MediaCarouselScrollHandler( private val closeGuts: (immediate: Boolean) -> Unit, private val falsingCollector: FalsingCollector, private val falsingManager: FalsingManager, - private val logSmartspaceImpression: () -> Unit + private val logSmartspaceImpression: (Boolean) -> Unit ) { /** * Is the view in RTL @@ -195,18 +195,22 @@ class MediaCarouselScrollHandler( if (playerWidthPlusPadding == 0) { return } + val relativeScrollX = scrollView.relativeScrollX onMediaScrollingChanged(relativeScrollX / playerWidthPlusPadding, relativeScrollX % playerWidthPlusPadding) } } + /** + * Whether the media card is visible to user if any + */ var visibleToUser: Boolean = false - set(value) { - if (field != value) { - field = value - } - } + + /** + * Whether the quick setting is expanded or not + */ + var qsExpanded: Boolean = false init { gestureDetector = GestureDetectorCompat(scrollView.context, gestureListener) @@ -471,7 +475,7 @@ class MediaCarouselScrollHandler( val oldIndex = visibleMediaIndex visibleMediaIndex = newIndex if (oldIndex != visibleMediaIndex && visibleToUser) { - logSmartspaceImpression() + logSmartspaceImpression(qsExpanded) } closeGuts(false) updatePlayerVisibilities() diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index 19190cd4a17d4..19a67e95a496e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -266,7 +266,7 @@ public class MediaControlPanel { } mKey = key; MediaSession.Token token = data.getToken(); - mInstanceId = data.getPackageName().hashCode(); + mInstanceId = SmallHash.hash(data.getPackageName()); mBackgroundColor = data.getBackgroundColor(); if (mToken == null || !mToken.equals(token)) { @@ -504,7 +504,7 @@ public class MediaControlPanel { return; } - mInstanceId = data.getTargetId().hashCode(); + mInstanceId = SmallHash.hash(data.getTargetId()); mBackgroundColor = data.getBackgroundColor(); TransitionLayout recommendationCard = mRecommendationViewHolder.getRecommendations(); recommendationCard.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor)); diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt index ee1d3ea87da8d..296bfda89432b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt @@ -31,7 +31,8 @@ class MediaDataCombineLatest @Inject constructor() : MediaDataManager.Listener, key: String, oldKey: String?, data: MediaData, - immediately: Boolean + immediately: Boolean, + isSsReactivated: Boolean ) { if (oldKey != null && oldKey != key && entries.contains(oldKey)) { entries[key] = data to entries.remove(oldKey)?.second diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt index a611b600f47f8..c8deb014f7814 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt @@ -83,7 +83,8 @@ class MediaDataFilter @Inject constructor( key: String, oldKey: String?, data: MediaData, - immediately: Boolean + immediately: Boolean, + isSsReactivated: Boolean ) { if (oldKey != null && oldKey != key) { allEntries.remove(oldKey) @@ -101,7 +102,7 @@ class MediaDataFilter @Inject constructor( // Notify listeners listeners.forEach { - it.onMediaDataLoaded(key, oldKey, data) + it.onMediaDataLoaded(key, oldKey, data, isSsReactivated = isSsReactivated) } } @@ -118,6 +119,8 @@ class MediaDataFilter @Inject constructor( // Override the pass-in value here, as the order of Smartspace card is only determined here. var shouldPrioritizeMutable = false smartspaceMediaData = data + // Override the pass-in value here, as the Smartspace reactivation could only happen here. + var isSsReactivated = false // Before forwarding the smartspace target, first check if we have recently inactive media val sorted = userEntries.toSortedMap(compareBy { @@ -137,9 +140,13 @@ class MediaDataFilter @Inject constructor( // Notify listeners to consider this media active Log.d(TAG, "reactivating $lastActiveKey instead of smartspace") reactivatedKey = lastActiveKey + if (MediaPlayerData.firstActiveMediaIndex() == -1) { + isSsReactivated = true + } val mediaData = sorted.get(lastActiveKey)!!.copy(active = true) listeners.forEach { - it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData) + it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData, + isSsReactivated = isSsReactivated) } } else { // Mark to prioritize Smartspace card if no recent media. diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index 28d336ea18d5a..ed6f5505cbd16 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -148,7 +148,7 @@ class MediaDataManager( private val internalListeners: MutableSet = mutableSetOf() private val mediaEntries: LinkedHashMap = LinkedHashMap() // There should ONLY be at most one Smartspace media recommendation. - private var smartspaceMediaData: SmartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA + var smartspaceMediaData: SmartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA private var smartspaceSession: SmartspaceSession? = null private var allowMediaRecommendations = Utils.allowMediaRecommendations(context) @@ -824,12 +824,16 @@ class MediaDataManager( * @param immediately indicates should apply the UI changes immediately, otherwise wait * until the next refresh-round before UI becomes visible. True by default to take in place * immediately. + * + * @param isSsReactivated indicates transition from a state with no active media players to + * a state with active media players upon receiving Smartspace media data. */ fun onMediaDataLoaded( key: String, oldKey: String?, data: MediaData, - immediately: Boolean = true + immediately: Boolean = true, + isSsReactivated: Boolean = false ) {} /** diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt index 52ecbea059243..292b0e291244c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt @@ -67,7 +67,8 @@ class MediaDeviceManager @Inject constructor( key: String, oldKey: String?, data: MediaData, - immediately: Boolean + immediately: Boolean, + isSsReactivated: Boolean ) { if (oldKey != null && oldKey != key) { val oldEntry = entries.remove(oldKey) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt index edbf18789e285..3d1b4fbde56ae 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt @@ -220,14 +220,11 @@ class MediaHierarchyManager @Inject constructor( set(value) { if (field != value) { field = value + mediaCarouselController.mediaCarouselScrollHandler.qsExpanded = value } // qs is expanded on LS shade and HS shade if (value && (isLockScreenShadeVisibleToUser() || isHomeScreenShadeVisibleToUser())) { - mediaCarouselController.logSmartspaceImpression() - } - // Release shade and back to lock screen - if (isLockScreenVisibleToUser()) { - mediaCarouselController.logSmartspaceImpression() + mediaCarouselController.logSmartspaceImpression(value) } mediaCarouselController.mediaCarouselScrollHandler.visibleToUser = isVisibleToUser() } @@ -409,7 +406,7 @@ class MediaHierarchyManager @Inject constructor( updateTargetState() // Enters shade from lock screen if (newState == StatusBarState.SHADE_LOCKED && isLockScreenShadeVisibleToUser()) { - mediaCarouselController.logSmartspaceImpression() + mediaCarouselController.logSmartspaceImpression(qsExpanded) } mediaCarouselController.mediaCarouselScrollHandler.visibleToUser = isVisibleToUser() } @@ -423,7 +420,7 @@ class MediaHierarchyManager @Inject constructor( dozeAnimationRunning = false // Enters lock screen from screen off if (isLockScreenVisibleToUser()) { - mediaCarouselController.logSmartspaceImpression() + mediaCarouselController.logSmartspaceImpression(qsExpanded) } } else { updateDesiredLocation() @@ -436,11 +433,7 @@ class MediaHierarchyManager @Inject constructor( override fun onExpandedChanged(isExpanded: Boolean) { // Enters shade from home screen if (isHomeScreenShadeVisibleToUser()) { - mediaCarouselController.logSmartspaceImpression() - } - // Back to lock screen from bouncer - if (isLockScreenVisibleToUser()) { - mediaCarouselController.logSmartspaceImpression() + mediaCarouselController.logSmartspaceImpression(qsExpanded) } mediaCarouselController.mediaCarouselScrollHandler.visibleToUser = isVisibleToUser() } @@ -465,6 +458,10 @@ class MediaHierarchyManager @Inject constructor( goingToSleep = false } }) + + mediaCarouselController.updateUserVisibility = { + mediaCarouselController.mediaCarouselScrollHandler.visibleToUser = isVisibleToUser() + } } private fun updateConfiguration() { diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt index 43e21424c45e5..ff085c36ef9c9 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt @@ -60,7 +60,8 @@ class MediaHost constructor( key: String, oldKey: String?, data: MediaData, - immediately: Boolean + immediately: Boolean, + isSsReactivated: Boolean ) { if (immediately) { updateViewVisibility() diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt index 0da84fbac6000..ab568c8c5a855 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt @@ -159,7 +159,8 @@ class MediaResumeListener @Inject constructor( key: String, oldKey: String?, data: MediaData, - immediately: Boolean + immediately: Boolean, + isSsReactivated: Boolean ) { if (useMediaResumption) { // If this had been started from a resume state, disconnect now that it's live diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt index a4f33e354b68b..8bddde839817c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt @@ -95,7 +95,8 @@ class MediaSessionBasedFilter @Inject constructor( key: String, oldKey: String?, data: MediaData, - immediately: Boolean + immediately: Boolean, + isSsReactivated: Boolean ) { backgroundExecutor.execute { data.token?.let { diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt index bbea140ecfaf8..9a3919326cbd7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt @@ -54,7 +54,8 @@ class MediaTimeoutListener @Inject constructor( key: String, oldKey: String?, data: MediaData, - immediately: Boolean + immediately: Boolean, + isSsReactivated: Boolean ) { var reusedListener: PlaybackStateListener? = null diff --git a/packages/SystemUI/src/com/android/systemui/media/SmallHash.java b/packages/SystemUI/src/com/android/systemui/media/SmallHash.java new file mode 100644 index 0000000000000..de7aac609955a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/SmallHash.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021 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 java.util.Objects; + +/** + * A simple hash function for use in privacy-sensitive logging. + */ +public final class SmallHash { + // Hashes will be in the range [0, MAX_HASH). + public static final int MAX_HASH = (1 << 13); + + /** Return Small hash of the string, if non-null, or 0 otherwise. */ + public static int hash(String in) { + return hash(Objects.hashCode(in)); + } + + /** + * Maps in to the range [0, MAX_HASH), keeping similar values distinct. + * + * @param in An arbitrary integer. + * @return in mod MAX_HASH, signs chosen to stay in the range [0, MAX_HASH). + */ + public static int hash(int in) { + return Math.abs(Math.floorMod(in, MAX_HASH)); + } + + private SmallHash() {} +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index a69b8d60681cc..25cbdc5c2187e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -245,7 +245,8 @@ public class NotificationMediaManager implements Dumpable { mMediaDataManager.addListener(new MediaDataManager.Listener() { @Override public void onMediaDataLoaded(@NonNull String key, - @Nullable String oldKey, @NonNull MediaData data, boolean immediately) { + @Nullable String oldKey, @NonNull MediaData data, boolean immediately, + boolean isSsReactivated) { } @Override @@ -318,7 +319,8 @@ public class NotificationMediaManager implements Dumpable { mMediaDataManager.addListener(new MediaDataManager.Listener() { @Override public void onMediaDataLoaded(@NonNull String key, - @Nullable String oldKey, @NonNull MediaData data, boolean immediately) { + @Nullable String oldKey, @NonNull MediaData data, boolean immediately, + boolean isSsReactivated) { } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java index e20b426907be4..66b64708ad24c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java @@ -82,9 +82,11 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void eventNotEmittedWithoutDevice() { // WHEN data source emits an event without device data - mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, + false /* isSsReactivated */); // THEN an event isn't emitted - verify(mListener, never()).onMediaDataLoaded(eq(KEY), any(), any(), anyBoolean()); + verify(mListener, never()).onMediaDataLoaded(eq(KEY), any(), any(), anyBoolean(), + anyBoolean()); } @Test @@ -92,7 +94,8 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { // WHEN device source emits an event without media data mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // THEN an event isn't emitted - verify(mListener, never()).onMediaDataLoaded(eq(KEY), any(), any(), anyBoolean()); + verify(mListener, never()).onMediaDataLoaded(eq(KEY), any(), any(), anyBoolean(), + anyBoolean()); } @Test @@ -100,80 +103,95 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { // GIVEN that a device event has already been received mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // WHEN media event is received - mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, + false /* isSsReactivated */); // THEN the listener receives a combined event ArgumentCaptor captor = ArgumentCaptor.forClass(MediaData.class); - verify(mListener).onMediaDataLoaded(eq(KEY), any(), captor.capture(), anyBoolean()); + verify(mListener).onMediaDataLoaded(eq(KEY), any(), captor.capture(), anyBoolean(), + anyBoolean()); assertThat(captor.getValue().getDevice()).isNotNull(); } @Test public void emitEventAfterMediaFirst() { // GIVEN that media event has already been received - mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, + false /* isSsReactivated */); // WHEN device event is received mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // THEN the listener receives a combined event ArgumentCaptor captor = ArgumentCaptor.forClass(MediaData.class); - verify(mListener).onMediaDataLoaded(eq(KEY), any(), captor.capture(), anyBoolean()); + verify(mListener).onMediaDataLoaded(eq(KEY), any(), captor.capture(), anyBoolean(), + anyBoolean()); assertThat(captor.getValue().getDevice()).isNotNull(); } @Test public void migrateKeyMediaFirst() { // GIVEN that media and device info has already been received - mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */, + false /* isSsReactivated */); mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); reset(mListener); // WHEN a key migration event is received - mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData, true /* immediately */, + false /* isSsReactivated */); // THEN the listener receives a combined event ArgumentCaptor captor = ArgumentCaptor.forClass(MediaData.class); - verify(mListener).onMediaDataLoaded(eq(KEY), eq(OLD_KEY), captor.capture(), anyBoolean()); + verify(mListener).onMediaDataLoaded(eq(KEY), eq(OLD_KEY), captor.capture(), anyBoolean(), + anyBoolean()); assertThat(captor.getValue().getDevice()).isNotNull(); } @Test public void migrateKeyDeviceFirst() { // GIVEN that media and device info has already been received - mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */, + false /* isSsReactivated */); mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); reset(mListener); // WHEN a key migration event is received mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); // THEN the listener receives a combined event ArgumentCaptor captor = ArgumentCaptor.forClass(MediaData.class); - verify(mListener).onMediaDataLoaded(eq(KEY), eq(OLD_KEY), captor.capture(), anyBoolean()); + verify(mListener).onMediaDataLoaded(eq(KEY), eq(OLD_KEY), captor.capture(), anyBoolean(), + anyBoolean()); assertThat(captor.getValue().getDevice()).isNotNull(); } @Test public void migrateKeyMediaAfter() { // GIVEN that media and device info has already been received - mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */, + false /* isSsReactivated */); mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); reset(mListener); // WHEN a second key migration event is received for media - mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData, true /* immediately */, + false /* isSsReactivated */); // THEN the key has already been migrated ArgumentCaptor captor = ArgumentCaptor.forClass(MediaData.class); - verify(mListener).onMediaDataLoaded(eq(KEY), eq(KEY), captor.capture(), anyBoolean()); + verify(mListener).onMediaDataLoaded(eq(KEY), eq(KEY), captor.capture(), anyBoolean(), + anyBoolean()); assertThat(captor.getValue().getDevice()).isNotNull(); } @Test public void migrateKeyDeviceAfter() { // GIVEN that media and device info has already been received - mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */, + false /* isSsReactivated */); mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); - mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData, true /* immediately */, + false /* isSsReactivated */); reset(mListener); // WHEN a second key migration event is received for the device mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); // THEN the key has already be migrated ArgumentCaptor captor = ArgumentCaptor.forClass(MediaData.class); - verify(mListener).onMediaDataLoaded(eq(KEY), eq(KEY), captor.capture(), anyBoolean()); + verify(mListener).onMediaDataLoaded(eq(KEY), eq(KEY), captor.capture(), anyBoolean(), + anyBoolean()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -187,7 +205,8 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void mediaDataRemovedAfterMediaEvent() { - mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, + false /* isSsReactivated */); mManager.onMediaDataRemoved(KEY); verify(mListener).onMediaDataRemoved(eq(KEY)); } @@ -202,13 +221,15 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void mediaDataKeyUpdated() { // GIVEN that device and media events have already been received - mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, + false /* isSsReactivated */); mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // WHEN the key is changed - mManager.onMediaDataLoaded("NEW_KEY", KEY, mMediaData, true /* immediately */); + mManager.onMediaDataLoaded("NEW_KEY", KEY, mMediaData, true /* immediately */, + false /* isSsReactivated */); // THEN the listener gets a load event with the correct keys ArgumentCaptor captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded( - eq("NEW_KEY"), any(), captor.capture(), anyBoolean()); + eq("NEW_KEY"), any(), captor.capture(), anyBoolean(), anyBoolean()); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt index 17f2a07eb249b..d8791867cb45c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt @@ -120,7 +120,8 @@ class MediaDataFilterTest : SysuiTestCase() { mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) // THEN we should tell the listener - verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataMain), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataMain), eq(true), + eq(false)) } @Test @@ -129,7 +130,7 @@ class MediaDataFilterTest : SysuiTestCase() { mediaDataFilter.onMediaDataLoaded(KEY, null, dataGuest) // THEN we should NOT tell the listener - verify(listener, never()).onMediaDataLoaded(any(), any(), any(), anyBoolean()) + verify(listener, never()).onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyBoolean()) } @Test @@ -175,10 +176,12 @@ class MediaDataFilterTest : SysuiTestCase() { setUser(USER_GUEST) // THEN we should add back the guest user media - verify(listener).onMediaDataLoaded(eq(KEY_ALT), eq(null), eq(dataGuest), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY_ALT), eq(null), eq(dataGuest), eq(true), + eq(false)) // but not the main user's - verify(listener, never()).onMediaDataLoaded(eq(KEY), any(), eq(dataMain), anyBoolean()) + verify(listener, never()).onMediaDataLoaded(eq(KEY), any(), eq(dataMain), anyBoolean(), + anyBoolean()) } @Test @@ -245,7 +248,7 @@ class MediaDataFilterTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - verify(listener, never()).onMediaDataLoaded(any(), any(), any(), anyBoolean()) + verify(listener, never()).onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyBoolean()) verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } @@ -282,12 +285,15 @@ class MediaDataFilterTest : SysuiTestCase() { // WHEN we have media that was recently played, but not currently active val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) - verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), + eq(false)) // AND we get a smartspace signal mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - // THEN we should tell listeners to treat the media as active instead + // THEN we should tell listeners to treat the media as not active instead + verify(listener, never()).onMediaDataLoaded(eq(KEY), eq(KEY), any(), anyBoolean(), + anyBoolean()) verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } @@ -299,14 +305,16 @@ class MediaDataFilterTest : SysuiTestCase() { // WHEN we have media that was recently played, but not currently active val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) - verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), + eq(false)) // AND we get a smartspace signal mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) // THEN we should tell listeners to treat the media as active instead val dataCurrentAndActive = dataCurrent.copy(active = true) - verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive), eq(true), + eq(true)) assertThat(mediaDataFilter.hasActiveMedia()).isTrue() // Smartspace update shouldn't be propagated for the empty rec list. verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) @@ -317,14 +325,16 @@ class MediaDataFilterTest : SysuiTestCase() { // WHEN we have media that was recently played, but not currently active val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) - verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), + eq(false)) // AND we get a smartspace signal mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) // THEN we should tell listeners to treat the media as active instead val dataCurrentAndActive = dataCurrent.copy(active = true) - verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive), eq(true), + eq(true)) assertThat(mediaDataFilter.hasActiveMedia()).isTrue() // Smartspace update should also be propagated but not prioritized. verify(listener) @@ -344,11 +354,17 @@ class MediaDataFilterTest : SysuiTestCase() { fun testOnSmartspaceMediaDataRemoved_usedMediaAndSmartspace_clearsBoth() { val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), + eq(false)) + mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) + val dataCurrentAndActive = dataCurrent.copy(active = true) + verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive), eq(true), + eq(true)) + mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) - verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrent), eq(true)) verify(listener).onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt index 3128db423a24d..5b4e12463370d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -185,7 +185,8 @@ class MediaDataManagerTest : SysuiTestCase() { fun testOnMetaDataLoaded_callsListener() { mediaDataManager.onNotificationAdded(KEY, mediaNotification) mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java)) - verify(listener).onMediaDataLoaded(eq(KEY), eq(null), anyObject(), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), anyObject(), eq(true), + eq(false)) } @Test @@ -196,7 +197,8 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.onNotificationAdded(KEY, mediaNotification) assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) - verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), + eq(false)) assertThat(mediaDataCaptor.value!!.active).isTrue() } @@ -215,7 +217,8 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.onNotificationAdded(KEY, mediaNotification) assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) - verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), + eq(false)) val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {})) @@ -223,7 +226,8 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.onNotificationRemoved(KEY) // THEN the media data indicates that it is for resumption verify(listener) - .onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor), eq(true)) + .onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor), eq(true), + eq(false)) assertThat(mediaDataCaptor.value.resumption).isTrue() } @@ -236,7 +240,8 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(2) assertThat(foregroundExecutor.runAllReady()).isEqualTo(2) verify(listener) - .onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true)) + .onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), + eq(false)) val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() val resumableData = data.copy(resumeAction = Runnable {}) @@ -247,7 +252,8 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.onNotificationRemoved(KEY) // THEN the data is for resumption and the key is migrated to the package name verify(listener) - .onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor), eq(true)) + .onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor), eq(true), + eq(false)) assertThat(mediaDataCaptor.value.resumption).isTrue() verify(listener, never()).onMediaDataRemoved(eq(KEY)) // WHEN the second is removed @@ -255,7 +261,8 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN the data is for resumption and the second key is removed verify(listener) .onMediaDataLoaded( - eq(PACKAGE_NAME), eq(PACKAGE_NAME), capture(mediaDataCaptor), eq(true)) + eq(PACKAGE_NAME), eq(PACKAGE_NAME), capture(mediaDataCaptor), eq(true), + eq(false)) assertThat(mediaDataCaptor.value.resumption).isTrue() verify(listener).onMediaDataRemoved(eq(KEY_2)) } @@ -269,7 +276,8 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.onNotificationAdded(KEY, mediaNotification) assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) - verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), + eq(false)) val data = mediaDataCaptor.value val dataRemoteWithResume = data.copy(resumeAction = Runnable {}, isLocalSession = false) mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume) @@ -295,7 +303,8 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) // THEN the media data indicates that it is for resumption verify(listener) - .onMediaDataLoaded(eq(PACKAGE_NAME), eq(null), capture(mediaDataCaptor), eq(true)) + .onMediaDataLoaded(eq(PACKAGE_NAME), eq(null), capture(mediaDataCaptor), eq(true), + eq(false)) val data = mediaDataCaptor.value assertThat(data.resumption).isTrue() assertThat(data.song).isEqualTo(SESSION_TITLE) @@ -335,7 +344,8 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener) - .onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true)) + .onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), + eq(false)) } @Test @@ -414,7 +424,8 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.onNotificationAdded(KEY, mediaNotification) assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) - verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), + eq(false)) assertThat(mediaDataCaptor.value!!.lastActive).isAtLeast(currentTime) } @@ -431,7 +442,8 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.setTimedOut(KEY, true, true) // THEN the last active time is not changed - verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), capture(mediaDataCaptor), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), capture(mediaDataCaptor), eq(true), + eq(false)) assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTime) } @@ -442,7 +454,8 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.onNotificationAdded(KEY, mediaNotification) assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) - verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), + eq(false)) val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {})) @@ -454,7 +467,8 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN the last active time is not changed verify(listener) - .onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor), eq(true)) + .onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor), eq(true), + eq(false)) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTime) } @@ -480,7 +494,8 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) // THEN only the first MAX_COMPACT_ACTIONS are actually set - verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true)) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), + eq(false)) assertThat(mediaDataCaptor.value.actionsToShowInCompact.size).isEqualTo( MediaDataManager.MAX_COMPACT_ACTIONS) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt index c6d7e92175eb1..b9caab277c4cd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt @@ -185,7 +185,8 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { filter.onMediaDataLoaded(KEY, null, mediaData1) bgExecutor.runAllReady() fgExecutor.runAllReady() - verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), + eq(false)) } @Test @@ -207,7 +208,8 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered - verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), + eq(false)) } @Test @@ -236,7 +238,8 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered - verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), + eq(false)) } @Test @@ -251,14 +254,15 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered - verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), + eq(false)) // WHEN a loaded event is received that matches the local session filter.onMediaDataLoaded(KEY, null, mediaData2) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is filtered verify(mediaListener, never()).onMediaDataLoaded( - eq(KEY), eq(null), eq(mediaData2), anyBoolean()) + eq(KEY), eq(null), eq(mediaData2), anyBoolean(), anyBoolean()) } @Test @@ -274,7 +278,8 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered because there isn't a notification for the remote // session. - verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), + eq(false)) } @Test @@ -291,14 +296,15 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered - verify(mediaListener).onMediaDataLoaded(eq(key1), eq(null), eq(mediaData1), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(key1), eq(null), eq(mediaData1), eq(true), + eq(false)) // WHEN a loaded event is received that matches the local session filter.onMediaDataLoaded(key2, null, mediaData2) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is filtered verify(mediaListener, never()) - .onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), anyBoolean()) + .onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), anyBoolean(), anyBoolean()) // AND there should be a removed event for key2 verify(mediaListener).onMediaDataRemoved(eq(key2)) } @@ -317,13 +323,15 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered - verify(mediaListener).onMediaDataLoaded(eq(key1), eq(null), eq(mediaData1), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(key1), eq(null), eq(mediaData1), eq(true), + eq(false)) // WHEN a loaded event is received that matches the remote session filter.onMediaDataLoaded(key2, null, mediaData2) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered - verify(mediaListener).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), eq(true), + eq(false)) } @Test @@ -339,13 +347,15 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered - verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), + eq(false)) // WHEN a loaded event is received that matches the local session filter.onMediaDataLoaded(KEY, null, mediaData2) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered - verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData2), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData2), eq(true), + eq(false)) } @Test @@ -363,7 +373,8 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered - verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), + eq(false)) } @Test @@ -385,7 +396,8 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the key migration event is fired - verify(mediaListener).onMediaDataLoaded(eq(key2), eq(key1), eq(mediaData2), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(key2), eq(key1), eq(mediaData2), eq(true), + eq(false)) } @Test @@ -415,12 +427,13 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the key migration event is filtered verify(mediaListener, never()) - .onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), anyBoolean()) + .onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), anyBoolean(), anyBoolean()) // WHEN a loaded event is received that matches the remote session filter.onMediaDataLoaded(key2, null, mediaData1) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the key migration event is fired - verify(mediaListener).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData1), eq(true)) + verify(mediaListener).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData1), eq(true), + eq(false)) } }