diff options
| author | 2024-06-15 16:44:22 +0000 | |
|---|---|---|
| committer | 2024-06-15 16:44:22 +0000 | |
| commit | a0e55bf92dfff4c08570e564ddf5c21b13fa2c9c (patch) | |
| tree | 76470aca53c756e4e30b1b6417b985896fe31fcd | |
| parent | 25a01a3842c6d8e12a012a4a0a87d5f96d9af3df (diff) | |
| parent | a7d4027e991f53e82896ab5bbf95821632a2ebad (diff) | |
Merge "Add logs when media is loaded or removed" into main
8 files changed, 285 insertions, 12 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java index 14890d7031f0..1e79f429cee6 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -364,6 +364,16 @@ public class LogModule { return factory.create("MediaCarouselCtlrLog", 20); } + /** + * Provides a buffer for media loading changes + */ + @Provides + @SysUISingleton + @MediaLoadingLog + public static LogBuffer providesMediaLoadingLogBuffer(LogBufferFactory factory) { + return factory.create("MediaLoadingLog", 20); + } + /** Allows logging buffers to be tweaked via adb on debug builds but not on prod builds. */ @Provides @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaLoadingLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/MediaLoadingLog.kt new file mode 100644 index 000000000000..05e1b2e2cd23 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/MediaLoadingLog.kt @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.log.dagger + +import com.android.systemui.log.LogBuffer +import javax.inject.Qualifier + +/** A [LogBuffer] for [com.android.systemui.media.controls.domain.pipeline.MediaLoadingLogger] */ +@Qualifier +@MustBeDocumented +@Retention(AnnotationRetention.RUNTIME) +annotation class MediaLoadingLog 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 8d19ce800cbe..f78a0f959f3c 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 @@ -24,6 +24,7 @@ import com.android.internal.annotations.KeepForWeakReference import com.android.internal.annotations.VisibleForTesting import com.android.internal.logging.InstanceId import com.android.systemui.broadcast.BroadcastSender +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.media.controls.data.repository.MediaFilterRepository import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_RESUME @@ -56,6 +57,7 @@ private const val RESUMABLE_MEDIA_MAX_AGE_SECONDS_KEY = "resumable_media_max_age * This is added at the end of the pipeline since we may still need to handle callbacks from * background users (e.g. timeouts). */ +@SysUISingleton class MediaDataFilterImpl @Inject constructor( @@ -68,11 +70,13 @@ constructor( private val logger: MediaUiEventLogger, private val mediaFlags: MediaFlags, private val mediaFilterRepository: MediaFilterRepository, + private val mediaLoadingLogger: MediaLoadingLogger, ) : MediaDataManager.Listener { /** Non-UI listeners to media changes. */ private val _listeners: MutableSet<MediaDataProcessor.Listener> = mutableSetOf() val listeners: Set<MediaDataProcessor.Listener> get() = _listeners.toSet() + lateinit var mediaDataProcessor: MediaDataProcessor // Ensure the field (and associated reference) isn't removed during optimization. @@ -114,6 +118,7 @@ constructor( mediaFilterRepository.addSelectedUserMediaEntry(data) + mediaLoadingLogger.logMediaLoaded(data.instanceId, data.active, "loading media") mediaFilterRepository.addMediaDataLoadingState( MediaDataLoadingModel.Loaded(data.instanceId) ) @@ -167,7 +172,6 @@ constructor( if (shouldReactivate) { val lastActiveId = sorted.lastKey() // most recently active id // Update loading state to consider this media active - Log.d(TAG, "reactivating $lastActiveId instead of smartspace") mediaFilterRepository.setReactivatedId(lastActiveId) val mediaData = sorted[lastActiveId]!!.copy(active = true) logger.logRecommendationActivated( @@ -178,6 +182,11 @@ constructor( mediaFilterRepository.addMediaDataLoadingState( MediaDataLoadingModel.Loaded(lastActiveId) ) + mediaLoadingLogger.logMediaLoaded( + mediaData.instanceId, + mediaData.active, + "reactivating media instead of smartspace" + ) listeners.forEach { listener -> getKey(lastActiveId)?.let { lastActiveKey -> listener.onMediaDataLoaded( @@ -210,6 +219,7 @@ constructor( mediaFilterRepository.setRecommendationsLoadingState( SmartspaceMediaLoadingModel.Loaded(key, shouldPrioritizeMutable) ) + mediaLoadingLogger.logRecommendationLoaded(key, data.isActive, "loading recommendations") listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable) } } @@ -220,6 +230,7 @@ constructor( mediaFilterRepository.addMediaDataLoadingState( MediaDataLoadingModel.Removed(instanceId) ) + mediaLoadingLogger.logMediaRemoved(instanceId, "removing media card") // Only notify listeners if something actually changed listeners.forEach { it.onMediaDataRemoved(key, userInitiated) } } @@ -230,12 +241,16 @@ constructor( // First check if we had reactivated media instead of forwarding smartspace mediaFilterRepository.reactivatedId.value?.let { lastActiveId -> mediaFilterRepository.setReactivatedId(null) - Log.d(TAG, "expiring reactivated key $lastActiveId") // Update loading state with actual active value mediaFilterRepository.selectedUserEntries.value[lastActiveId]?.let { mediaFilterRepository.addMediaDataLoadingState( MediaDataLoadingModel.Loaded(lastActiveId, immediately) ) + mediaLoadingLogger.logMediaLoaded( + lastActiveId, + it.active, + "expiring reactivated id" + ) listeners.forEach { listener -> getKey(lastActiveId)?.let { lastActiveKey -> listener.onMediaDataLoaded(lastActiveKey, lastActiveKey, it, immediately) @@ -256,6 +271,11 @@ constructor( mediaFilterRepository.setRecommendationsLoadingState( SmartspaceMediaLoadingModel.Removed(key, immediately) ) + mediaLoadingLogger.logRecommendationRemoved( + key, + immediately, + "removing recommendations card" + ) listeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) } } @@ -265,11 +285,14 @@ constructor( mediaFilterRepository.allUserEntries.value.forEach { (key, data) -> if (!lockscreenUserManager.isProfileAvailable(data.userId)) { // Only remove media when the profile is unavailable. - if (DEBUG) Log.d(TAG, "Removing $key after profile change") mediaFilterRepository.removeSelectedUserMediaEntry(data.instanceId, data) mediaFilterRepository.addMediaDataLoadingState( MediaDataLoadingModel.Removed(data.instanceId) ) + mediaLoadingLogger.logMediaRemoved( + data.instanceId, + "Removing $key after profile change" + ) listeners.forEach { listener -> listener.onMediaDataRemoved(key, false) } } } @@ -283,10 +306,10 @@ constructor( // Clear the list first and update loading state to remove media from UI. mediaFilterRepository.clearSelectedUserMedia() keyCopy.forEach { instanceId -> - if (DEBUG) Log.d(TAG, "Removing $instanceId after user change") mediaFilterRepository.addMediaDataLoadingState( MediaDataLoadingModel.Removed(instanceId) ) + mediaLoadingLogger.logMediaRemoved(instanceId, "Removing media after user change") getKey(instanceId)?.let { listenersCopy.forEach { listener -> listener.onMediaDataRemoved(it, false) } } @@ -294,15 +317,15 @@ constructor( mediaFilterRepository.allUserEntries.value.forEach { (key, data) -> if (lockscreenUserManager.isCurrentProfile(data.userId)) { - if (DEBUG) - Log.d( - TAG, - "Re-adding $key with instanceId=${data.instanceId} after user change" - ) mediaFilterRepository.addSelectedUserMediaEntry(data) mediaFilterRepository.addMediaDataLoadingState( MediaDataLoadingModel.Loaded(data.instanceId) ) + mediaLoadingLogger.logMediaLoaded( + data.instanceId, + data.active, + "Re-adding $key after user change" + ) listenersCopy.forEach { listener -> listener.onMediaDataLoaded(key, null, data) } } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaLoadingLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaLoadingLogger.kt new file mode 100644 index 000000000000..c6cfd659eed5 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaLoadingLogger.kt @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.domain.pipeline + +import com.android.internal.logging.InstanceId +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.core.LogLevel +import com.android.systemui.log.dagger.MediaLoadingLog +import javax.inject.Inject + +/** A buffered log for media loading events. */ +@SysUISingleton +class MediaLoadingLogger @Inject constructor(@MediaLoadingLog private val buffer: LogBuffer) { + + fun logMediaLoaded(instanceId: InstanceId, active: Boolean, reason: String) { + buffer.log( + TAG, + LogLevel.DEBUG, + { + str1 = instanceId.toString() + bool1 = active + str2 = reason + }, + { "add media $str1, active: $bool1, reason: $str2" } + ) + } + + fun logMediaRemoved(instanceId: InstanceId, reason: String) { + buffer.log( + TAG, + LogLevel.DEBUG, + { + str1 = instanceId.toString() + str2 = reason + }, + { "removing media $str1, reason: $str2" } + ) + } + + fun logRecommendationLoaded(key: String, isActive: Boolean, reason: String) { + buffer.log( + TAG, + LogLevel.DEBUG, + { + str1 = key + bool1 = isActive + str2 = reason + }, + { "add recommendation $str1, active $bool1, reason: $str2" } + ) + } + + fun logRecommendationRemoved(key: String, immediately: Boolean, reason: String) { + buffer.log( + TAG, + LogLevel.DEBUG, + { + str1 = key + bool1 = immediately + str2 = reason + }, + { "removing recommendation $str1, immediate=$bool1, reason: $str2" } + ) + } + + companion object { + private const val TAG = "MediaLoadingLog" + } +} 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 315a9fb0c592..f0d8df511c73 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 @@ -155,13 +155,17 @@ constructor( mediaFlags.isPersistentSsCardEnabled(), recsViewModel = recommendationsViewModel, onAdded = { commonViewModel -> - onMediaRecommendationAddedOrUpdated(commonViewModel) + onMediaRecommendationAddedOrUpdated( + commonViewModel as MediaCommonViewModel.MediaRecommendations + ) }, onRemoved = { immediatelyRemove -> onMediaRecommendationRemoved(commonModel, immediatelyRemove) }, onUpdated = { commonViewModel -> - onMediaRecommendationAddedOrUpdated(commonViewModel) + onMediaRecommendationAddedOrUpdated( + commonViewModel as MediaCommonViewModel.MediaRecommendations + ) }, ) .also { mediaRecs = it } @@ -185,7 +189,9 @@ constructor( } } - private fun onMediaRecommendationAddedOrUpdated(commonViewModel: MediaCommonViewModel) { + private fun onMediaRecommendationAddedOrUpdated( + commonViewModel: MediaCommonViewModel.MediaRecommendations + ) { if (!interactor.isRecommendationActive()) { if (!mediaFlags.isPersistentSsCardEnabled()) { commonViewModel.onRemoved(true) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt index 064cf09959ca..4da56b51e423 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt @@ -53,8 +53,10 @@ import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyLong +import org.mockito.ArgumentMatchers.anyString import org.mockito.Mock import org.mockito.Mockito.never +import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import org.mockito.kotlin.any @@ -100,6 +102,7 @@ class MediaDataFilterImplTest : SysuiTestCase() { private lateinit var dataPrivateProfile: MediaData private val clock = FakeSystemClock() private val repository: MediaFilterRepository = kosmos.mediaFilterRepository + private val mediaLoadingLogger = kosmos.mockMediaLoadingLogger @Before fun setup() { @@ -118,6 +121,7 @@ class MediaDataFilterImplTest : SysuiTestCase() { logger, mediaFlags, repository, + mediaLoadingLogger, ) mediaDataFilter.mediaDataProcessor = mediaDataProcessor mediaDataFilter.addListener(listener) @@ -176,6 +180,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { verify(listener) .onMediaDataLoaded(eq(KEY), eq(null), eq(dataMain), eq(true), eq(0), eq(false)) + verify(mediaLoadingLogger) + .logMediaLoaded(eq(dataMain.instanceId), eq(dataMain.active), anyString()) assertThat(currentMedia).containsExactly(mediaCommonModel) } @@ -190,6 +196,7 @@ class MediaDataFilterImplTest : SysuiTestCase() { verify(listener, never()) .onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt(), anyBoolean()) + verify(mediaLoadingLogger, never()).logMediaLoaded(any(), anyBoolean(), anyString()) assertThat(currentMedia).doesNotContain(mediaCommonModel) } @@ -203,11 +210,14 @@ class MediaDataFilterImplTest : SysuiTestCase() { // GIVEN a media was removed for main user mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) + verify(mediaLoadingLogger) + .logMediaLoaded(eq(dataMain.instanceId), eq(dataMain.active), anyString()) assertThat(currentMedia).containsExactly(mediaCommonModel) mediaDataFilter.onMediaDataRemoved(KEY, false) verify(listener).onMediaDataRemoved(eq(KEY), eq(false)) + verify(mediaLoadingLogger).logMediaRemoved(eq(dataMain.instanceId), anyString()) assertThat(currentMedia).doesNotContain(mediaCommonModel) } @@ -221,6 +231,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { mediaDataFilter.onMediaDataRemoved(KEY, false) verify(listener, never()).onMediaDataRemoved(eq(KEY), eq(false)) + verify(mediaLoadingLogger, never()) + .logMediaRemoved(eq(dataGuest.instanceId), anyString()) assertThat(currentMedia).isEmpty() } @@ -233,6 +245,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { // GIVEN that we have a media loaded for main user mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain) + verify(mediaLoadingLogger) + .logMediaLoaded(eq(dataMain.instanceId), eq(dataMain.active), anyString()) assertThat(currentMedia).containsExactly(MediaCommonModel.MediaControl(mediaLoaded)) // and we switch to guest user @@ -240,6 +254,7 @@ class MediaDataFilterImplTest : SysuiTestCase() { // THEN we should remove the main user's media verify(listener).onMediaDataRemoved(eq(KEY), eq(false)) + verify(mediaLoadingLogger).logMediaRemoved(eq(dataMain.instanceId), anyString()) assertThat(currentMedia).isEmpty() } @@ -260,6 +275,10 @@ class MediaDataFilterImplTest : SysuiTestCase() { // THEN we should add back the guest user media verify(listener) .onMediaDataLoaded(eq(KEY_ALT), eq(null), eq(dataGuest), eq(true), eq(0), eq(false)) + verify(mediaLoadingLogger) + .logMediaLoaded(eq(dataGuest.instanceId), eq(dataGuest.active), anyString()) + + reset(mediaLoadingLogger) // but not the main user's verify(listener, never()) @@ -271,6 +290,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { anyInt(), anyBoolean() ) + verify(mediaLoadingLogger, never()) + .logMediaLoaded(eq(dataMain.instanceId), anyBoolean(), anyString()) assertThat(currentMedia) .containsExactly(MediaCommonModel.MediaControl(guestLoadedStatesModel)) assertThat(currentMedia) @@ -292,6 +313,7 @@ class MediaDataFilterImplTest : SysuiTestCase() { val mediaLoadedStatesModel = MediaDataLoadingModel.Loaded(dataMain.instanceId) // THEN we should remove the private profile media verify(listener).onMediaDataRemoved(eq(KEY_ALT), eq(false)) + verify(mediaLoadingLogger).logMediaRemoved(eq(dataGuest.instanceId), anyString()) assertThat(currentMedia) .containsExactly(MediaCommonModel.MediaControl(mediaLoadedStatesModel)) } @@ -541,6 +563,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { assertThat(hasActiveMedia(selectedUserEntries)).isFalse() verify(listener) .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true)) + verify(mediaLoadingLogger) + .logRecommendationLoaded(eq(SMARTSPACE_KEY), eq(true), anyString()) verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID) verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @@ -570,6 +594,9 @@ class MediaDataFilterImplTest : SysuiTestCase() { verify(listener, never()) .onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt(), anyBoolean()) verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) + verify(mediaLoadingLogger, never()).logMediaLoaded(any(), anyBoolean(), anyString()) + verify(mediaLoadingLogger, never()) + .logRecommendationLoaded(any(), anyBoolean(), anyString()) verify(logger, never()).logRecommendationAdded(any(), any()) verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @@ -607,6 +634,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { assertThat(hasActiveMedia(selectedUserEntries)).isFalse() verify(listener) .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true)) + verify(mediaLoadingLogger) + .logRecommendationLoaded(eq(SMARTSPACE_KEY), eq(true), anyString()) verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID) verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @@ -641,6 +670,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { .isFalse() assertThat(hasActiveMedia(selectedUserEntries)).isFalse() verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) + verify(mediaLoadingLogger, never()) + .logRecommendationLoaded(any(), anyBoolean(), anyString()) verify(logger, never()).logRecommendationAdded(any(), any()) verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @@ -668,6 +699,10 @@ class MediaDataFilterImplTest : SysuiTestCase() { assertThat(currentMedia).containsExactly(controlCommonModel) verify(listener) .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) + verify(mediaLoadingLogger) + .logMediaLoaded(eq(dataCurrent.instanceId), eq(dataCurrent.active), anyString()) + + reset(mediaLoadingLogger) // AND we get a smartspace signal mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) @@ -686,6 +721,10 @@ class MediaDataFilterImplTest : SysuiTestCase() { verify(listener, never()) .onMediaDataLoaded(eq(KEY), eq(KEY), any(), anyBoolean(), anyInt(), anyBoolean()) verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) + verify(mediaLoadingLogger, never()) + .logMediaLoaded(eq(dataCurrent.instanceId), anyBoolean(), anyString()) + verify(mediaLoadingLogger, never()) + .logRecommendationLoaded(any(), anyBoolean(), anyString()) verify(logger, never()).logRecommendationAdded(any(), any()) verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @@ -711,6 +750,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { assertThat(currentMedia).containsExactly(controlCommonModel) verify(listener) .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) + verify(mediaLoadingLogger) + .logMediaLoaded(eq(dataCurrent.instanceId), eq(dataCurrent.active), anyString()) // AND we get a smartspace signal runCurrent() @@ -736,8 +777,16 @@ class MediaDataFilterImplTest : SysuiTestCase() { eq(100), eq(true) ) + verify(mediaLoadingLogger) + .logMediaLoaded( + eq(dataCurrentAndActive.instanceId), + eq(dataCurrentAndActive.active), + anyString() + ) // Smartspace update shouldn't be propagated for the empty rec list. verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) + verify(mediaLoadingLogger, never()) + .logRecommendationLoaded(any(), anyBoolean(), anyString()) verify(logger, never()).logRecommendationAdded(any(), any()) verify(logger).logRecommendationActivated(eq(APP_UID), eq(PACKAGE), eq(INSTANCE_ID)) } @@ -767,6 +816,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { assertThat(currentMedia).containsExactly(controlCommonModel) verify(listener) .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) + verify(mediaLoadingLogger) + .logMediaLoaded(eq(dataCurrent.instanceId), eq(dataCurrent.active), anyString()) // AND we get a smartspace signal runCurrent() @@ -783,6 +834,12 @@ class MediaDataFilterImplTest : SysuiTestCase() { eq(100), eq(true) ) + verify(mediaLoadingLogger) + .logMediaLoaded( + eq(dataCurrentAndActive.instanceId), + eq(dataCurrentAndActive.active), + anyString() + ) assertThat( hasActiveMediaOrRecommendation( selectedUserEntries, @@ -795,6 +852,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { assertThat(currentMedia).containsExactly(controlCommonModel, recsCommonModel) verify(listener) .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) + verify(mediaLoadingLogger) + .logRecommendationLoaded(eq(SMARTSPACE_KEY), eq(true), anyString()) verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID) verify(logger).logRecommendationActivated(eq(APP_UID), eq(PACKAGE), eq(INSTANCE_ID)) } @@ -811,6 +870,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) verify(listener).onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) + verify(mediaLoadingLogger) + .logRecommendationRemoved(eq(SMARTSPACE_KEY), eq(true), anyString()) assertThat(currentMedia).isEmpty() assertThat( hasActiveMediaOrRecommendation( @@ -842,6 +903,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { assertThat(currentMedia).containsExactly(controlCommonModel) verify(listener) .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) + verify(mediaLoadingLogger) + .logMediaLoaded(eq(dataCurrent.instanceId), eq(dataCurrent.active), anyString()) runCurrent() mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) @@ -856,10 +919,18 @@ class MediaDataFilterImplTest : SysuiTestCase() { eq(100), eq(true) ) + verify(mediaLoadingLogger) + .logMediaLoaded( + eq(dataCurrentAndActive.instanceId), + eq(dataCurrentAndActive.active), + anyString() + ) mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) verify(listener).onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) + verify(mediaLoadingLogger) + .logRecommendationRemoved(eq(SMARTSPACE_KEY), eq(true), anyString()) assertThat(currentMedia).containsExactly(controlCommonModel) assertThat( hasActiveMediaOrRecommendation( @@ -890,6 +961,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { verify(listener) .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) + verify(mediaLoadingLogger) + .logRecommendationLoaded(eq(SMARTSPACE_KEY), eq(false), anyString()) assertThat(currentMedia).containsExactly(recsCommonModel) assertThat( hasActiveMediaOrRecommendation( @@ -930,16 +1003,23 @@ class MediaDataFilterImplTest : SysuiTestCase() { verify(listener) .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) + verify(mediaLoadingLogger) + .logMediaLoaded(eq(dataCurrent.instanceId), eq(dataCurrent.active), anyString()) assertThat(currentMedia).containsExactly(controlCommonModel) + reset(mediaLoadingLogger) + // And an inactive recommendation is loaded mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) // Smartspace is loaded but the media stays inactive verify(listener) .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) + verify(mediaLoadingLogger) + .logRecommendationLoaded(eq(SMARTSPACE_KEY), eq(false), anyString()) verify(listener, never()) .onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt(), anyBoolean()) + verify(mediaLoadingLogger, never()).logMediaLoaded(any(), anyBoolean(), anyString()) assertThat(currentMedia).containsExactly(controlCommonModel, recsCommonModel) assertThat( hasActiveMediaOrRecommendation( @@ -995,6 +1075,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { verify(listener) .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) + verify(mediaLoadingLogger) + .logMediaLoaded(eq(dataCurrent.instanceId), eq(dataCurrent.active), anyString()) assertThat(currentMedia).containsExactly(controlCommonModel) // AND we get a smartspace signal with extra to trigger resume @@ -1014,6 +1096,12 @@ class MediaDataFilterImplTest : SysuiTestCase() { eq(100), eq(true) ) + verify(mediaLoadingLogger) + .logMediaLoaded( + eq(dataCurrentAndActive.instanceId), + eq(dataCurrentAndActive.active), + anyString() + ) assertThat(currentMedia).containsExactly(controlCommonModel, recsCommonModel) assertThat( hasActiveMediaOrRecommendation( @@ -1026,6 +1114,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { // And update the smartspace data state, but not prioritized verify(listener) .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) + verify(mediaLoadingLogger) + .logRecommendationLoaded(eq(SMARTSPACE_KEY), eq(true), anyString()) } @Test @@ -1049,8 +1139,12 @@ class MediaDataFilterImplTest : SysuiTestCase() { verify(listener) .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false)) + verify(mediaLoadingLogger) + .logMediaLoaded(eq(dataCurrent.instanceId), eq(dataCurrent.active), anyString()) assertThat(currentMedia).containsExactly(controlCommonModel) + reset(mediaLoadingLogger) + // AND we get a smartspace signal with extra to not trigger resume val extras = Bundle().apply { putBoolean(EXTRA_KEY_TRIGGER_RESUME, false) } whenever(cardAction.extras).thenReturn(extras) @@ -1059,9 +1153,13 @@ class MediaDataFilterImplTest : SysuiTestCase() { // THEN listeners are not updated to show media verify(listener, never()) .onMediaDataLoaded(eq(KEY), eq(KEY), any(), eq(true), eq(100), eq(true)) + verify(mediaLoadingLogger, never()) + .logMediaLoaded(eq(dataCurrent.instanceId), anyBoolean(), anyString()) // But the smartspace update is still propagated verify(listener) .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) + verify(mediaLoadingLogger) + .logRecommendationLoaded(eq(SMARTSPACE_KEY), eq(true), anyString()) assertThat(currentMedia).containsExactly(controlCommonModel, recsCommonModel) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterKosmos.kt index d56222ed45a4..b8b006098c6f 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterKosmos.kt @@ -45,5 +45,6 @@ val Kosmos.mediaDataFilter by logger = mediaUiEventLogger, mediaFlags = mediaFlags, mediaFilterRepository = mediaFilterRepository, + mediaLoadingLogger = mediaLoadingLogger, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaLoadingLoggerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaLoadingLoggerKosmos.kt new file mode 100644 index 000000000000..96886f738dbd --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaLoadingLoggerKosmos.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.domain.pipeline + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.log.logcatLogBuffer +import org.mockito.Mockito.mock + +val Kosmos.mediaLoadingLogger by + Kosmos.Fixture { MediaLoadingLogger(logcatLogBuffer("MediaLoadingLogBuffer")) } +val Kosmos.mockMediaLoadingLogger by Kosmos.Fixture { mock(MediaLoadingLogger::class.java) } |