Merge "Add logging for media recommendation events" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f30664e60b
@@ -508,6 +508,11 @@ class MediaCarouselController @Inject constructor(
|
|||||||
dismissMediaData: Boolean = true,
|
dismissMediaData: Boolean = true,
|
||||||
dismissRecommendation: Boolean = true
|
dismissRecommendation: Boolean = true
|
||||||
) {
|
) {
|
||||||
|
if (key == MediaPlayerData.smartspaceMediaKey()) {
|
||||||
|
MediaPlayerData.smartspaceMediaData?.let {
|
||||||
|
logger.logRecommendationRemoved(it.packageName, it.instanceId)
|
||||||
|
}
|
||||||
|
}
|
||||||
val removed = MediaPlayerData.removeMediaPlayer(key)
|
val removed = MediaPlayerData.removeMediaPlayer(key)
|
||||||
removed?.apply {
|
removed?.apply {
|
||||||
mediaCarouselScrollHandler.onPrePlayerRemoved(removed)
|
mediaCarouselScrollHandler.onPrePlayerRemoved(removed)
|
||||||
|
|||||||
@@ -331,6 +331,7 @@ public class MediaControlPanel {
|
|||||||
});
|
});
|
||||||
mRecommendationViewHolder.getSettings().setOnClickListener(v -> {
|
mRecommendationViewHolder.getSettings().setOnClickListener(v -> {
|
||||||
if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
|
if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
|
||||||
|
mLogger.logLongPressSettings(mUid, mPackageName, mInstanceId);
|
||||||
mActivityStarter.startActivity(SETTINGS_INTENT, true /* dismissShade */);
|
mActivityStarter.startActivity(SETTINGS_INTENT, true /* dismissShade */);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -940,6 +941,8 @@ public class MediaControlPanel {
|
|||||||
|
|
||||||
mSmartspaceId = SmallHash.hash(data.getTargetId());
|
mSmartspaceId = SmallHash.hash(data.getTargetId());
|
||||||
mBackgroundColor = data.getBackgroundColor();
|
mBackgroundColor = data.getBackgroundColor();
|
||||||
|
mPackageName = data.getPackageName();
|
||||||
|
mInstanceId = data.getInstanceId();
|
||||||
TransitionLayout recommendationCard = mRecommendationViewHolder.getRecommendations();
|
TransitionLayout recommendationCard = mRecommendationViewHolder.getRecommendations();
|
||||||
recommendationCard.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor));
|
recommendationCard.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor));
|
||||||
|
|
||||||
@@ -1068,6 +1071,7 @@ public class MediaControlPanel {
|
|||||||
mRecommendationViewHolder.getDismiss().setOnClickListener(v -> {
|
mRecommendationViewHolder.getDismiss().setOnClickListener(v -> {
|
||||||
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return;
|
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return;
|
||||||
|
|
||||||
|
mLogger.logLongPressDismiss(mUid, mPackageName, mInstanceId);
|
||||||
logSmartspaceCardReported(
|
logSmartspaceCardReported(
|
||||||
761 // SMARTSPACE_CARD_DISMISS
|
761 // SMARTSPACE_CARD_DISMISS
|
||||||
);
|
);
|
||||||
@@ -1204,6 +1208,11 @@ public class MediaControlPanel {
|
|||||||
view.setOnClickListener(v -> {
|
view.setOnClickListener(v -> {
|
||||||
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return;
|
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return;
|
||||||
|
|
||||||
|
if (interactedSubcardRank == -1) {
|
||||||
|
mLogger.logRecommendationCardTap(mPackageName, mInstanceId);
|
||||||
|
} else {
|
||||||
|
mLogger.logRecommendationItemTap(mPackageName, mInstanceId, interactedSubcardRank);
|
||||||
|
}
|
||||||
logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT,
|
logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT,
|
||||||
interactedSubcardRank,
|
interactedSubcardRank,
|
||||||
getSmartspaceSubCardCardinality());
|
getSmartspaceSubCardCardinality());
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ class MediaDataFilter @Inject constructor(
|
|||||||
private val broadcastSender: BroadcastSender,
|
private val broadcastSender: BroadcastSender,
|
||||||
private val lockscreenUserManager: NotificationLockscreenUserManager,
|
private val lockscreenUserManager: NotificationLockscreenUserManager,
|
||||||
@Main private val executor: Executor,
|
@Main private val executor: Executor,
|
||||||
private val systemClock: SystemClock
|
private val systemClock: SystemClock,
|
||||||
|
private val logger: MediaUiEventLogger
|
||||||
) : MediaDataManager.Listener {
|
) : MediaDataManager.Listener {
|
||||||
private val userTracker: CurrentUserTracker
|
private val userTracker: CurrentUserTracker
|
||||||
private val _listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf()
|
private val _listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf()
|
||||||
@@ -151,6 +152,8 @@ class MediaDataFilter @Inject constructor(
|
|||||||
Log.d(TAG, "reactivating $lastActiveKey instead of smartspace")
|
Log.d(TAG, "reactivating $lastActiveKey instead of smartspace")
|
||||||
reactivatedKey = lastActiveKey
|
reactivatedKey = lastActiveKey
|
||||||
val mediaData = sorted.get(lastActiveKey)!!.copy(active = true)
|
val mediaData = sorted.get(lastActiveKey)!!.copy(active = true)
|
||||||
|
logger.logRecommendationActivated(mediaData.appUid, mediaData.packageName,
|
||||||
|
mediaData.instanceId)
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData,
|
it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData,
|
||||||
receivedSmartspaceCardLatency =
|
receivedSmartspaceCardLatency =
|
||||||
@@ -167,6 +170,8 @@ class MediaDataFilter @Inject constructor(
|
|||||||
Log.d(TAG, "Invalid recommendation data. Skip showing the rec card")
|
Log.d(TAG, "Invalid recommendation data. Skip showing the rec card")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
logger.logRecommendationAdded(smartspaceMediaData.packageName,
|
||||||
|
smartspaceMediaData.instanceId)
|
||||||
listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable) }
|
listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +202,9 @@ class MediaDataFilter @Inject constructor(
|
|||||||
|
|
||||||
if (smartspaceMediaData.isActive) {
|
if (smartspaceMediaData.isActive) {
|
||||||
smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
|
smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
|
||||||
targetId = smartspaceMediaData.targetId, isValid = smartspaceMediaData.isValid)
|
targetId = smartspaceMediaData.targetId,
|
||||||
|
isValid = smartspaceMediaData.isValid,
|
||||||
|
instanceId = smartspaceMediaData.instanceId)
|
||||||
}
|
}
|
||||||
listeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) }
|
listeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) }
|
||||||
}
|
}
|
||||||
@@ -252,9 +259,12 @@ class MediaDataFilter @Inject constructor(
|
|||||||
broadcastSender.sendBroadcast(dismissIntent)
|
broadcastSender.sendBroadcast(dismissIntent)
|
||||||
}
|
}
|
||||||
smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
|
smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
|
||||||
targetId = smartspaceMediaData.targetId, isValid = smartspaceMediaData.isValid)
|
targetId = smartspaceMediaData.targetId,
|
||||||
|
isValid = smartspaceMediaData.isValid,
|
||||||
|
instanceId = smartspaceMediaData.instanceId)
|
||||||
|
mediaDataManager.dismissSmartspaceRecommendation(smartspaceMediaData.targetId,
|
||||||
|
delay = 0L)
|
||||||
}
|
}
|
||||||
mediaDataManager.dismissSmartspaceRecommendation(smartspaceMediaData.targetId, delay = 0L)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -103,8 +103,17 @@ private val LOADING = MediaData(
|
|||||||
appUid = Process.INVALID_UID)
|
appUid = Process.INVALID_UID)
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, false,
|
internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData(
|
||||||
"INVALID", null, emptyList(), null, 0, 0)
|
targetId = "INVALID",
|
||||||
|
isActive = false,
|
||||||
|
isValid = false,
|
||||||
|
packageName = "INVALID",
|
||||||
|
cardAction = null,
|
||||||
|
recommendations = emptyList(),
|
||||||
|
dismissIntent = null,
|
||||||
|
backgroundColor = 0,
|
||||||
|
headphoneConnectionTimeMillis = 0,
|
||||||
|
instanceId = InstanceId.fakeInstanceId(-1))
|
||||||
|
|
||||||
fun isMediaNotification(sbn: StatusBarNotification): Boolean {
|
fun isMediaNotification(sbn: StatusBarNotification): Boolean {
|
||||||
return sbn.notification.isMediaNotification()
|
return sbn.notification.isMediaNotification()
|
||||||
@@ -532,14 +541,16 @@ class MediaDataManager(
|
|||||||
* connection session.
|
* connection session.
|
||||||
*/
|
*/
|
||||||
fun dismissSmartspaceRecommendation(key: String, delay: Long) {
|
fun dismissSmartspaceRecommendation(key: String, delay: Long) {
|
||||||
if (smartspaceMediaData.targetId != key) {
|
if (smartspaceMediaData.targetId != key || !smartspaceMediaData.isValid) {
|
||||||
|
// If this doesn't match, or we've already invalidated the data, no action needed
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG) Log.d(TAG, "Dismissing Smartspace media target")
|
if (DEBUG) Log.d(TAG, "Dismissing Smartspace media target")
|
||||||
if (smartspaceMediaData.isActive) {
|
if (smartspaceMediaData.isActive) {
|
||||||
smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
|
smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
|
||||||
targetId = smartspaceMediaData.targetId)
|
targetId = smartspaceMediaData.targetId,
|
||||||
|
instanceId = smartspaceMediaData.instanceId)
|
||||||
}
|
}
|
||||||
foregroundExecutor.executeDelayed(
|
foregroundExecutor.executeDelayed(
|
||||||
{ notifySmartspaceMediaDataRemoved(
|
{ notifySmartspaceMediaDataRemoved(
|
||||||
@@ -1035,7 +1046,8 @@ class MediaDataManager(
|
|||||||
Log.d(TAG, "Set Smartspace media to be inactive for the data update")
|
Log.d(TAG, "Set Smartspace media to be inactive for the data update")
|
||||||
}
|
}
|
||||||
smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
|
smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
|
||||||
targetId = smartspaceMediaData.targetId)
|
targetId = smartspaceMediaData.targetId,
|
||||||
|
instanceId = smartspaceMediaData.instanceId)
|
||||||
notifySmartspaceMediaDataRemoved(smartspaceMediaData.targetId, immediately = false)
|
notifySmartspaceMediaDataRemoved(smartspaceMediaData.targetId, immediately = false)
|
||||||
}
|
}
|
||||||
1 -> {
|
1 -> {
|
||||||
@@ -1214,15 +1226,24 @@ class MediaDataManager(
|
|||||||
.getParcelable(EXTRAS_SMARTSPACE_DISMISS_INTENT_KEY) as Intent?
|
.getParcelable(EXTRAS_SMARTSPACE_DISMISS_INTENT_KEY) as Intent?
|
||||||
}
|
}
|
||||||
packageName(target)?.let {
|
packageName(target)?.let {
|
||||||
return SmartspaceMediaData(target.smartspaceTargetId, isActive, true, it,
|
return SmartspaceMediaData(
|
||||||
target.baseAction, target.iconGrid,
|
targetId = target.smartspaceTargetId,
|
||||||
dismissIntent, 0, target.creationTimeMillis)
|
isActive = isActive,
|
||||||
|
isValid = true,
|
||||||
|
packageName = it,
|
||||||
|
cardAction = target.baseAction,
|
||||||
|
recommendations = target.iconGrid,
|
||||||
|
dismissIntent = dismissIntent,
|
||||||
|
backgroundColor = 0,
|
||||||
|
headphoneConnectionTimeMillis = target.creationTimeMillis,
|
||||||
|
instanceId = logger.getNewInstanceId())
|
||||||
}
|
}
|
||||||
return EMPTY_SMARTSPACE_MEDIA_DATA
|
return EMPTY_SMARTSPACE_MEDIA_DATA
|
||||||
.copy(targetId = target.smartspaceTargetId,
|
.copy(targetId = target.smartspaceTargetId,
|
||||||
isActive = isActive,
|
isActive = isActive,
|
||||||
dismissIntent = dismissIntent,
|
dismissIntent = dismissIntent,
|
||||||
headphoneConnectionTimeMillis = target.creationTimeMillis)
|
headphoneConnectionTimeMillis = target.creationTimeMillis,
|
||||||
|
instanceId = logger.getNewInstanceId())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun packageName(target: SmartspaceTarget): String? {
|
private fun packageName(target: SmartspaceTarget): String? {
|
||||||
|
|||||||
@@ -151,6 +151,31 @@ class MediaUiEventLogger @Inject constructor(private val logger: UiEventLogger)
|
|||||||
}
|
}
|
||||||
logger.log(event)
|
logger.log(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun logRecommendationAdded(packageName: String, instanceId: InstanceId) {
|
||||||
|
logger.logWithInstanceId(MediaUiEvent.MEDIA_RECOMMENDATION_ADDED, 0, packageName,
|
||||||
|
instanceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logRecommendationRemoved(packageName: String, instanceId: InstanceId) {
|
||||||
|
logger.logWithInstanceId(MediaUiEvent.MEDIA_RECOMMENDATION_REMOVED, 0, packageName,
|
||||||
|
instanceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logRecommendationActivated(uid: Int, packageName: String, instanceId: InstanceId) {
|
||||||
|
logger.logWithInstanceId(MediaUiEvent.MEDIA_RECOMMENDATION_ACTIVATED, uid, packageName,
|
||||||
|
instanceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logRecommendationItemTap(packageName: String, instanceId: InstanceId, position: Int) {
|
||||||
|
logger.logWithInstanceIdAndPosition(MediaUiEvent.MEDIA_RECOMMENDATION_ITEM_TAP, 0,
|
||||||
|
packageName, instanceId, position)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logRecommendationCardTap(packageName: String, instanceId: InstanceId) {
|
||||||
|
logger.logWithInstanceId(MediaUiEvent.MEDIA_RECOMMENDATION_CARD_TAP, 0, packageName,
|
||||||
|
instanceId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class MediaUiEvent(val metricId: Int) : UiEventLogger.UiEventEnum {
|
enum class MediaUiEvent(val metricId: Int) : UiEventLogger.UiEventEnum {
|
||||||
@@ -233,7 +258,22 @@ enum class MediaUiEvent(val metricId: Int) : UiEventLogger.UiEventEnum {
|
|||||||
MEDIA_CAROUSEL_LOCATION_LOCKSCREEN(1039),
|
MEDIA_CAROUSEL_LOCATION_LOCKSCREEN(1039),
|
||||||
|
|
||||||
@UiEvent(doc = "The media carousel moved to the dream state")
|
@UiEvent(doc = "The media carousel moved to the dream state")
|
||||||
MEDIA_CAROUSEL_LOCATION_DREAM(1040);
|
MEDIA_CAROUSEL_LOCATION_DREAM(1040),
|
||||||
|
|
||||||
|
@UiEvent(doc = "A media recommendation card was added to the media carousel")
|
||||||
|
MEDIA_RECOMMENDATION_ADDED(1041),
|
||||||
|
|
||||||
|
@UiEvent(doc = "A media recommendation card was removed from the media carousel")
|
||||||
|
MEDIA_RECOMMENDATION_REMOVED(1042),
|
||||||
|
|
||||||
|
@UiEvent(doc = "An existing media control was made active as a recommendation")
|
||||||
|
MEDIA_RECOMMENDATION_ACTIVATED(1043),
|
||||||
|
|
||||||
|
@UiEvent(doc = "User tapped on an item in a media recommendation card")
|
||||||
|
MEDIA_RECOMMENDATION_ITEM_TAP(1044),
|
||||||
|
|
||||||
|
@UiEvent(doc = "User tapped on a media recommendation card")
|
||||||
|
MEDIA_RECOMMENDATION_CARD_TAP(1045);
|
||||||
|
|
||||||
override fun getId() = metricId
|
override fun getId() = metricId
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,7 @@ package com.android.systemui.media
|
|||||||
|
|
||||||
import android.app.smartspace.SmartspaceAction
|
import android.app.smartspace.SmartspaceAction
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import com.android.internal.logging.InstanceId
|
||||||
|
|
||||||
/** State of a Smartspace media recommendations view. */
|
/** State of a Smartspace media recommendations view. */
|
||||||
data class SmartspaceMediaData(
|
data class SmartspaceMediaData(
|
||||||
@@ -56,5 +57,9 @@ data class SmartspaceMediaData(
|
|||||||
/**
|
/**
|
||||||
* The timestamp in milliseconds that headphone is connected.
|
* The timestamp in milliseconds that headphone is connected.
|
||||||
*/
|
*/
|
||||||
val headphoneConnectionTimeMillis: Long
|
val headphoneConnectionTimeMillis: Long,
|
||||||
|
/**
|
||||||
|
* Instance ID for [MediaUiEventLogger]
|
||||||
|
*/
|
||||||
|
val instanceId: InstanceId
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.android.systemui.media
|
|||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.testing.TestableLooper
|
import android.testing.TestableLooper
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.internal.logging.InstanceId
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.classifier.FalsingCollector
|
import com.android.systemui.classifier.FalsingCollector
|
||||||
import com.android.systemui.dagger.qualifiers.Main
|
import com.android.systemui.dagger.qualifiers.Main
|
||||||
@@ -28,6 +29,7 @@ import com.android.systemui.plugins.FalsingManager
|
|||||||
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider
|
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||||
|
import com.android.systemui.util.mockito.eq
|
||||||
import com.android.systemui.util.time.FakeSystemClock
|
import com.android.systemui.util.time.FakeSystemClock
|
||||||
import junit.framework.Assert.assertEquals
|
import junit.framework.Assert.assertEquals
|
||||||
import junit.framework.Assert.assertTrue
|
import junit.framework.Assert.assertTrue
|
||||||
@@ -225,4 +227,19 @@ class MediaCarouselControllerTest : SysuiTestCase() {
|
|||||||
animate = false)
|
animate = false)
|
||||||
verify(logger).logCarouselPosition(MediaHierarchyManager.LOCATION_DREAM_OVERLAY)
|
verify(logger).logCarouselPosition(MediaHierarchyManager.LOCATION_DREAM_OVERLAY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testRecommendationRemoved_logged() {
|
||||||
|
val packageName = "smartspace package"
|
||||||
|
val instanceId = InstanceId.fakeInstanceId(123)
|
||||||
|
|
||||||
|
val smartspaceData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
|
||||||
|
packageName = packageName,
|
||||||
|
instanceId = instanceId
|
||||||
|
)
|
||||||
|
MediaPlayerData.addMediaRecommendation(SMARTSPACE_KEY, smartspaceData, panel, true, clock)
|
||||||
|
mediaCarouselController.removePlayer(SMARTSPACE_KEY)
|
||||||
|
|
||||||
|
verify(logger).logRecommendationRemoved(eq(packageName), eq(instanceId!!))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -17,16 +17,22 @@
|
|||||||
package com.android.systemui.media
|
package com.android.systemui.media
|
||||||
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
|
import android.app.smartspace.SmartspaceAction
|
||||||
|
import android.content.Context
|
||||||
import org.mockito.Mockito.`when` as whenever
|
import org.mockito.Mockito.`when` as whenever
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.Animatable2
|
import android.graphics.drawable.Animatable2
|
||||||
import android.graphics.drawable.AnimatedVectorDrawable
|
import android.graphics.drawable.AnimatedVectorDrawable
|
||||||
import android.graphics.drawable.GradientDrawable
|
import android.graphics.drawable.GradientDrawable
|
||||||
|
import android.graphics.drawable.Icon
|
||||||
import android.graphics.drawable.RippleDrawable
|
import android.graphics.drawable.RippleDrawable
|
||||||
import android.media.MediaMetadata
|
import android.media.MediaMetadata
|
||||||
import android.media.session.MediaSession
|
import android.media.session.MediaSession
|
||||||
import android.media.session.PlaybackState
|
import android.media.session.PlaybackState
|
||||||
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
|
import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
@@ -67,6 +73,7 @@ import org.mockito.ArgumentMatchers.anyInt
|
|||||||
import org.mockito.ArgumentMatchers.anyLong
|
import org.mockito.ArgumentMatchers.anyLong
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.any
|
import org.mockito.Mockito.any
|
||||||
|
import org.mockito.Mockito.anyString
|
||||||
import org.mockito.Mockito.mock
|
import org.mockito.Mockito.mock
|
||||||
import org.mockito.Mockito.never
|
import org.mockito.Mockito.never
|
||||||
import org.mockito.Mockito.reset
|
import org.mockito.Mockito.reset
|
||||||
@@ -107,6 +114,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
@Mock private lateinit var collapsedSet: ConstraintSet
|
@Mock private lateinit var collapsedSet: ConstraintSet
|
||||||
@Mock private lateinit var mediaOutputDialogFactory: MediaOutputDialogFactory
|
@Mock private lateinit var mediaOutputDialogFactory: MediaOutputDialogFactory
|
||||||
@Mock private lateinit var mediaCarouselController: MediaCarouselController
|
@Mock private lateinit var mediaCarouselController: MediaCarouselController
|
||||||
|
@Mock private lateinit var mediaCarouselScrollHandler: MediaCarouselScrollHandler
|
||||||
@Mock private lateinit var falsingManager: FalsingManager
|
@Mock private lateinit var falsingManager: FalsingManager
|
||||||
@Mock private lateinit var transitionParent: ViewGroup
|
@Mock private lateinit var transitionParent: ViewGroup
|
||||||
private lateinit var appIcon: ImageView
|
private lateinit var appIcon: ImageView
|
||||||
@@ -145,6 +153,14 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
private val clock = FakeSystemClock()
|
private val clock = FakeSystemClock()
|
||||||
@Mock private lateinit var logger: MediaUiEventLogger
|
@Mock private lateinit var logger: MediaUiEventLogger
|
||||||
@Mock private lateinit var instanceId: InstanceId
|
@Mock private lateinit var instanceId: InstanceId
|
||||||
|
@Mock private lateinit var packageManager: PackageManager
|
||||||
|
@Mock private lateinit var applicationInfo: ApplicationInfo
|
||||||
|
|
||||||
|
@Mock private lateinit var recommendationViewHolder: RecommendationViewHolder
|
||||||
|
@Mock private lateinit var smartspaceAction: SmartspaceAction
|
||||||
|
private lateinit var smartspaceData: SmartspaceMediaData
|
||||||
|
@Mock private lateinit var coverContainer: ViewGroup
|
||||||
|
private lateinit var coverItem: ImageView
|
||||||
|
|
||||||
@JvmField @Rule val mockito = MockitoJUnit.rule()
|
@JvmField @Rule val mockito = MockitoJUnit.rule()
|
||||||
|
|
||||||
@@ -155,6 +171,16 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
whenever(mediaViewController.expandedLayout).thenReturn(expandedSet)
|
whenever(mediaViewController.expandedLayout).thenReturn(expandedSet)
|
||||||
whenever(mediaViewController.collapsedLayout).thenReturn(collapsedSet)
|
whenever(mediaViewController.collapsedLayout).thenReturn(collapsedSet)
|
||||||
|
|
||||||
|
// Set up package manager mocks
|
||||||
|
val icon = context.getDrawable(R.drawable.ic_android)
|
||||||
|
whenever(packageManager.getApplicationIcon(anyString())).thenReturn(icon)
|
||||||
|
whenever(packageManager.getApplicationIcon(any(ApplicationInfo::class.java)))
|
||||||
|
.thenReturn(icon)
|
||||||
|
whenever(packageManager.getApplicationInfo(eq(PACKAGE), anyInt()))
|
||||||
|
.thenReturn(applicationInfo)
|
||||||
|
whenever(packageManager.getApplicationLabel(any())).thenReturn(PACKAGE)
|
||||||
|
context.setMockPackageManager(packageManager)
|
||||||
|
|
||||||
player = MediaControlPanel(
|
player = MediaControlPanel(
|
||||||
context,
|
context,
|
||||||
bgExecutor,
|
bgExecutor,
|
||||||
@@ -170,7 +196,60 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
clock,
|
clock,
|
||||||
logger
|
logger
|
||||||
)
|
)
|
||||||
|
|
||||||
|
initMediaViewHolderMocks()
|
||||||
|
|
||||||
|
// Create media session
|
||||||
|
val metadataBuilder = MediaMetadata.Builder().apply {
|
||||||
|
putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
|
||||||
|
putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
|
||||||
|
}
|
||||||
|
val playbackBuilder = PlaybackState.Builder().apply {
|
||||||
|
setState(PlaybackState.STATE_PAUSED, 6000L, 1f)
|
||||||
|
setActions(PlaybackState.ACTION_PLAY)
|
||||||
|
}
|
||||||
|
session = MediaSession(context, SESSION_KEY).apply {
|
||||||
|
setMetadata(metadataBuilder.build())
|
||||||
|
setPlaybackState(playbackBuilder.build())
|
||||||
|
}
|
||||||
|
session.setActive(true)
|
||||||
|
|
||||||
|
mediaData = MediaTestUtils.emptyMediaData.copy(
|
||||||
|
backgroundColor = BG_COLOR,
|
||||||
|
artist = ARTIST,
|
||||||
|
song = TITLE,
|
||||||
|
packageName = PACKAGE,
|
||||||
|
token = session.sessionToken,
|
||||||
|
device = device,
|
||||||
|
instanceId = instanceId)
|
||||||
|
|
||||||
|
// Set up recommendation view
|
||||||
|
initRecommendationViewHolderMocks()
|
||||||
|
|
||||||
|
// Set valid recommendation data
|
||||||
|
val extras = Bundle()
|
||||||
|
val intent = Intent().apply {
|
||||||
|
putExtras(extras)
|
||||||
|
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
}
|
||||||
|
whenever(smartspaceAction.intent).thenReturn(intent)
|
||||||
|
whenever(smartspaceAction.extras).thenReturn(extras)
|
||||||
|
smartspaceData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
|
||||||
|
packageName = PACKAGE,
|
||||||
|
instanceId = instanceId,
|
||||||
|
recommendations = listOf(smartspaceAction),
|
||||||
|
cardAction = smartspaceAction
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize elements in media view holder
|
||||||
|
*/
|
||||||
|
private fun initMediaViewHolderMocks() {
|
||||||
whenever(seekBarViewModel.progress).thenReturn(seekBarData)
|
whenever(seekBarViewModel.progress).thenReturn(seekBarData)
|
||||||
|
whenever(mediaCarouselController.mediaCarouselScrollHandler)
|
||||||
|
.thenReturn(mediaCarouselScrollHandler)
|
||||||
|
whenever(mediaCarouselScrollHandler.qsExpanded).thenReturn(false)
|
||||||
|
|
||||||
// Set up mock views for the players
|
// Set up mock views for the players
|
||||||
appIcon = ImageView(context)
|
appIcon = ImageView(context)
|
||||||
@@ -218,37 +297,6 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
action4.id)
|
action4.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
initMediaViewHolderMocks()
|
|
||||||
|
|
||||||
// Create media session
|
|
||||||
val metadataBuilder = MediaMetadata.Builder().apply {
|
|
||||||
putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
|
|
||||||
putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
|
|
||||||
}
|
|
||||||
val playbackBuilder = PlaybackState.Builder().apply {
|
|
||||||
setState(PlaybackState.STATE_PAUSED, 6000L, 1f)
|
|
||||||
setActions(PlaybackState.ACTION_PLAY)
|
|
||||||
}
|
|
||||||
session = MediaSession(context, SESSION_KEY).apply {
|
|
||||||
setMetadata(metadataBuilder.build())
|
|
||||||
setPlaybackState(playbackBuilder.build())
|
|
||||||
}
|
|
||||||
session.setActive(true)
|
|
||||||
|
|
||||||
mediaData = MediaTestUtils.emptyMediaData.copy(
|
|
||||||
backgroundColor = BG_COLOR,
|
|
||||||
artist = ARTIST,
|
|
||||||
song = TITLE,
|
|
||||||
packageName = PACKAGE,
|
|
||||||
token = session.sessionToken,
|
|
||||||
device = device,
|
|
||||||
instanceId = instanceId)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize elements in media view holder
|
|
||||||
*/
|
|
||||||
private fun initMediaViewHolderMocks() {
|
|
||||||
whenever(viewHolder.player).thenReturn(view)
|
whenever(viewHolder.player).thenReturn(view)
|
||||||
whenever(viewHolder.appIcon).thenReturn(appIcon)
|
whenever(viewHolder.appIcon).thenReturn(appIcon)
|
||||||
whenever(viewHolder.albumView).thenReturn(albumView)
|
whenever(viewHolder.albumView).thenReturn(albumView)
|
||||||
@@ -297,6 +345,38 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
whenever(viewHolder.actionsTopBarrier).thenReturn(actionsTopBarrier)
|
whenever(viewHolder.actionsTopBarrier).thenReturn(actionsTopBarrier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize elements for the recommendation view holder
|
||||||
|
*/
|
||||||
|
private fun initRecommendationViewHolderMocks() {
|
||||||
|
whenever(recommendationViewHolder.recommendations).thenReturn(view)
|
||||||
|
whenever(recommendationViewHolder.cardIcon).thenReturn(appIcon)
|
||||||
|
whenever(recommendationViewHolder.cardText).thenReturn(titleText)
|
||||||
|
|
||||||
|
// Add a recommendation item
|
||||||
|
coverItem = ImageView(context).also { it.setId(R.id.media_cover1) }
|
||||||
|
whenever(coverContainer.id).thenReturn(R.id.media_cover1_container)
|
||||||
|
whenever(recommendationViewHolder.mediaCoverItems).thenReturn(listOf(coverItem))
|
||||||
|
whenever(recommendationViewHolder.mediaCoverContainers).thenReturn(listOf(coverContainer))
|
||||||
|
whenever(recommendationViewHolder.mediaCoverItemsResIds)
|
||||||
|
.thenReturn(listOf(R.id.media_cover1))
|
||||||
|
whenever(recommendationViewHolder.mediaCoverContainersResIds)
|
||||||
|
.thenReturn(listOf(R.id.media_cover1_container))
|
||||||
|
|
||||||
|
// Long press menu
|
||||||
|
whenever(recommendationViewHolder.settings).thenReturn(settings)
|
||||||
|
whenever(recommendationViewHolder.cancel).thenReturn(cancel)
|
||||||
|
whenever(recommendationViewHolder.dismiss).thenReturn(dismiss)
|
||||||
|
|
||||||
|
val actionIcon = Icon.createWithResource(context, R.drawable.ic_android)
|
||||||
|
whenever(smartspaceAction.icon).thenReturn(actionIcon)
|
||||||
|
|
||||||
|
// Needed for card and item action click
|
||||||
|
val mockContext = mock(Context::class.java)
|
||||||
|
whenever(view.context).thenReturn(mockContext)
|
||||||
|
whenever(coverContainer.context).thenReturn(mockContext)
|
||||||
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
fun tearDown() {
|
fun tearDown() {
|
||||||
session.release()
|
session.release()
|
||||||
@@ -923,6 +1003,67 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
|||||||
verify(logger).logSeek(anyInt(), eq(PACKAGE), eq(instanceId))
|
verify(logger).logSeek(anyInt(), eq(PACKAGE), eq(instanceId))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun recommendation_gutsClosed_longPressOpens() {
|
||||||
|
player.attachRecommendation(recommendationViewHolder)
|
||||||
|
player.bindRecommendation(smartspaceData)
|
||||||
|
whenever(mediaViewController.isGutsVisible).thenReturn(false)
|
||||||
|
|
||||||
|
val captor = ArgumentCaptor.forClass(View.OnLongClickListener::class.java)
|
||||||
|
verify(recommendationViewHolder.recommendations).setOnLongClickListener(captor.capture())
|
||||||
|
|
||||||
|
captor.value.onLongClick(recommendationViewHolder.recommendations)
|
||||||
|
verify(mediaViewController).openGuts()
|
||||||
|
verify(logger).logLongPressOpen(anyInt(), eq(PACKAGE), eq(instanceId))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun recommendation_settingsButtonClick_isLogged() {
|
||||||
|
player.attachRecommendation(recommendationViewHolder)
|
||||||
|
player.bindRecommendation(smartspaceData)
|
||||||
|
|
||||||
|
settings.callOnClick()
|
||||||
|
verify(logger).logLongPressSettings(anyInt(), eq(PACKAGE), eq(instanceId))
|
||||||
|
|
||||||
|
val captor = ArgumentCaptor.forClass(Intent::class.java)
|
||||||
|
verify(activityStarter).startActivity(captor.capture(), eq(true))
|
||||||
|
|
||||||
|
assertThat(captor.value.action).isEqualTo(ACTION_MEDIA_CONTROLS_SETTINGS)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun recommendation_dismissButton_isLogged() {
|
||||||
|
player.attachRecommendation(recommendationViewHolder)
|
||||||
|
player.bindRecommendation(smartspaceData)
|
||||||
|
|
||||||
|
dismiss.callOnClick()
|
||||||
|
verify(logger).logLongPressDismiss(anyInt(), eq(PACKAGE), eq(instanceId))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun recommendation_tapOnCard_isLogged() {
|
||||||
|
val captor = ArgumentCaptor.forClass(View.OnClickListener::class.java)
|
||||||
|
player.attachRecommendation(recommendationViewHolder)
|
||||||
|
player.bindRecommendation(smartspaceData)
|
||||||
|
|
||||||
|
verify(recommendationViewHolder.recommendations).setOnClickListener(captor.capture())
|
||||||
|
captor.value.onClick(recommendationViewHolder.recommendations)
|
||||||
|
|
||||||
|
verify(logger).logRecommendationCardTap(eq(PACKAGE), eq(instanceId))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun recommendation_tapOnItem_isLogged() {
|
||||||
|
val captor = ArgumentCaptor.forClass(View.OnClickListener::class.java)
|
||||||
|
player.attachRecommendation(recommendationViewHolder)
|
||||||
|
player.bindRecommendation(smartspaceData)
|
||||||
|
|
||||||
|
verify(coverContainer).setOnClickListener(captor.capture())
|
||||||
|
captor.value.onClick(recommendationViewHolder.recommendations)
|
||||||
|
|
||||||
|
verify(logger).logRecommendationItemTap(eq(PACKAGE), eq(instanceId), eq(0))
|
||||||
|
}
|
||||||
|
|
||||||
private fun getScrubbingChangeListener(): SeekBarViewModel.ScrubbingChangeListener =
|
private fun getScrubbingChangeListener(): SeekBarViewModel.ScrubbingChangeListener =
|
||||||
withArgCaptor { verify(seekBarViewModel).setScrubbingChangeListener(capture()) }
|
withArgCaptor { verify(seekBarViewModel).setScrubbingChangeListener(capture()) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import android.app.smartspace.SmartspaceAction
|
|||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.testing.TestableLooper
|
import android.testing.TestableLooper
|
||||||
|
import com.android.internal.logging.InstanceId
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||||
import com.android.systemui.broadcast.BroadcastSender
|
import com.android.systemui.broadcast.BroadcastSender
|
||||||
@@ -46,7 +47,11 @@ private const val KEY_ALT = "TEST_KEY_2"
|
|||||||
private const val USER_MAIN = 0
|
private const val USER_MAIN = 0
|
||||||
private const val USER_GUEST = 10
|
private const val USER_GUEST = 10
|
||||||
private const val PACKAGE = "PKG"
|
private const val PACKAGE = "PKG"
|
||||||
|
private val INSTANCE_ID = InstanceId.fakeInstanceId(123)!!
|
||||||
|
private const val APP_UID = 99
|
||||||
private const val SMARTSPACE_KEY = "SMARTSPACE_KEY"
|
private const val SMARTSPACE_KEY = "SMARTSPACE_KEY"
|
||||||
|
private const val SMARTSPACE_PACKAGE = "SMARTSPACE_PKG"
|
||||||
|
private val SMARTSPACE_INSTANCE_ID = InstanceId.fakeInstanceId(456)!!
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
@@ -69,6 +74,8 @@ class MediaDataFilterTest : SysuiTestCase() {
|
|||||||
private lateinit var smartspaceData: SmartspaceMediaData
|
private lateinit var smartspaceData: SmartspaceMediaData
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var smartspaceMediaRecommendationItem: SmartspaceAction
|
private lateinit var smartspaceMediaRecommendationItem: SmartspaceAction
|
||||||
|
@Mock
|
||||||
|
private lateinit var logger: MediaUiEventLogger
|
||||||
|
|
||||||
private lateinit var mediaDataFilter: MediaDataFilter
|
private lateinit var mediaDataFilter: MediaDataFilter
|
||||||
private lateinit var dataMain: MediaData
|
private lateinit var dataMain: MediaData
|
||||||
@@ -79,8 +86,14 @@ class MediaDataFilterTest : SysuiTestCase() {
|
|||||||
fun setup() {
|
fun setup() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
MediaPlayerData.clear()
|
MediaPlayerData.clear()
|
||||||
mediaDataFilter = MediaDataFilter(context, broadcastDispatcher, broadcastSender,
|
mediaDataFilter = MediaDataFilter(
|
||||||
lockscreenUserManager, executor, clock)
|
context,
|
||||||
|
broadcastDispatcher,
|
||||||
|
broadcastSender,
|
||||||
|
lockscreenUserManager,
|
||||||
|
executor,
|
||||||
|
clock,
|
||||||
|
logger)
|
||||||
mediaDataFilter.mediaDataManager = mediaDataManager
|
mediaDataFilter.mediaDataManager = mediaDataManager
|
||||||
mediaDataFilter.addListener(listener)
|
mediaDataFilter.addListener(listener)
|
||||||
|
|
||||||
@@ -90,16 +103,19 @@ class MediaDataFilterTest : SysuiTestCase() {
|
|||||||
// Set up test media data
|
// Set up test media data
|
||||||
dataMain = MediaTestUtils.emptyMediaData.copy(
|
dataMain = MediaTestUtils.emptyMediaData.copy(
|
||||||
userId = USER_MAIN,
|
userId = USER_MAIN,
|
||||||
packageName = PACKAGE)
|
packageName = PACKAGE,
|
||||||
|
instanceId = INSTANCE_ID,
|
||||||
|
appUid = APP_UID)
|
||||||
dataGuest = dataMain.copy(userId = USER_GUEST)
|
dataGuest = dataMain.copy(userId = USER_GUEST)
|
||||||
|
|
||||||
`when`(smartspaceData.targetId).thenReturn(SMARTSPACE_KEY)
|
`when`(smartspaceData.targetId).thenReturn(SMARTSPACE_KEY)
|
||||||
`when`(smartspaceData.isActive).thenReturn(true)
|
`when`(smartspaceData.isActive).thenReturn(true)
|
||||||
`when`(smartspaceData.isValid).thenReturn(true)
|
`when`(smartspaceData.isValid).thenReturn(true)
|
||||||
`when`(smartspaceData.packageName).thenReturn(PACKAGE)
|
`when`(smartspaceData.packageName).thenReturn(SMARTSPACE_PACKAGE)
|
||||||
`when`(smartspaceData.recommendations).thenReturn(listOf(smartspaceMediaRecommendationItem))
|
`when`(smartspaceData.recommendations).thenReturn(listOf(smartspaceMediaRecommendationItem))
|
||||||
`when`(smartspaceData.headphoneConnectionTimeMillis).thenReturn(
|
`when`(smartspaceData.headphoneConnectionTimeMillis).thenReturn(
|
||||||
clock.currentTimeMillis() - 100)
|
clock.currentTimeMillis() - 100)
|
||||||
|
`when`(smartspaceData.instanceId).thenReturn(SMARTSPACE_INSTANCE_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUser(id: Int) {
|
private fun setUser(id: Int) {
|
||||||
@@ -241,6 +257,8 @@ class MediaDataFilterTest : SysuiTestCase() {
|
|||||||
.onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true))
|
.onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true))
|
||||||
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue()
|
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue()
|
||||||
assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
|
assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
|
||||||
|
verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID)
|
||||||
|
verify(logger, never()).logRecommendationActivated(any(), any(), any())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -254,6 +272,8 @@ class MediaDataFilterTest : SysuiTestCase() {
|
|||||||
verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
|
verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
|
||||||
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
|
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
|
||||||
assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
|
assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
|
||||||
|
verify(logger, never()).logRecommendationAdded(any(), any())
|
||||||
|
verify(logger, never()).logRecommendationActivated(any(), any(), any())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -267,6 +287,8 @@ class MediaDataFilterTest : SysuiTestCase() {
|
|||||||
.onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true))
|
.onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true))
|
||||||
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue()
|
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue()
|
||||||
assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
|
assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
|
||||||
|
verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID)
|
||||||
|
verify(logger, never()).logRecommendationActivated(any(), any(), any())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -281,6 +303,8 @@ class MediaDataFilterTest : SysuiTestCase() {
|
|||||||
verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
|
verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
|
||||||
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
|
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
|
||||||
assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
|
assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
|
||||||
|
verify(logger, never()).logRecommendationAdded(any(), any())
|
||||||
|
verify(logger, never()).logRecommendationActivated(any(), any(), any())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -302,6 +326,8 @@ class MediaDataFilterTest : SysuiTestCase() {
|
|||||||
verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
|
verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
|
||||||
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
|
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
|
||||||
assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
|
assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
|
||||||
|
verify(logger, never()).logRecommendationAdded(any(), any())
|
||||||
|
verify(logger, never()).logRecommendationActivated(any(), any(), any())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -324,6 +350,8 @@ class MediaDataFilterTest : SysuiTestCase() {
|
|||||||
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
|
assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
|
||||||
// Smartspace update shouldn't be propagated for the empty rec list.
|
// Smartspace update shouldn't be propagated for the empty rec list.
|
||||||
verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
|
verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean())
|
||||||
|
verify(logger, never()).logRecommendationAdded(any(), any())
|
||||||
|
verify(logger).logRecommendationActivated(eq(APP_UID), eq(PACKAGE), eq(INSTANCE_ID))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -345,6 +373,8 @@ class MediaDataFilterTest : SysuiTestCase() {
|
|||||||
// Smartspace update should also be propagated but not prioritized.
|
// Smartspace update should also be propagated but not prioritized.
|
||||||
verify(listener)
|
verify(listener)
|
||||||
.onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
|
.onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
|
||||||
|
verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID)
|
||||||
|
verify(logger).logRecommendationActivated(eq(APP_UID), eq(PACKAGE), eq(INSTANCE_ID))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import android.testing.AndroidTestingRunner
|
|||||||
import android.testing.TestableLooper.RunWithLooper
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
import androidx.media.utils.MediaConstants
|
import androidx.media.utils.MediaConstants
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.internal.logging.InstanceId
|
||||||
import com.android.systemui.InstanceIdSequenceFake
|
import com.android.systemui.InstanceIdSequenceFake
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
@@ -47,6 +48,7 @@ import org.mockito.Mockito
|
|||||||
import org.mockito.Mockito.never
|
import org.mockito.Mockito.never
|
||||||
import org.mockito.Mockito.reset
|
import org.mockito.Mockito.reset
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.Mockito.verifyNoMoreInteractions
|
||||||
import org.mockito.junit.MockitoJUnit
|
import org.mockito.junit.MockitoJUnit
|
||||||
import org.mockito.Mockito.`when` as whenever
|
import org.mockito.Mockito.`when` as whenever
|
||||||
|
|
||||||
@@ -452,11 +454,22 @@ class MediaDataManagerTest : SysuiTestCase() {
|
|||||||
@Test
|
@Test
|
||||||
fun testOnSmartspaceMediaDataLoaded_hasNewValidMediaTarget_callsListener() {
|
fun testOnSmartspaceMediaDataLoaded_hasNewValidMediaTarget_callsListener() {
|
||||||
smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
|
smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
|
||||||
|
verify(logger).getNewInstanceId()
|
||||||
|
val instanceId = instanceIdSequence.lastInstanceId
|
||||||
|
|
||||||
verify(listener).onSmartspaceMediaDataLoaded(
|
verify(listener).onSmartspaceMediaDataLoaded(
|
||||||
eq(KEY_MEDIA_SMARTSPACE),
|
eq(KEY_MEDIA_SMARTSPACE),
|
||||||
eq(SmartspaceMediaData(KEY_MEDIA_SMARTSPACE, true /* isActive */, true /*isValid */,
|
eq(SmartspaceMediaData(
|
||||||
PACKAGE_NAME, mediaSmartspaceBaseAction, listOf(mediaRecommendationItem),
|
targetId = KEY_MEDIA_SMARTSPACE,
|
||||||
DISMISS_INTENT, 0, 1234L)),
|
isActive = true,
|
||||||
|
isValid = true,
|
||||||
|
packageName = PACKAGE_NAME,
|
||||||
|
cardAction = mediaSmartspaceBaseAction,
|
||||||
|
recommendations = listOf(mediaRecommendationItem),
|
||||||
|
dismissIntent = DISMISS_INTENT,
|
||||||
|
backgroundColor = 0,
|
||||||
|
headphoneConnectionTimeMillis = 1234L,
|
||||||
|
instanceId = InstanceId.fakeInstanceId(instanceId))),
|
||||||
eq(false))
|
eq(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,12 +477,18 @@ class MediaDataManagerTest : SysuiTestCase() {
|
|||||||
fun testOnSmartspaceMediaDataLoaded_hasNewInvalidMediaTarget_callsListener() {
|
fun testOnSmartspaceMediaDataLoaded_hasNewInvalidMediaTarget_callsListener() {
|
||||||
whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf())
|
whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf())
|
||||||
smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
|
smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
|
||||||
|
verify(logger).getNewInstanceId()
|
||||||
|
val instanceId = instanceIdSequence.lastInstanceId
|
||||||
|
|
||||||
verify(listener).onSmartspaceMediaDataLoaded(
|
verify(listener).onSmartspaceMediaDataLoaded(
|
||||||
eq(KEY_MEDIA_SMARTSPACE),
|
eq(KEY_MEDIA_SMARTSPACE),
|
||||||
eq(EMPTY_SMARTSPACE_MEDIA_DATA
|
eq(EMPTY_SMARTSPACE_MEDIA_DATA.copy(
|
||||||
.copy(targetId = KEY_MEDIA_SMARTSPACE, isActive = true,
|
targetId = KEY_MEDIA_SMARTSPACE,
|
||||||
isValid = false, dismissIntent = DISMISS_INTENT,
|
isActive = true,
|
||||||
headphoneConnectionTimeMillis = 1234L)),
|
isValid = false,
|
||||||
|
dismissIntent = DISMISS_INTENT,
|
||||||
|
headphoneConnectionTimeMillis = 1234L,
|
||||||
|
instanceId = InstanceId.fakeInstanceId(instanceId))),
|
||||||
eq(false))
|
eq(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,18 +503,25 @@ class MediaDataManagerTest : SysuiTestCase() {
|
|||||||
whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf())
|
whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf())
|
||||||
|
|
||||||
smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
|
smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
|
||||||
|
verify(logger).getNewInstanceId()
|
||||||
|
val instanceId = instanceIdSequence.lastInstanceId
|
||||||
|
|
||||||
verify(listener).onSmartspaceMediaDataLoaded(
|
verify(listener).onSmartspaceMediaDataLoaded(
|
||||||
eq(KEY_MEDIA_SMARTSPACE),
|
eq(KEY_MEDIA_SMARTSPACE),
|
||||||
eq(EMPTY_SMARTSPACE_MEDIA_DATA
|
eq(EMPTY_SMARTSPACE_MEDIA_DATA.copy(
|
||||||
.copy(targetId = KEY_MEDIA_SMARTSPACE, isActive = true,
|
targetId = KEY_MEDIA_SMARTSPACE,
|
||||||
isValid = false, dismissIntent = null, headphoneConnectionTimeMillis = 1234L)),
|
isActive = true,
|
||||||
|
isValid = false,
|
||||||
|
dismissIntent = null,
|
||||||
|
headphoneConnectionTimeMillis = 1234L,
|
||||||
|
instanceId = InstanceId.fakeInstanceId(instanceId))),
|
||||||
eq(false))
|
eq(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_notCallsListener() {
|
fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_notCallsListener() {
|
||||||
smartspaceMediaDataProvider.onTargetsAvailable(listOf())
|
smartspaceMediaDataProvider.onTargetsAvailable(listOf())
|
||||||
|
verify(logger, never()).getNewInstanceId()
|
||||||
verify(listener, never())
|
verify(listener, never())
|
||||||
.onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean())
|
.onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean())
|
||||||
}
|
}
|
||||||
@@ -503,11 +529,14 @@ class MediaDataManagerTest : SysuiTestCase() {
|
|||||||
@Test
|
@Test
|
||||||
fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_callsRemoveListener() {
|
fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_callsRemoveListener() {
|
||||||
smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
|
smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
|
||||||
|
verify(logger).getNewInstanceId()
|
||||||
|
|
||||||
smartspaceMediaDataProvider.onTargetsAvailable(listOf())
|
smartspaceMediaDataProvider.onTargetsAvailable(listOf())
|
||||||
foregroundExecutor.advanceClockToLast()
|
foregroundExecutor.advanceClockToLast()
|
||||||
foregroundExecutor.runAllReady()
|
foregroundExecutor.runAllReady()
|
||||||
|
|
||||||
verify(listener).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(false))
|
verify(listener).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(false))
|
||||||
|
verifyNoMoreInteractions(logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user