summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Michael Mikhail <michaelmikhil@google.com> 2024-06-20 16:01:12 +0000
committer Michael Mikhail <michaelmikhil@google.com> 2024-06-26 02:10:12 +0000
commit766674fa088e7005df2571001e23b0b0d7ce86dd (patch)
treecfa9ab9209712e9917a679e3a66953f9260746af
parentef07d4504d0b88907674d6f0aebbfe7fd3f4e202 (diff)
Add smartspace logs for media cards impression
Flag: com.android.systemui.scene_container Bug: 330897926 Test: atest SystemUiRoboTests:MediaCarouselInteractorTest Change-Id: I924eb34d433a4ad5531e2754f6614efa16bb3164
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt15
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt103
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/util/MediaDiffUtilTest.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt57
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaCommonModel.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelCallback.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelListUpdateCallback.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCommonViewModel.kt1
12 files changed, 233 insertions, 34 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt
index f43fa5048298..24672ebe6134 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt
@@ -183,7 +183,10 @@ class MediaFilterRepositoryTest : SysuiTestCase() {
SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true)
)
underTest.addSelectedUserMediaEntry(playingData)
- underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(playingInstanceId))
+ underTest.addMediaDataLoadingState(
+ MediaDataLoadingModel.Loaded(playingInstanceId),
+ false
+ )
verify(smartspaceLogger)
.logSmartspaceCardReceived(
@@ -193,7 +196,10 @@ class MediaFilterRepositoryTest : SysuiTestCase() {
)
underTest.addSelectedUserMediaEntry(remoteData)
- underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(remoteInstanceId))
+ underTest.addMediaDataLoadingState(
+ MediaDataLoadingModel.Loaded(remoteInstanceId),
+ false
+ )
verify(smartspaceLogger)
.logSmartspaceCardReceived(
@@ -442,7 +448,7 @@ class MediaFilterRepositoryTest : SysuiTestCase() {
reset(smartspaceLogger)
underTest.addSelectedUserMediaEntry(data)
- underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId))
+ underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId), false)
verify(smartspaceLogger)
.logSmartspaceCardReceived(data.smartspaceId, data.appUid, cardinality = 2)
@@ -451,7 +457,8 @@ class MediaFilterRepositoryTest : SysuiTestCase() {
underTest.addSelectedUserMediaEntry(data)
underTest.addMediaDataLoadingState(
- MediaDataLoadingModel.Loaded(instanceId, receivedSmartspaceCardLatency = 123)
+ MediaDataLoadingModel.Loaded(instanceId, receivedSmartspaceCardLatency = 123),
+ true
)
verify(smartspaceLogger)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt
index c62195fafd8c..414974cc2941 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt
@@ -18,6 +18,7 @@ package com.android.systemui.media.controls.domain.interactor
import android.R
import android.graphics.drawable.Icon
+import android.os.Process
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId
@@ -38,12 +39,19 @@ import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel
import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel
+import com.android.systemui.media.controls.util.MediaSmartspaceLogger
+import com.android.systemui.media.controls.util.SmallHash
+import com.android.systemui.media.controls.util.mediaSmartspaceLogger
+import com.android.systemui.media.controls.util.mockMediaSmartspaceLogger
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.Mockito.reset
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -52,7 +60,11 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private val mediaFilterRepository: MediaFilterRepository = kosmos.mediaFilterRepository
+ private val mediaFilterRepository: MediaFilterRepository =
+ with(kosmos) {
+ mediaSmartspaceLogger = mockMediaSmartspaceLogger
+ mediaFilterRepository
+ }
private val mediaRecommendationsInteractor: MediaRecommendationsInteractor =
kosmos.mediaRecommendationsInteractor
val icon = Icon.createWithResource(context, R.drawable.ic_media_play)
@@ -63,6 +75,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
packageName = PACKAGE_NAME,
recommendations = MediaTestHelper.getValidRecommendationList(icon),
)
+ private val smartspaceLogger = kosmos.mockMediaSmartspaceLogger
private val underTest: MediaCarouselInteractor = kosmos.mediaCarouselInteractor
@@ -153,6 +166,18 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
MediaCommonModel.MediaControl(mediaLoadingModel, true)
)
.inOrder()
+
+ underTest.logSmartspaceSeenCard(0, 1, false)
+
+ verify(smartspaceLogger)
+ .logSmartspaceCardUIEvent(
+ MediaSmartspaceLogger.SMARTSPACE_CARD_SEEN_EVENT,
+ SmallHash.hash(mediaRecommendation.targetId),
+ Process.INVALID_UID,
+ surface = SURFACE,
+ 2,
+ true
+ )
}
@Test
@@ -239,7 +264,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
.inOrder()
mediaFilterRepository.addSelectedUserMediaEntry(data.copy(isPlaying = true))
- mediaFilterRepository.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId))
+ mediaFilterRepository.addMediaDataLoadingState(mediaLoadingModel)
assertThat(currentMedia)
.containsExactly(
@@ -249,9 +274,83 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
.inOrder()
}
+ @Test
+ fun loadMediaAndRecommendation_logSmartspaceSeenCard() {
+ val instanceId = InstanceId.fakeInstanceId(123)
+ val data =
+ MediaData(
+ active = true,
+ instanceId = instanceId,
+ packageName = PACKAGE_NAME,
+ notificationKey = KEY
+ )
+ val smartspaceLoadingModel = SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE)
+ val mediaLoadingModel = MediaDataLoadingModel.Loaded(instanceId)
+
+ mediaFilterRepository.addSelectedUserMediaEntry(data)
+ mediaFilterRepository.addMediaDataLoadingState(mediaLoadingModel)
+ underTest.logSmartspaceSeenCard(0, 1, false)
+
+ verify(smartspaceLogger)
+ .logSmartspaceCardUIEvent(
+ MediaSmartspaceLogger.SMARTSPACE_CARD_SEEN_EVENT,
+ data.smartspaceId,
+ data.appUid,
+ surface = SURFACE,
+ 1
+ )
+
+ reset(smartspaceLogger)
+ mediaFilterRepository.addSelectedUserMediaEntry(data)
+ mediaFilterRepository.addMediaDataLoadingState(mediaLoadingModel)
+ underTest.logSmartspaceSeenCard(0, 1, true)
+
+ verify(smartspaceLogger, never())
+ .logSmartspaceCardUIEvent(
+ MediaSmartspaceLogger.SMARTSPACE_CARD_SEEN_EVENT,
+ data.smartspaceId,
+ data.appUid,
+ surface = SURFACE,
+ 2
+ )
+
+ reset(smartspaceLogger)
+ mediaFilterRepository.setRecommendation(mediaRecommendation)
+ mediaFilterRepository.setRecommendationsLoadingState(smartspaceLoadingModel)
+ underTest.logSmartspaceSeenCard(1, 1, true)
+
+ verify(smartspaceLogger)
+ .logSmartspaceCardUIEvent(
+ MediaSmartspaceLogger.SMARTSPACE_CARD_SEEN_EVENT,
+ SmallHash.hash(mediaRecommendation.targetId),
+ Process.INVALID_UID,
+ surface = SURFACE,
+ 2,
+ true,
+ rank = 1
+ )
+
+ reset(smartspaceLogger)
+ mediaFilterRepository.addSelectedUserMediaEntry(data)
+ mediaFilterRepository.addMediaDataLoadingState(
+ mediaLoadingModel.copy(receivedSmartspaceCardLatency = 1)
+ )
+ underTest.logSmartspaceSeenCard(0, 1, true)
+
+ verify(smartspaceLogger)
+ .logSmartspaceCardUIEvent(
+ MediaSmartspaceLogger.SMARTSPACE_CARD_SEEN_EVENT,
+ data.smartspaceId,
+ data.appUid,
+ surface = SURFACE,
+ 2
+ )
+ }
+
companion object {
private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID"
private const val PACKAGE_NAME = "com.android.example"
private const val KEY = "key"
+ private const val SURFACE = 4
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/util/MediaDiffUtilTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/util/MediaDiffUtilTest.kt
index 71685a4354bf..005424ba599e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/util/MediaDiffUtilTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/util/MediaDiffUtilTest.kt
@@ -47,7 +47,7 @@ class MediaDiffUtilTest : SysuiTestCase() {
oldList,
newList,
{ commonViewModel, _ -> assertThat(commonViewModel).isEqualTo(mediaControl) },
- { fail("Unexpected to update $it") },
+ { commonViewModel, _ -> fail("Unexpected to update $commonViewModel") },
{ fail("Unexpected to remove $it") },
{ commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
)
@@ -66,7 +66,7 @@ class MediaDiffUtilTest : SysuiTestCase() {
oldList,
newList,
{ commonViewModel, _ -> assertThat(commonViewModel).isEqualTo(mediaRecs) },
- { fail("Unexpected to update $it") },
+ { commonViewModel, _ -> fail("Unexpected to update $commonViewModel") },
{ fail("Unexpected to remove $it") },
{ commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
)
@@ -85,7 +85,7 @@ class MediaDiffUtilTest : SysuiTestCase() {
oldList,
newList,
{ commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
- { commonViewModel -> assertThat(commonViewModel).isNotEqualTo(mediaControl) },
+ { commonViewModel, _ -> assertThat(commonViewModel).isNotEqualTo(mediaControl) },
{ fail("Unexpected to remove $it") },
{ commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
)
@@ -104,7 +104,7 @@ class MediaDiffUtilTest : SysuiTestCase() {
oldList,
newList,
{ commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
- { commonViewModel -> assertThat(commonViewModel).isNotEqualTo(mediaRecs) },
+ { commonViewModel, _ -> assertThat(commonViewModel).isNotEqualTo(mediaRecs) },
{ fail("Unexpected to remove $it") },
{ commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
)
@@ -124,7 +124,7 @@ class MediaDiffUtilTest : SysuiTestCase() {
oldList,
newList,
{ commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
- { fail("Unexpected to update $it") },
+ { commonViewModel, _ -> fail("Unexpected to update $commonViewModel") },
{ fail("Unexpected to remove $it") },
{ commonViewModel, _, _ -> assertThat(commonViewModel).isEqualTo(mediaControl1) },
)
@@ -145,7 +145,7 @@ class MediaDiffUtilTest : SysuiTestCase() {
oldList,
newList,
{ commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
- { fail("Unexpected to update $it") },
+ { commonViewModel, _ -> fail("Unexpected to update $commonViewModel") },
{ fail("Unexpected to remove $it") },
{ commonViewModel, _, _ -> assertThat(commonViewModel).isEqualTo(mediaRecs) },
)
@@ -164,7 +164,7 @@ class MediaDiffUtilTest : SysuiTestCase() {
oldList,
newList,
{ commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
- { fail("Unexpected to update $it") },
+ { commonViewModel, _ -> fail("Unexpected to update $commonViewModel") },
{ commonViewModel -> assertThat(commonViewModel).isEqualTo(mediaControl) },
{ commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
)
@@ -183,7 +183,7 @@ class MediaDiffUtilTest : SysuiTestCase() {
oldList,
newList,
{ commonViewModel, _ -> fail("Unexpected to add $commonViewModel") },
- { fail("Unexpected to update $it") },
+ { commonViewModel, _ -> fail("Unexpected to update $commonViewModel") },
{ commonViewModel -> assertThat(commonViewModel).isEqualTo(mediaRecs) },
{ commonViewModel, _, _ -> fail("Unexpected to move $commonViewModel ") },
)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt
index 3ee85e8d6a1c..341b8d87eeef 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt
@@ -28,6 +28,7 @@ import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel
import com.android.systemui.media.controls.util.MediaSmartspaceLogger
import com.android.systemui.media.controls.util.MediaSmartspaceLogger.Companion.SMARTSPACE_CARD_DISMISS_EVENT
+import com.android.systemui.media.controls.util.MediaSmartspaceLogger.Companion.SMARTSPACE_CARD_SEEN_EVENT
import com.android.systemui.media.controls.util.SmallHash
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.time.SystemClock
@@ -137,10 +138,13 @@ constructor(
return mediaData
}
- fun addSelectedUserMediaEntry(data: MediaData) {
+ /** @return whether the added media data already exists. */
+ fun addSelectedUserMediaEntry(data: MediaData): Boolean {
val entries = LinkedHashMap<InstanceId, MediaData>(_selectedUserEntries.value)
+ val update = _selectedUserEntries.value.containsKey(data.instanceId)
entries[data.instanceId] = data
_selectedUserEntries.value = entries
+ return update
}
/**
@@ -184,7 +188,10 @@ constructor(
_reactivatedId.value = instanceId
}
- fun addMediaDataLoadingState(mediaDataLoadingModel: MediaDataLoadingModel) {
+ fun addMediaDataLoadingState(
+ mediaDataLoadingModel: MediaDataLoadingModel,
+ isUpdate: Boolean = true
+ ) {
val sortedMap = TreeMap<MediaSortKeyModel, MediaCommonModel>(comparator)
sortedMap.putAll(
sortedMedia.filter { (_, commonModel) ->
@@ -212,15 +219,10 @@ constructor(
MediaCommonModel.MediaControl(
mediaDataLoadingModel,
canBeRemoved(it),
- isMediaFromRec(it)
+ isMediaFromRec(it),
+ if (isUpdate) systemClock.currentTimeMillis() else 0,
)
sortedMap[sortKey] = newCommonModel
- val isUpdate =
- sortedMedia.values.any { commonModel ->
- commonModel is MediaCommonModel.MediaControl &&
- commonModel.mediaLoadedModel.instanceId ==
- mediaDataLoadingModel.instanceId
- }
// On Addition or tapping on recommendations, we should show the new order of media.
if (mediaFromRecPackageName == it.packageName) {
@@ -359,10 +361,47 @@ constructor(
return _selectedUserEntries.value.entries.isNotEmpty()
}
+ fun hasActiveMediaOrRecommendation(): Boolean {
+ return _selectedUserEntries.value.any { it.value.active } ||
+ (isRecommendationActive() &&
+ (_smartspaceMediaData.value.isValid() || _reactivatedId.value != null))
+ }
+
fun isRecommendationActive(): Boolean {
return _smartspaceMediaData.value.isActive
}
+ /** Log visible card given [visibleIndex]. */
+ fun logSmartspaceCardSeen(surface: Int, visibleIndex: Int, isMediaCardUpdate: Boolean) {
+ if (_currentMedia.value.size <= visibleIndex) return
+
+ when (val mediaCommonModel = _currentMedia.value[visibleIndex]) {
+ is MediaCommonModel.MediaControl -> {
+ if (
+ !isMediaCardUpdate ||
+ mediaCommonModel.mediaLoadedModel.receivedSmartspaceCardLatency != 0
+ ) {
+ logSmartspaceMediaCardUserEvent(
+ mediaCommonModel.mediaLoadedModel.instanceId,
+ visibleIndex,
+ SMARTSPACE_CARD_SEEN_EVENT,
+ surface,
+ mediaCommonModel.mediaLoadedModel.isSsReactivated,
+ )
+ }
+ }
+ is MediaCommonModel.MediaRecommendations -> {
+ if (isRecommendationActive()) {
+ logSmarspaceRecommendationCardUserEvent(
+ SMARTSPACE_CARD_SEEN_EVENT,
+ surface,
+ visibleIndex
+ )
+ }
+ }
+ }
+ }
+
/** Log user event on media card if smartspace logging is enabled. */
fun logSmartspaceCardUserEvent(
eventId: Int,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt
index a0ac0d7e7b62..803e7efa7f60 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt
@@ -116,11 +116,12 @@ constructor(
return
}
- mediaFilterRepository.addSelectedUserMediaEntry(data)
+ val isUpdate = mediaFilterRepository.addSelectedUserMediaEntry(data)
mediaLoadingLogger.logMediaLoaded(data.instanceId, data.active, "loading media")
mediaFilterRepository.addMediaDataLoadingState(
- MediaDataLoadingModel.Loaded(data.instanceId)
+ MediaDataLoadingModel.Loaded(data.instanceId),
+ isUpdate
)
// Notify listeners
@@ -323,9 +324,10 @@ constructor(
mediaFilterRepository.allUserEntries.value.forEach { (key, data) ->
if (lockscreenUserManager.isCurrentProfile(data.userId)) {
- mediaFilterRepository.addSelectedUserMediaEntry(data)
+ val isUpdate = mediaFilterRepository.addSelectedUserMediaEntry(data)
mediaFilterRepository.addMediaDataLoadingState(
- MediaDataLoadingModel.Loaded(data.instanceId)
+ MediaDataLoadingModel.Loaded(data.instanceId),
+ isUpdate
)
mediaLoadingLogger.logMediaLoaded(
data.instanceId,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
index 620af4e67e8b..9d7160cbaffc 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
@@ -211,7 +211,8 @@ constructor(
mediaDataFilter.onSwipeToDismiss(MediaSmartspaceLogger.getSurface(location))
}
- override fun hasActiveMediaOrRecommendation() = hasActiveMediaOrRecommendation.value
+ override fun hasActiveMediaOrRecommendation() =
+ mediaFilterRepository.hasActiveMediaOrRecommendation()
override fun hasAnyMediaOrRecommendation() = hasAnyMediaOrRecommendation.value
@@ -225,6 +226,14 @@ constructor(
mediaFilterRepository.setOrderedMedia()
}
+ fun logSmartspaceSeenCard(visibleIndex: Int, location: Int, isMediaCardUpdate: Boolean) {
+ mediaFilterRepository.logSmartspaceCardSeen(
+ MediaSmartspaceLogger.getSurface(location),
+ visibleIndex,
+ isMediaCardUpdate
+ )
+ }
+
/** Add a listener for internal events. */
private fun addInternalListener(listener: MediaDataManager.Listener) =
mediaDataProcessor.addInternalListener(listener)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaCommonModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaCommonModel.kt
index 56cc618eb61c..3d5d47b30860 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaCommonModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaCommonModel.kt
@@ -22,6 +22,7 @@ sealed class MediaCommonModel {
val mediaLoadedModel: MediaDataLoadingModel.Loaded,
val canBeRemoved: Boolean = false,
val isMediaFromRec: Boolean = false,
+ val updateTime: Long = 0L,
) : MediaCommonModel()
data class MediaRecommendations(val recsLoadingModel: SmartspaceMediaLoadingModel) :
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
index f596de0466e3..415a18625c29 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
@@ -764,6 +764,7 @@ constructor(
mediaContent.addView(viewHolder.recommendations, position)
}
}
+ onAddOrUpdateVisibleToUserCard(position, isMediaCardUpdate = false)
viewController.setListening(mediaCarouselScrollHandler.visibleToUser && currentlyExpanded)
controllerByViewModel[commonViewModel] = viewController
updateViewControllerToState(viewController, noAnimation = true)
@@ -781,10 +782,14 @@ constructor(
commonViewModel.onAdded(commonViewModel)
}
- private fun onUpdated(commonViewModel: MediaCommonViewModel) {
+ private fun onUpdated(commonViewModel: MediaCommonViewModel, position: Int) {
commonViewModel.onUpdated(commonViewModel)
updatePageIndicator()
mediaCarouselScrollHandler.onPlayersChanged()
+ onAddOrUpdateVisibleToUserCard(
+ position,
+ commonViewModel is MediaCommonViewModel.MediaControl
+ )
}
private fun onRemoved(commonViewModel: MediaCommonViewModel) {
@@ -821,6 +826,20 @@ constructor(
mediaCarouselScrollHandler.onPlayersChanged()
}
+ private fun onAddOrUpdateVisibleToUserCard(position: Int, isMediaCardUpdate: Boolean) {
+ if (
+ mediaCarouselScrollHandler.visibleToUser &&
+ mediaCarouselScrollHandler.visibleMediaIndex == position
+ ) {
+ mediaCarouselViewModel.onCardVisibleToUser(
+ mediaCarouselScrollHandler.qsExpanded,
+ mediaCarouselScrollHandler.visibleMediaIndex,
+ currentEndLocation,
+ isMediaCardUpdate
+ )
+ }
+ }
+
private fun setNewViewModelsList(viewModels: List<MediaCommonViewModel>) {
commonViewModels.clear()
commonViewModels.addAll(viewModels)
@@ -1434,6 +1453,14 @@ constructor(
/** Log the user impression for media card at visibleMediaIndex. */
fun logSmartspaceImpression(qsExpanded: Boolean) {
+ if (SceneContainerFlag.isEnabled) {
+ mediaCarouselViewModel.onCardVisibleToUser(
+ qsExpanded,
+ mediaCarouselScrollHandler.visibleMediaIndex,
+ currentEndLocation
+ )
+ return
+ }
val visibleMediaIndex = mediaCarouselScrollHandler.visibleMediaIndex
if (MediaPlayerData.players().size > visibleMediaIndex) {
val mediaControlPanel = MediaPlayerData.getMediaControlPanel(visibleMediaIndex)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelCallback.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelCallback.kt
index 952b134c5e16..f28edd638b10 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelCallback.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelCallback.kt
@@ -54,7 +54,8 @@ class MediaViewModelCallback(
oldItem is MediaCommonViewModel.MediaControl &&
newItem is MediaCommonViewModel.MediaControl
) {
- oldItem.immediatelyUpdateUi == newItem.immediatelyUpdateUi
+ oldItem.immediatelyUpdateUi == newItem.immediatelyUpdateUi &&
+ oldItem.updateTime == newItem.updateTime
} else if (
oldItem is MediaCommonViewModel.MediaRecommendations &&
newItem is MediaCommonViewModel.MediaRecommendations
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelListUpdateCallback.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelListUpdateCallback.kt
index bd81e44d091c..709723fa9480 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelListUpdateCallback.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/util/MediaViewModelListUpdateCallback.kt
@@ -24,7 +24,7 @@ class MediaViewModelListUpdateCallback(
private val old: List<MediaCommonViewModel>,
private val new: List<MediaCommonViewModel>,
private val onAdded: (MediaCommonViewModel, Int) -> Unit,
- private val onUpdated: (MediaCommonViewModel) -> Unit,
+ private val onUpdated: (MediaCommonViewModel, Int) -> Unit,
private val onRemoved: (MediaCommonViewModel) -> Unit,
private val onMoved: (MediaCommonViewModel, Int, Int) -> Unit,
) : ListUpdateCallback {
@@ -47,7 +47,7 @@ class MediaViewModelListUpdateCallback(
override fun onChanged(position: Int, count: Int, payload: Any?) {
for (i in position until position + count) {
- onUpdated(new[i])
+ onUpdated(new[i], position)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
index 3c6ccba92ff2..c453a212a3cd 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
@@ -108,12 +108,24 @@ constructor(
interactor.reorderMedia()
}
+ fun onCardVisibleToUser(
+ qsExpanded: Boolean,
+ visibleIndex: Int,
+ location: Int,
+ isUpdate: Boolean = false
+ ) {
+ // Skip logging if on LS or QQS, and there is no active media card
+ if (!qsExpanded && !interactor.hasActiveMediaOrRecommendation()) return
+ interactor.logSmartspaceSeenCard(visibleIndex, location, isUpdate)
+ }
+
private fun toViewModel(
commonModel: MediaCommonModel.MediaControl
): MediaCommonViewModel.MediaControl {
val instanceId = commonModel.mediaLoadedModel.instanceId
return mediaControlByInstanceId[instanceId]?.copy(
- immediatelyUpdateUi = commonModel.mediaLoadedModel.immediatelyUpdateUi
+ immediatelyUpdateUi = commonModel.mediaLoadedModel.immediatelyUpdateUi,
+ updateTime = commonModel.updateTime
)
?: MediaCommonViewModel.MediaControl(
instanceId = instanceId,
@@ -125,7 +137,8 @@ constructor(
mediaControlByInstanceId.remove(instanceId)
},
onUpdated = { onMediaControlAddedOrUpdated(it, commonModel) },
- isMediaFromRec = commonModel.isMediaFromRec
+ isMediaFromRec = commonModel.isMediaFromRec,
+ updateTime = commonModel.updateTime
)
.also { mediaControlByInstanceId[instanceId] = it }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCommonViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCommonViewModel.kt
index a96d75c9ed30..52cb173b39cb 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCommonViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCommonViewModel.kt
@@ -33,6 +33,7 @@ sealed class MediaCommonViewModel {
override val onRemoved: (Boolean) -> Unit,
override val onUpdated: (MediaCommonViewModel) -> Unit,
val isMediaFromRec: Boolean = false,
+ val updateTime: Long = 0,
) : MediaCommonViewModel()
data class MediaRecommendations(