diff options
| author | 2024-06-20 16:01:12 +0000 | |
|---|---|---|
| committer | 2024-06-26 02:10:12 +0000 | |
| commit | 766674fa088e7005df2571001e23b0b0d7ce86dd (patch) | |
| tree | cfa9ab9209712e9917a679e3a66953f9260746af | |
| parent | ef07d4504d0b88907674d6f0aebbfe7fd3f4e202 (diff) | |
Add smartspace logs for media cards impression
Flag: com.android.systemui.scene_container
Bug: 330897926
Test: atest SystemUiRoboTests:MediaCarouselInteractorTest
Change-Id: I924eb34d433a4ad5531e2754f6614efa16bb3164
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( |