Loading packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt +92 −74 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ import com.android.systemui.dump.DumpManager import com.android.systemui.media.controls.domain.pipeline.MediaDataManager.Companion.isMediaNotification import com.android.systemui.media.controls.domain.resume.MediaResumeListener import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser import com.android.systemui.media.controls.shared.MediaLogger import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_SOURCE import com.android.systemui.media.controls.shared.model.EXTRA_VALUE_TRIGGER_PERIODIC import com.android.systemui.media.controls.shared.model.MediaAction Loading @@ -84,7 +85,7 @@ import com.android.systemui.media.controls.util.MediaControllerFactory import com.android.systemui.media.controls.util.MediaDataUtils import com.android.systemui.media.controls.util.MediaFlags import com.android.systemui.media.controls.util.MediaUiEventLogger import com.android.systemui.plugins.ActivityStarter import com.android.systemui.media.controls.util.SmallHash import com.android.systemui.plugins.BcSmartspaceDataPlugin import com.android.systemui.res.R import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState Loading Loading @@ -186,7 +187,6 @@ class LegacyMediaDataManagerImpl( private val mediaDeviceManager: MediaDeviceManager, mediaDataCombineLatest: MediaDataCombineLatest, private val mediaDataFilter: LegacyMediaDataFilterImpl, private val activityStarter: ActivityStarter, private val smartspaceMediaDataProvider: SmartspaceMediaDataProvider, private var useMediaResumption: Boolean, private val useQsMediaPlayer: Boolean, Loading @@ -197,6 +197,7 @@ class LegacyMediaDataManagerImpl( private val smartspaceManager: SmartspaceManager?, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val mediaDataLoader: dagger.Lazy<MediaDataLoader>, private val mediaLogger: MediaLogger, ) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener, MediaDataManager { companion object { Loading Loading @@ -273,7 +274,6 @@ class LegacyMediaDataManagerImpl( mediaDeviceManager: MediaDeviceManager, mediaDataCombineLatest: MediaDataCombineLatest, mediaDataFilter: LegacyMediaDataFilterImpl, activityStarter: ActivityStarter, smartspaceMediaDataProvider: SmartspaceMediaDataProvider, clock: SystemClock, tunerService: TunerService, Loading @@ -282,6 +282,7 @@ class LegacyMediaDataManagerImpl( smartspaceManager: SmartspaceManager?, keyguardUpdateMonitor: KeyguardUpdateMonitor, mediaDataLoader: dagger.Lazy<MediaDataLoader>, mediaLogger: MediaLogger, ) : this( context, // Loading bitmap for UMO background can take longer time, so it cannot run on the default Loading @@ -301,7 +302,6 @@ class LegacyMediaDataManagerImpl( mediaDeviceManager, mediaDataCombineLatest, mediaDataFilter, activityStarter, smartspaceMediaDataProvider, Utils.useMediaResumption(context), Utils.useQsMediaPlayer(context), Loading @@ -312,6 +312,7 @@ class LegacyMediaDataManagerImpl( smartspaceManager, keyguardUpdateMonitor, mediaDataLoader, mediaLogger, ) private val appChangeReceiver = Loading Loading @@ -564,29 +565,9 @@ class LegacyMediaDataManagerImpl( val resumeAction: Runnable? = currentEntry?.resumeAction val hasCheckedForResume = currentEntry?.hasCheckedForResume == true val active = currentEntry?.active ?: true val mediaController = mediaControllerFactory.create(result.token!!) // We need to log the correct media added. if (isNewlyActiveEntry) { logSingleVsMultipleMediaAdded(result.appUid, sbn.packageName, instanceId) logger.logActiveMediaAdded( result.appUid, sbn.packageName, instanceId, result.playbackLocation ) } else if (result.playbackLocation != currentEntry?.playbackLocation) { logger.logPlaybackLocationChange( result.appUid, sbn.packageName, instanceId, result.playbackLocation ) } withContext(mainDispatcher) { onMediaDataLoaded( key, oldKey, val mediaData = MediaData( userId = sbn.normalizedUserId, initialized = true, Loading Loading @@ -615,8 +596,31 @@ class LegacyMediaDataManagerImpl( appUid = result.appUid, isExplicit = result.isExplicit, ) if (isSameMediaData(context, mediaController, mediaData, currentEntry)) { mediaLogger.logDuplicateMediaNotification(key) return@withContext } // We need to log the correct media added. if (isNewlyActiveEntry) { logSingleVsMultipleMediaAdded(result.appUid, sbn.packageName, instanceId) logger.logActiveMediaAdded( result.appUid, sbn.packageName, instanceId, result.playbackLocation ) } else if (result.playbackLocation != currentEntry?.playbackLocation) { logger.logPlaybackLocationChange( result.appUid, sbn.packageName, instanceId, result.playbackLocation ) } withContext(mainDispatcher) { onMediaDataLoaded(key, oldKey, mediaData) } } /** Add a listener for changes in this class */ Loading Loading @@ -1100,22 +1104,12 @@ class LegacyMediaDataManagerImpl( val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId() val appUid = appInfo?.uid ?: Process.INVALID_UID if (isNewlyActiveEntry) { logSingleVsMultipleMediaAdded(appUid, sbn.packageName, instanceId) logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation) } else if (playbackLocation != currentEntry?.playbackLocation) { logger.logPlaybackLocationChange(appUid, sbn.packageName, instanceId, playbackLocation) } val lastActive = systemClock.elapsedRealtime() val createdTimestampMillis = currentEntry?.createdTimestampMillis ?: 0L foregroundExecutor.execute { val resumeAction: Runnable? = mediaEntries[key]?.resumeAction val hasCheckedForResume = mediaEntries[key]?.hasCheckedForResume == true val active = mediaEntries[key]?.active ?: true onMediaDataLoaded( key, oldKey, var mediaData = MediaData( sbn.normalizedUserId, true, Loading Loading @@ -1143,8 +1137,32 @@ class LegacyMediaDataManagerImpl( instanceId = instanceId, appUid = appUid, isExplicit = isExplicit, smartspaceId = SmallHash.hash(appUid + systemClock.currentTimeMillis().toInt()), ) if (isSameMediaData(context, mediaController, mediaData, currentEntry)) { mediaLogger.logDuplicateMediaNotification(key) return } if (isNewlyActiveEntry) { logSingleVsMultipleMediaAdded(appUid, sbn.packageName, instanceId) logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation) } else if (playbackLocation != currentEntry?.playbackLocation) { logger.logPlaybackLocationChange(appUid, sbn.packageName, instanceId, playbackLocation) } foregroundExecutor.execute { val oldResumeAction: Runnable? = mediaEntries[key]?.resumeAction val oldHasCheckedForResume = mediaEntries[key]?.hasCheckedForResume == true val oldActive = mediaEntries[key]?.active ?: true mediaData = mediaData.copy( resumeAction = oldResumeAction, hasCheckedForResume = oldHasCheckedForResume, active = oldActive ) onMediaDataLoaded(key, oldKey, mediaData) } } Loading packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt +24 −10 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import androidx.annotation.WorkerThread import androidx.core.view.GestureDetectorCompat import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.android.systemui.Flags import com.android.systemui.classifier.Classifier.MEDIA_SEEKBAR import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.plugins.FalsingManager Loading Loading @@ -102,9 +103,11 @@ constructor( } _progress.postValue(value) } private val _progress = MutableLiveData<Progress>().apply { postValue(_data) } val progress: LiveData<Progress> get() = _progress private var controller: MediaController? = null set(value) { if (field?.sessionToken != value?.sessionToken) { Loading @@ -113,6 +116,7 @@ constructor( field = value } } private var playbackState: PlaybackState? = null private var callback = object : MediaController.Callback() { Loading @@ -128,6 +132,15 @@ constructor( override fun onSessionDestroyed() { clearController() } override fun onMetadataChanged(metadata: MediaMetadata?) { if (!Flags.mediaControlsPostsOptimization()) return val (enabled, duration) = getEnabledStateAndDuration(metadata) if (_data.duration != duration) { _data = _data.copy(enabled = enabled, duration = duration) } } } private var cancel: Runnable? = null Loading Loading @@ -233,22 +246,13 @@ constructor( fun updateController(mediaController: MediaController?) { controller = mediaController playbackState = controller?.playbackState val mediaMetadata = controller?.metadata val (enabled, duration) = getEnabledStateAndDuration(controller?.metadata) val seekAvailable = ((playbackState?.actions ?: 0L) and PlaybackState.ACTION_SEEK_TO) != 0L val position = playbackState?.position?.toInt() val duration = mediaMetadata?.getLong(MediaMetadata.METADATA_KEY_DURATION)?.toInt() ?: 0 val playing = NotificationMediaManager.isPlayingState( playbackState?.state ?: PlaybackState.STATE_NONE ) val enabled = if ( playbackState == null || playbackState?.getState() == PlaybackState.STATE_NONE || (duration <= 0) ) false else true _data = Progress(enabled, seekAvailable, playing, scrubbing, position, duration, listening) checkIfPollingNeeded() } Loading Loading @@ -368,6 +372,16 @@ constructor( } } /** returns a pair of whether seekbar is enabled and the duration of media. */ private fun getEnabledStateAndDuration(metadata: MediaMetadata?): Pair<Boolean, Int> { val duration = metadata?.getLong(MediaMetadata.METADATA_KEY_DURATION)?.toInt() ?: 0 val enabled = !(playbackState == null || playbackState?.state == PlaybackState.STATE_NONE || (duration <= 0)) return Pair(enabled, duration) } /** * This method specifies if user made a bad seekbar grab or not. If the vertical distance from * first touch on seekbar is more than the horizontal distance, this means that the seekbar grab Loading packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt +45 −4 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ import android.media.session.MediaSession import android.media.session.PlaybackState import android.net.Uri import android.os.Bundle import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization import android.provider.Settings import android.service.notification.StatusBarNotification Loading @@ -61,6 +63,8 @@ import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.media.controls.domain.resume.MediaResumeListener import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser import com.android.systemui.media.controls.shared.mediaLogger import com.android.systemui.media.controls.shared.mockMediaLogger import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_SOURCE import com.android.systemui.media.controls.shared.model.EXTRA_VALUE_TRIGGER_PERIODIC import com.android.systemui.media.controls.shared.model.MediaData Loading @@ -69,7 +73,6 @@ import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvi import com.android.systemui.media.controls.util.MediaUiEventLogger import com.android.systemui.media.controls.util.fakeMediaControllerFactory import com.android.systemui.media.controls.util.mediaFlags import com.android.systemui.plugins.activityStarter import com.android.systemui.res.R import com.android.systemui.statusbar.SbnBuilder import com.android.systemui.testKosmos Loading Loading @@ -186,11 +189,10 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa mSetFlagsRule.setFlagsParameterization(flags) } private val kosmos = testKosmos() private val kosmos = testKosmos().apply { mediaLogger = mockMediaLogger } private val testDispatcher = kosmos.testDispatcher private val testScope = kosmos.testScope private val fakeFeatureFlags = kosmos.fakeFeatureFlagsClassic private val activityStarter = kosmos.activityStarter private val mediaControllerFactory = kosmos.fakeMediaControllerFactory private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20) Loading Loading @@ -240,7 +242,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa mediaDeviceManager = mediaDeviceManager, mediaDataCombineLatest = mediaDataCombineLatest, mediaDataFilter = mediaDataFilter, activityStarter = activityStarter, smartspaceMediaDataProvider = smartspaceMediaDataProvider, useMediaResumption = true, useQsMediaPlayer = true, Loading @@ -251,6 +252,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa smartspaceManager = smartspaceManager, keyguardUpdateMonitor = keyguardUpdateMonitor, mediaDataLoader = { kosmos.mediaDataLoader }, mediaLogger = kosmos.mediaLogger, ) verify(tunerService) .addTunable(capture(tunableCaptor), eq(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION)) Loading Loading @@ -2404,6 +2406,45 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa assertThat(mediaDataCaptor.value.artwork).isNull() } @Test @EnableFlags(Flags.FLAG_MEDIA_CONTROLS_POSTS_OPTIMIZATION) fun postDuplicateNotification_doesNotCallListeners() { addNotificationAndLoad() reset(listener) mediaDataManager.onNotificationAdded(KEY, mediaNotification) testScope.assertRunAllReady(foreground = 0, background = 1) verify(listener, never()) .onMediaDataLoaded( eq(KEY), eq(KEY), capture(mediaDataCaptor), eq(true), eq(0), eq(false) ) verify(kosmos.mediaLogger).logDuplicateMediaNotification(eq(KEY)) } @Test @DisableFlags(Flags.FLAG_MEDIA_CONTROLS_POSTS_OPTIMIZATION) fun postDuplicateNotification_callsListeners() { addNotificationAndLoad() reset(listener) mediaDataManager.onNotificationAdded(KEY, mediaNotification) testScope.assertRunAllReady(foreground = 1, background = 1) verify(listener) .onMediaDataLoaded( eq(KEY), eq(KEY), capture(mediaDataCaptor), eq(true), eq(0), eq(false) ) verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY)) } private fun TestScope.assertRunAllReady(foreground: Int = 0, background: Int = 0) { runCurrent() if (Flags.mediaLoadMetadataViaMediaDataLoader()) { Loading Loading
packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt +92 −74 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ import com.android.systemui.dump.DumpManager import com.android.systemui.media.controls.domain.pipeline.MediaDataManager.Companion.isMediaNotification import com.android.systemui.media.controls.domain.resume.MediaResumeListener import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser import com.android.systemui.media.controls.shared.MediaLogger import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_SOURCE import com.android.systemui.media.controls.shared.model.EXTRA_VALUE_TRIGGER_PERIODIC import com.android.systemui.media.controls.shared.model.MediaAction Loading @@ -84,7 +85,7 @@ import com.android.systemui.media.controls.util.MediaControllerFactory import com.android.systemui.media.controls.util.MediaDataUtils import com.android.systemui.media.controls.util.MediaFlags import com.android.systemui.media.controls.util.MediaUiEventLogger import com.android.systemui.plugins.ActivityStarter import com.android.systemui.media.controls.util.SmallHash import com.android.systemui.plugins.BcSmartspaceDataPlugin import com.android.systemui.res.R import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState Loading Loading @@ -186,7 +187,6 @@ class LegacyMediaDataManagerImpl( private val mediaDeviceManager: MediaDeviceManager, mediaDataCombineLatest: MediaDataCombineLatest, private val mediaDataFilter: LegacyMediaDataFilterImpl, private val activityStarter: ActivityStarter, private val smartspaceMediaDataProvider: SmartspaceMediaDataProvider, private var useMediaResumption: Boolean, private val useQsMediaPlayer: Boolean, Loading @@ -197,6 +197,7 @@ class LegacyMediaDataManagerImpl( private val smartspaceManager: SmartspaceManager?, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val mediaDataLoader: dagger.Lazy<MediaDataLoader>, private val mediaLogger: MediaLogger, ) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener, MediaDataManager { companion object { Loading Loading @@ -273,7 +274,6 @@ class LegacyMediaDataManagerImpl( mediaDeviceManager: MediaDeviceManager, mediaDataCombineLatest: MediaDataCombineLatest, mediaDataFilter: LegacyMediaDataFilterImpl, activityStarter: ActivityStarter, smartspaceMediaDataProvider: SmartspaceMediaDataProvider, clock: SystemClock, tunerService: TunerService, Loading @@ -282,6 +282,7 @@ class LegacyMediaDataManagerImpl( smartspaceManager: SmartspaceManager?, keyguardUpdateMonitor: KeyguardUpdateMonitor, mediaDataLoader: dagger.Lazy<MediaDataLoader>, mediaLogger: MediaLogger, ) : this( context, // Loading bitmap for UMO background can take longer time, so it cannot run on the default Loading @@ -301,7 +302,6 @@ class LegacyMediaDataManagerImpl( mediaDeviceManager, mediaDataCombineLatest, mediaDataFilter, activityStarter, smartspaceMediaDataProvider, Utils.useMediaResumption(context), Utils.useQsMediaPlayer(context), Loading @@ -312,6 +312,7 @@ class LegacyMediaDataManagerImpl( smartspaceManager, keyguardUpdateMonitor, mediaDataLoader, mediaLogger, ) private val appChangeReceiver = Loading Loading @@ -564,29 +565,9 @@ class LegacyMediaDataManagerImpl( val resumeAction: Runnable? = currentEntry?.resumeAction val hasCheckedForResume = currentEntry?.hasCheckedForResume == true val active = currentEntry?.active ?: true val mediaController = mediaControllerFactory.create(result.token!!) // We need to log the correct media added. if (isNewlyActiveEntry) { logSingleVsMultipleMediaAdded(result.appUid, sbn.packageName, instanceId) logger.logActiveMediaAdded( result.appUid, sbn.packageName, instanceId, result.playbackLocation ) } else if (result.playbackLocation != currentEntry?.playbackLocation) { logger.logPlaybackLocationChange( result.appUid, sbn.packageName, instanceId, result.playbackLocation ) } withContext(mainDispatcher) { onMediaDataLoaded( key, oldKey, val mediaData = MediaData( userId = sbn.normalizedUserId, initialized = true, Loading Loading @@ -615,8 +596,31 @@ class LegacyMediaDataManagerImpl( appUid = result.appUid, isExplicit = result.isExplicit, ) if (isSameMediaData(context, mediaController, mediaData, currentEntry)) { mediaLogger.logDuplicateMediaNotification(key) return@withContext } // We need to log the correct media added. if (isNewlyActiveEntry) { logSingleVsMultipleMediaAdded(result.appUid, sbn.packageName, instanceId) logger.logActiveMediaAdded( result.appUid, sbn.packageName, instanceId, result.playbackLocation ) } else if (result.playbackLocation != currentEntry?.playbackLocation) { logger.logPlaybackLocationChange( result.appUid, sbn.packageName, instanceId, result.playbackLocation ) } withContext(mainDispatcher) { onMediaDataLoaded(key, oldKey, mediaData) } } /** Add a listener for changes in this class */ Loading Loading @@ -1100,22 +1104,12 @@ class LegacyMediaDataManagerImpl( val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId() val appUid = appInfo?.uid ?: Process.INVALID_UID if (isNewlyActiveEntry) { logSingleVsMultipleMediaAdded(appUid, sbn.packageName, instanceId) logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation) } else if (playbackLocation != currentEntry?.playbackLocation) { logger.logPlaybackLocationChange(appUid, sbn.packageName, instanceId, playbackLocation) } val lastActive = systemClock.elapsedRealtime() val createdTimestampMillis = currentEntry?.createdTimestampMillis ?: 0L foregroundExecutor.execute { val resumeAction: Runnable? = mediaEntries[key]?.resumeAction val hasCheckedForResume = mediaEntries[key]?.hasCheckedForResume == true val active = mediaEntries[key]?.active ?: true onMediaDataLoaded( key, oldKey, var mediaData = MediaData( sbn.normalizedUserId, true, Loading Loading @@ -1143,8 +1137,32 @@ class LegacyMediaDataManagerImpl( instanceId = instanceId, appUid = appUid, isExplicit = isExplicit, smartspaceId = SmallHash.hash(appUid + systemClock.currentTimeMillis().toInt()), ) if (isSameMediaData(context, mediaController, mediaData, currentEntry)) { mediaLogger.logDuplicateMediaNotification(key) return } if (isNewlyActiveEntry) { logSingleVsMultipleMediaAdded(appUid, sbn.packageName, instanceId) logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation) } else if (playbackLocation != currentEntry?.playbackLocation) { logger.logPlaybackLocationChange(appUid, sbn.packageName, instanceId, playbackLocation) } foregroundExecutor.execute { val oldResumeAction: Runnable? = mediaEntries[key]?.resumeAction val oldHasCheckedForResume = mediaEntries[key]?.hasCheckedForResume == true val oldActive = mediaEntries[key]?.active ?: true mediaData = mediaData.copy( resumeAction = oldResumeAction, hasCheckedForResume = oldHasCheckedForResume, active = oldActive ) onMediaDataLoaded(key, oldKey, mediaData) } } Loading
packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt +24 −10 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import androidx.annotation.WorkerThread import androidx.core.view.GestureDetectorCompat import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.android.systemui.Flags import com.android.systemui.classifier.Classifier.MEDIA_SEEKBAR import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.plugins.FalsingManager Loading Loading @@ -102,9 +103,11 @@ constructor( } _progress.postValue(value) } private val _progress = MutableLiveData<Progress>().apply { postValue(_data) } val progress: LiveData<Progress> get() = _progress private var controller: MediaController? = null set(value) { if (field?.sessionToken != value?.sessionToken) { Loading @@ -113,6 +116,7 @@ constructor( field = value } } private var playbackState: PlaybackState? = null private var callback = object : MediaController.Callback() { Loading @@ -128,6 +132,15 @@ constructor( override fun onSessionDestroyed() { clearController() } override fun onMetadataChanged(metadata: MediaMetadata?) { if (!Flags.mediaControlsPostsOptimization()) return val (enabled, duration) = getEnabledStateAndDuration(metadata) if (_data.duration != duration) { _data = _data.copy(enabled = enabled, duration = duration) } } } private var cancel: Runnable? = null Loading Loading @@ -233,22 +246,13 @@ constructor( fun updateController(mediaController: MediaController?) { controller = mediaController playbackState = controller?.playbackState val mediaMetadata = controller?.metadata val (enabled, duration) = getEnabledStateAndDuration(controller?.metadata) val seekAvailable = ((playbackState?.actions ?: 0L) and PlaybackState.ACTION_SEEK_TO) != 0L val position = playbackState?.position?.toInt() val duration = mediaMetadata?.getLong(MediaMetadata.METADATA_KEY_DURATION)?.toInt() ?: 0 val playing = NotificationMediaManager.isPlayingState( playbackState?.state ?: PlaybackState.STATE_NONE ) val enabled = if ( playbackState == null || playbackState?.getState() == PlaybackState.STATE_NONE || (duration <= 0) ) false else true _data = Progress(enabled, seekAvailable, playing, scrubbing, position, duration, listening) checkIfPollingNeeded() } Loading Loading @@ -368,6 +372,16 @@ constructor( } } /** returns a pair of whether seekbar is enabled and the duration of media. */ private fun getEnabledStateAndDuration(metadata: MediaMetadata?): Pair<Boolean, Int> { val duration = metadata?.getLong(MediaMetadata.METADATA_KEY_DURATION)?.toInt() ?: 0 val enabled = !(playbackState == null || playbackState?.state == PlaybackState.STATE_NONE || (duration <= 0)) return Pair(enabled, duration) } /** * This method specifies if user made a bad seekbar grab or not. If the vertical distance from * first touch on seekbar is more than the horizontal distance, this means that the seekbar grab Loading
packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt +45 −4 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ import android.media.session.MediaSession import android.media.session.PlaybackState import android.net.Uri import android.os.Bundle import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization import android.provider.Settings import android.service.notification.StatusBarNotification Loading @@ -61,6 +63,8 @@ import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.media.controls.domain.resume.MediaResumeListener import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser import com.android.systemui.media.controls.shared.mediaLogger import com.android.systemui.media.controls.shared.mockMediaLogger import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_SOURCE import com.android.systemui.media.controls.shared.model.EXTRA_VALUE_TRIGGER_PERIODIC import com.android.systemui.media.controls.shared.model.MediaData Loading @@ -69,7 +73,6 @@ import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvi import com.android.systemui.media.controls.util.MediaUiEventLogger import com.android.systemui.media.controls.util.fakeMediaControllerFactory import com.android.systemui.media.controls.util.mediaFlags import com.android.systemui.plugins.activityStarter import com.android.systemui.res.R import com.android.systemui.statusbar.SbnBuilder import com.android.systemui.testKosmos Loading Loading @@ -186,11 +189,10 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa mSetFlagsRule.setFlagsParameterization(flags) } private val kosmos = testKosmos() private val kosmos = testKosmos().apply { mediaLogger = mockMediaLogger } private val testDispatcher = kosmos.testDispatcher private val testScope = kosmos.testScope private val fakeFeatureFlags = kosmos.fakeFeatureFlagsClassic private val activityStarter = kosmos.activityStarter private val mediaControllerFactory = kosmos.fakeMediaControllerFactory private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20) Loading Loading @@ -240,7 +242,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa mediaDeviceManager = mediaDeviceManager, mediaDataCombineLatest = mediaDataCombineLatest, mediaDataFilter = mediaDataFilter, activityStarter = activityStarter, smartspaceMediaDataProvider = smartspaceMediaDataProvider, useMediaResumption = true, useQsMediaPlayer = true, Loading @@ -251,6 +252,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa smartspaceManager = smartspaceManager, keyguardUpdateMonitor = keyguardUpdateMonitor, mediaDataLoader = { kosmos.mediaDataLoader }, mediaLogger = kosmos.mediaLogger, ) verify(tunerService) .addTunable(capture(tunableCaptor), eq(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION)) Loading Loading @@ -2404,6 +2406,45 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa assertThat(mediaDataCaptor.value.artwork).isNull() } @Test @EnableFlags(Flags.FLAG_MEDIA_CONTROLS_POSTS_OPTIMIZATION) fun postDuplicateNotification_doesNotCallListeners() { addNotificationAndLoad() reset(listener) mediaDataManager.onNotificationAdded(KEY, mediaNotification) testScope.assertRunAllReady(foreground = 0, background = 1) verify(listener, never()) .onMediaDataLoaded( eq(KEY), eq(KEY), capture(mediaDataCaptor), eq(true), eq(0), eq(false) ) verify(kosmos.mediaLogger).logDuplicateMediaNotification(eq(KEY)) } @Test @DisableFlags(Flags.FLAG_MEDIA_CONTROLS_POSTS_OPTIMIZATION) fun postDuplicateNotification_callsListeners() { addNotificationAndLoad() reset(listener) mediaDataManager.onNotificationAdded(KEY, mediaNotification) testScope.assertRunAllReady(foreground = 1, background = 1) verify(listener) .onMediaDataLoaded( eq(KEY), eq(KEY), capture(mediaDataCaptor), eq(true), eq(0), eq(false) ) verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY)) } private fun TestScope.assertRunAllReady(foreground: Int = 0, background: Int = 0) { runCurrent() if (Flags.mediaLoadMetadataViaMediaDataLoader()) { Loading