Loading packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt +0 −2 Original line number Diff line number Diff line Loading @@ -41,7 +41,6 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.media.controls.shared.model.MediaData 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 @@ -86,7 +85,6 @@ class MediaDataLoaderTest : SysuiTestCase() { context, testDispatcher, testScope, kosmos.activityStarter, mediaControllerFactory, mediaFlags, kosmos.imageLoader, Loading packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt +6 −5 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import com.android.systemui.media.controls.shared.model.MediaAction import com.android.systemui.media.controls.shared.model.MediaButton import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.media.controls.shared.model.MediaDeviceData import com.android.systemui.media.controls.shared.model.MediaNotificationAction import com.android.systemui.media.controls.shared.model.SmartspaceMediaData import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvider import com.android.systemui.media.controls.ui.view.MediaViewHolder Loading Loading @@ -943,7 +944,7 @@ class LegacyMediaDataManagerImpl( desc.subtitle, desc.title, artworkIcon, listOf(mediaAction), listOf(), listOf(0), MediaButton(playOrPause = mediaAction), packageName, Loading Loading @@ -1074,13 +1075,13 @@ class LegacyMediaDataManagerImpl( } // Control buttons // If flag is enabled and controller has a PlaybackState, create actions from session info // If controller has a PlaybackState, create actions from session info // Otherwise, use the notification actions var actionIcons: List<MediaAction> = emptyList() var actionIcons: List<MediaNotificationAction> = emptyList() var actionsToShowCollapsed: List<Int> = emptyList() val semanticActions = createActionsFromState(sbn.packageName, mediaController, sbn.user) if (semanticActions == null) { val actions = createActionsFromNotification(context, activityStarter, sbn) val actions = createActionsFromNotification(context, sbn) actionIcons = actions.first actionsToShowCollapsed = actions.second } Loading Loading @@ -1464,7 +1465,7 @@ class LegacyMediaDataManagerImpl( val updated = data.copy( token = null, actions = actions, actions = listOf(), semanticActions = MediaButton(playOrPause = resumeAction), actionsToShowInCompact = listOf(0), active = false, Loading packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaActions.kt +44 −23 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import com.android.systemui.media.controls.domain.pipeline.LegacyMediaDataManage import com.android.systemui.media.controls.shared.MediaControlDrawables import com.android.systemui.media.controls.shared.model.MediaAction import com.android.systemui.media.controls.shared.model.MediaButton import com.android.systemui.media.controls.shared.model.MediaNotificationAction import com.android.systemui.plugins.ActivityStarter import com.android.systemui.res.R import com.android.systemui.statusbar.NotificationMediaManager.isConnectingState Loading Loading @@ -217,11 +218,10 @@ private fun includesAction(stateActions: Long, @PlaybackState.Actions action: Lo /** Generate action buttons based on notification actions */ fun createActionsFromNotification( context: Context, activityStarter: ActivityStarter, sbn: StatusBarNotification ): Pair<List<MediaAction>, List<Int>> { ): Pair<List<MediaNotificationAction>, List<Int>> { val notif = sbn.notification val actionIcons: MutableList<MediaAction> = ArrayList() val actionIcons: MutableList<MediaNotificationAction> = ArrayList() val actions = notif.actions var actionsToShowCollapsed = notif.extras.getIntArray(Notification.EXTRA_COMPACT_ACTIONS)?.toMutableList() Loading Loading @@ -250,25 +250,6 @@ fun createActionsFromNotification( continue } val runnable = action.actionIntent?.let { actionIntent -> Runnable { when { actionIntent.isActivity -> activityStarter.startPendingIntentDismissingKeyguard( action.actionIntent ) action.isAuthenticationRequired -> activityStarter.dismissKeyguardThenExecute( { sendPendingIntent(action.actionIntent) }, {}, true ) else -> sendPendingIntent(actionIntent) } } } val themeText = com.android.settingslib.Utils.getColorAttr( context, Loading @@ -285,13 +266,53 @@ fun createActionsFromNotification( .setTint(themeText) .loadDrawable(context) val mediaAction = MediaAction(mediaActionIcon, runnable, action.title, null) val mediaAction = MediaNotificationAction( action.isAuthenticationRequired, action.actionIntent, mediaActionIcon, action.title ) actionIcons.add(mediaAction) } } return Pair(actionIcons, actionsToShowCollapsed) } /** * Converts [MediaNotificationAction] list into [MediaAction] list * * @param actions list of [MediaNotificationAction] * @param activityStarter starter for activities * @return list of [MediaAction] */ fun getNotificationActions( actions: List<MediaNotificationAction>, activityStarter: ActivityStarter ): List<MediaAction> { return actions.map { action -> val runnable = action.actionIntent?.let { actionIntent -> Runnable { when { actionIntent.isActivity -> activityStarter.startPendingIntentDismissingKeyguard( action.actionIntent ) action.isAuthenticationRequired -> activityStarter.dismissKeyguardThenExecute( { sendPendingIntent(action.actionIntent) }, {}, true ) else -> sendPendingIntent(actionIntent) } } } MediaAction(action.icon, runnable, action.contentDescription, background = null) } } private fun sendPendingIntent(intent: PendingIntent): Boolean { return try { intent.send( Loading packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt +6 −8 Original line number Diff line number Diff line Loading @@ -54,10 +54,10 @@ import com.android.systemui.media.controls.shared.model.MediaAction import com.android.systemui.media.controls.shared.model.MediaButton import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.media.controls.shared.model.MediaDeviceData import com.android.systemui.media.controls.shared.model.MediaNotificationAction 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.plugins.ActivityStarter import com.android.systemui.res.R import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState import com.android.systemui.statusbar.notification.row.HybridGroupManager Loading @@ -80,7 +80,6 @@ constructor( @Application val context: Context, @Main val mainDispatcher: CoroutineDispatcher, @Background val backgroundScope: CoroutineScope, private val activityStarter: ActivityStarter, private val mediaControllerFactory: MediaControllerFactory, private val mediaFlags: MediaFlags, private val imageLoader: ImageLoader, Loading Loading @@ -209,15 +208,14 @@ constructor( val device: MediaDeviceData? = getDeviceInfoForRemoteCast(key, sbn) // Control buttons // If flag is enabled and controller has a PlaybackState, create actions from session // info // If controller has a PlaybackState, create actions from session info // Otherwise, use the notification actions var actionIcons: List<MediaAction> = emptyList() var actionIcons: List<MediaNotificationAction> = emptyList() var actionsToShowCollapsed: List<Int> = emptyList() val semanticActions = createActionsFromState(sbn.packageName, mediaController, sbn.user) logD(TAG) { "Semantic actions: $semanticActions" } if (semanticActions == null) { val actions = createActionsFromNotification(context, activityStarter, sbn) val actions = createActionsFromNotification(context, sbn) actionIcons = actions.first actionsToShowCollapsed = actions.second logD(TAG) { "[!!] Semantic actions: $semanticActions" } Loading Loading @@ -329,7 +327,7 @@ constructor( artist = desc.subtitle, song = desc.title, artworkIcon = artworkIcon, actionIcons = listOf(mediaAction), actionIcons = listOf(), actionsToShowInCompact = listOf(0), semanticActions = MediaButton(playOrPause = mediaAction), token = token, Loading Loading @@ -514,7 +512,7 @@ constructor( val artist: CharSequence?, val song: CharSequence?, val artworkIcon: Icon?, val actionIcons: List<MediaAction>, val actionIcons: List<MediaNotificationAction>, val actionsToShowInCompact: List<Int>, val semanticActions: MediaButton?, val token: MediaSession.Token?, Loading packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt +109 −86 Original line number Diff line number Diff line Loading @@ -71,12 +71,14 @@ import com.android.systemui.media.controls.data.repository.MediaDataRepository import com.android.systemui.media.controls.domain.pipeline.MediaDataManager.Companion.isMediaNotification import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor 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 import com.android.systemui.media.controls.shared.model.MediaButton import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.media.controls.shared.model.MediaDeviceData import com.android.systemui.media.controls.shared.model.MediaNotificationAction import com.android.systemui.media.controls.shared.model.SmartspaceMediaData import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvider import com.android.systemui.media.controls.ui.view.MediaViewHolder Loading Loading @@ -149,6 +151,7 @@ class MediaDataProcessor( private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val mediaDataRepository: MediaDataRepository, private val mediaDataLoader: dagger.Lazy<MediaDataLoader>, private val mediaLogger: MediaLogger, ) : CoreStartable, BcSmartspaceDataPlugin.SmartspaceTargetListener { companion object { Loading Loading @@ -228,6 +231,7 @@ class MediaDataProcessor( keyguardUpdateMonitor: KeyguardUpdateMonitor, mediaDataRepository: MediaDataRepository, mediaDataLoader: dagger.Lazy<MediaDataLoader>, mediaLogger: MediaLogger, ) : this( context, applicationScope, Loading @@ -253,6 +257,7 @@ class MediaDataProcessor( keyguardUpdateMonitor, mediaDataRepository, mediaDataLoader, mediaLogger, ) private val appChangeReceiver = Loading Loading @@ -794,7 +799,7 @@ class MediaDataProcessor( desc.subtitle, desc.title, artworkIcon, listOf(mediaAction), listOf(), listOf(0), MediaButton(playOrPause = mediaAction), packageName, Loading Loading @@ -832,35 +837,15 @@ class MediaDataProcessor( return@withContext } val currentEntry = mediaDataRepository.mediaEntries.value[key] val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId() val createdTimestampMillis = currentEntry?.createdTimestampMillis ?: 0L val resumeAction: Runnable? = currentEntry?.resumeAction val hasCheckedForResume = currentEntry?.hasCheckedForResume == true val active = currentEntry?.active ?: true val mediaController = mediaControllerFactory.create(result.token!!) val oldEntry = mediaDataRepository.mediaEntries.value[key] val instanceId = oldEntry?.instanceId ?: logger.getNewInstanceId() val createdTimestampMillis = oldEntry?.createdTimestampMillis ?: 0L val resumeAction: Runnable? = oldEntry?.resumeAction val hasCheckedForResume = oldEntry?.hasCheckedForResume == true val active = oldEntry?.active ?: true // 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 @@ -889,8 +874,31 @@ class MediaDataProcessor( appUid = result.appUid, isExplicit = result.isExplicit, ) if (isSameMediaData(context, mediaController, mediaData, oldEntry)) { 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 != oldEntry?.playbackLocation) { logger.logPlaybackLocationChange( result.appUid, sbn.packageName, instanceId, result.playbackLocation ) } withContext(mainDispatcher) { onMediaDataLoaded(key, oldKey, mediaData) } } @Deprecated("Cleanup when media_load_metadata_via_media_data_loader is cleaned up") Loading Loading @@ -1001,13 +1009,13 @@ class MediaDataProcessor( } // Control buttons // If flag is enabled and controller has a PlaybackState, create actions from session info // If controller has a PlaybackState, create actions from session info // Otherwise, use the notification actions var actionIcons: List<MediaAction> = emptyList() var actionIcons: List<MediaNotificationAction> = emptyList() var actionsToShowCollapsed: List<Int> = emptyList() val semanticActions = createActionsFromState(sbn.packageName, mediaController, sbn.user) if (semanticActions == null) { val actions = createActionsFromNotification(context, activityStarter, sbn) val actions = createActionsFromNotification(context, sbn) actionIcons = actions.first actionsToShowCollapsed = actions.second } Loading @@ -1022,27 +1030,17 @@ class MediaDataProcessor( else MediaData.PLAYBACK_CAST_LOCAL val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } val currentEntry = mediaDataRepository.mediaEntries.value.get(key) val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId() val oldEntry = mediaDataRepository.mediaEntries.value.get(key) val instanceId = oldEntry?.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 createdTimestampMillis = oldEntry?.createdTimestampMillis ?: 0L val resumeAction: Runnable? = mediaDataRepository.mediaEntries.value[key]?.resumeAction val hasCheckedForResume = mediaDataRepository.mediaEntries.value[key]?.hasCheckedForResume == true val active = mediaDataRepository.mediaEntries.value[key]?.active ?: true onMediaDataLoaded( key, oldKey, var mediaData = MediaData( sbn.normalizedUserId, true, Loading Loading @@ -1072,7 +1070,32 @@ class MediaDataProcessor( isExplicit = isExplicit, smartspaceId = SmallHash.hash(appUid + systemClock.currentTimeMillis().toInt()), ) if (isSameMediaData(context, mediaController, mediaData, oldEntry)) { mediaLogger.logDuplicateMediaNotification(key) return } if (isNewlyActiveEntry) { logSingleVsMultipleMediaAdded(appUid, sbn.packageName, instanceId) logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation) } else if (playbackLocation != oldEntry?.playbackLocation) { logger.logPlaybackLocationChange(appUid, sbn.packageName, instanceId, playbackLocation) } foregroundExecutor.execute { val oldResumeAction: Runnable? = mediaDataRepository.mediaEntries.value[key]?.resumeAction val oldHasCheckedForResume = mediaDataRepository.mediaEntries.value[key]?.hasCheckedForResume == true val oldActive = mediaDataRepository.mediaEntries.value[key]?.active ?: true mediaData = mediaData.copy( resumeAction = oldResumeAction, hasCheckedForResume = oldHasCheckedForResume, active = oldActive ) onMediaDataLoaded(key, oldKey, mediaData) } } Loading Loading @@ -1402,7 +1425,7 @@ class MediaDataProcessor( val updated = data.copy( token = null, actions = actions, actions = listOf(), semanticActions = MediaButton(playOrPause = resumeAction), actionsToShowInCompact = listOf(0), active = false, Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt +0 −2 Original line number Diff line number Diff line Loading @@ -41,7 +41,6 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.media.controls.shared.model.MediaData 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 @@ -86,7 +85,6 @@ class MediaDataLoaderTest : SysuiTestCase() { context, testDispatcher, testScope, kosmos.activityStarter, mediaControllerFactory, mediaFlags, kosmos.imageLoader, Loading
packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt +6 −5 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import com.android.systemui.media.controls.shared.model.MediaAction import com.android.systemui.media.controls.shared.model.MediaButton import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.media.controls.shared.model.MediaDeviceData import com.android.systemui.media.controls.shared.model.MediaNotificationAction import com.android.systemui.media.controls.shared.model.SmartspaceMediaData import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvider import com.android.systemui.media.controls.ui.view.MediaViewHolder Loading Loading @@ -943,7 +944,7 @@ class LegacyMediaDataManagerImpl( desc.subtitle, desc.title, artworkIcon, listOf(mediaAction), listOf(), listOf(0), MediaButton(playOrPause = mediaAction), packageName, Loading Loading @@ -1074,13 +1075,13 @@ class LegacyMediaDataManagerImpl( } // Control buttons // If flag is enabled and controller has a PlaybackState, create actions from session info // If controller has a PlaybackState, create actions from session info // Otherwise, use the notification actions var actionIcons: List<MediaAction> = emptyList() var actionIcons: List<MediaNotificationAction> = emptyList() var actionsToShowCollapsed: List<Int> = emptyList() val semanticActions = createActionsFromState(sbn.packageName, mediaController, sbn.user) if (semanticActions == null) { val actions = createActionsFromNotification(context, activityStarter, sbn) val actions = createActionsFromNotification(context, sbn) actionIcons = actions.first actionsToShowCollapsed = actions.second } Loading Loading @@ -1464,7 +1465,7 @@ class LegacyMediaDataManagerImpl( val updated = data.copy( token = null, actions = actions, actions = listOf(), semanticActions = MediaButton(playOrPause = resumeAction), actionsToShowInCompact = listOf(0), active = false, Loading
packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaActions.kt +44 −23 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import com.android.systemui.media.controls.domain.pipeline.LegacyMediaDataManage import com.android.systemui.media.controls.shared.MediaControlDrawables import com.android.systemui.media.controls.shared.model.MediaAction import com.android.systemui.media.controls.shared.model.MediaButton import com.android.systemui.media.controls.shared.model.MediaNotificationAction import com.android.systemui.plugins.ActivityStarter import com.android.systemui.res.R import com.android.systemui.statusbar.NotificationMediaManager.isConnectingState Loading Loading @@ -217,11 +218,10 @@ private fun includesAction(stateActions: Long, @PlaybackState.Actions action: Lo /** Generate action buttons based on notification actions */ fun createActionsFromNotification( context: Context, activityStarter: ActivityStarter, sbn: StatusBarNotification ): Pair<List<MediaAction>, List<Int>> { ): Pair<List<MediaNotificationAction>, List<Int>> { val notif = sbn.notification val actionIcons: MutableList<MediaAction> = ArrayList() val actionIcons: MutableList<MediaNotificationAction> = ArrayList() val actions = notif.actions var actionsToShowCollapsed = notif.extras.getIntArray(Notification.EXTRA_COMPACT_ACTIONS)?.toMutableList() Loading Loading @@ -250,25 +250,6 @@ fun createActionsFromNotification( continue } val runnable = action.actionIntent?.let { actionIntent -> Runnable { when { actionIntent.isActivity -> activityStarter.startPendingIntentDismissingKeyguard( action.actionIntent ) action.isAuthenticationRequired -> activityStarter.dismissKeyguardThenExecute( { sendPendingIntent(action.actionIntent) }, {}, true ) else -> sendPendingIntent(actionIntent) } } } val themeText = com.android.settingslib.Utils.getColorAttr( context, Loading @@ -285,13 +266,53 @@ fun createActionsFromNotification( .setTint(themeText) .loadDrawable(context) val mediaAction = MediaAction(mediaActionIcon, runnable, action.title, null) val mediaAction = MediaNotificationAction( action.isAuthenticationRequired, action.actionIntent, mediaActionIcon, action.title ) actionIcons.add(mediaAction) } } return Pair(actionIcons, actionsToShowCollapsed) } /** * Converts [MediaNotificationAction] list into [MediaAction] list * * @param actions list of [MediaNotificationAction] * @param activityStarter starter for activities * @return list of [MediaAction] */ fun getNotificationActions( actions: List<MediaNotificationAction>, activityStarter: ActivityStarter ): List<MediaAction> { return actions.map { action -> val runnable = action.actionIntent?.let { actionIntent -> Runnable { when { actionIntent.isActivity -> activityStarter.startPendingIntentDismissingKeyguard( action.actionIntent ) action.isAuthenticationRequired -> activityStarter.dismissKeyguardThenExecute( { sendPendingIntent(action.actionIntent) }, {}, true ) else -> sendPendingIntent(actionIntent) } } } MediaAction(action.icon, runnable, action.contentDescription, background = null) } } private fun sendPendingIntent(intent: PendingIntent): Boolean { return try { intent.send( Loading
packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt +6 −8 Original line number Diff line number Diff line Loading @@ -54,10 +54,10 @@ import com.android.systemui.media.controls.shared.model.MediaAction import com.android.systemui.media.controls.shared.model.MediaButton import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.media.controls.shared.model.MediaDeviceData import com.android.systemui.media.controls.shared.model.MediaNotificationAction 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.plugins.ActivityStarter import com.android.systemui.res.R import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState import com.android.systemui.statusbar.notification.row.HybridGroupManager Loading @@ -80,7 +80,6 @@ constructor( @Application val context: Context, @Main val mainDispatcher: CoroutineDispatcher, @Background val backgroundScope: CoroutineScope, private val activityStarter: ActivityStarter, private val mediaControllerFactory: MediaControllerFactory, private val mediaFlags: MediaFlags, private val imageLoader: ImageLoader, Loading Loading @@ -209,15 +208,14 @@ constructor( val device: MediaDeviceData? = getDeviceInfoForRemoteCast(key, sbn) // Control buttons // If flag is enabled and controller has a PlaybackState, create actions from session // info // If controller has a PlaybackState, create actions from session info // Otherwise, use the notification actions var actionIcons: List<MediaAction> = emptyList() var actionIcons: List<MediaNotificationAction> = emptyList() var actionsToShowCollapsed: List<Int> = emptyList() val semanticActions = createActionsFromState(sbn.packageName, mediaController, sbn.user) logD(TAG) { "Semantic actions: $semanticActions" } if (semanticActions == null) { val actions = createActionsFromNotification(context, activityStarter, sbn) val actions = createActionsFromNotification(context, sbn) actionIcons = actions.first actionsToShowCollapsed = actions.second logD(TAG) { "[!!] Semantic actions: $semanticActions" } Loading Loading @@ -329,7 +327,7 @@ constructor( artist = desc.subtitle, song = desc.title, artworkIcon = artworkIcon, actionIcons = listOf(mediaAction), actionIcons = listOf(), actionsToShowInCompact = listOf(0), semanticActions = MediaButton(playOrPause = mediaAction), token = token, Loading Loading @@ -514,7 +512,7 @@ constructor( val artist: CharSequence?, val song: CharSequence?, val artworkIcon: Icon?, val actionIcons: List<MediaAction>, val actionIcons: List<MediaNotificationAction>, val actionsToShowInCompact: List<Int>, val semanticActions: MediaButton?, val token: MediaSession.Token?, Loading
packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt +109 −86 Original line number Diff line number Diff line Loading @@ -71,12 +71,14 @@ import com.android.systemui.media.controls.data.repository.MediaDataRepository import com.android.systemui.media.controls.domain.pipeline.MediaDataManager.Companion.isMediaNotification import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor 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 import com.android.systemui.media.controls.shared.model.MediaButton import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.media.controls.shared.model.MediaDeviceData import com.android.systemui.media.controls.shared.model.MediaNotificationAction import com.android.systemui.media.controls.shared.model.SmartspaceMediaData import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvider import com.android.systemui.media.controls.ui.view.MediaViewHolder Loading Loading @@ -149,6 +151,7 @@ class MediaDataProcessor( private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val mediaDataRepository: MediaDataRepository, private val mediaDataLoader: dagger.Lazy<MediaDataLoader>, private val mediaLogger: MediaLogger, ) : CoreStartable, BcSmartspaceDataPlugin.SmartspaceTargetListener { companion object { Loading Loading @@ -228,6 +231,7 @@ class MediaDataProcessor( keyguardUpdateMonitor: KeyguardUpdateMonitor, mediaDataRepository: MediaDataRepository, mediaDataLoader: dagger.Lazy<MediaDataLoader>, mediaLogger: MediaLogger, ) : this( context, applicationScope, Loading @@ -253,6 +257,7 @@ class MediaDataProcessor( keyguardUpdateMonitor, mediaDataRepository, mediaDataLoader, mediaLogger, ) private val appChangeReceiver = Loading Loading @@ -794,7 +799,7 @@ class MediaDataProcessor( desc.subtitle, desc.title, artworkIcon, listOf(mediaAction), listOf(), listOf(0), MediaButton(playOrPause = mediaAction), packageName, Loading Loading @@ -832,35 +837,15 @@ class MediaDataProcessor( return@withContext } val currentEntry = mediaDataRepository.mediaEntries.value[key] val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId() val createdTimestampMillis = currentEntry?.createdTimestampMillis ?: 0L val resumeAction: Runnable? = currentEntry?.resumeAction val hasCheckedForResume = currentEntry?.hasCheckedForResume == true val active = currentEntry?.active ?: true val mediaController = mediaControllerFactory.create(result.token!!) val oldEntry = mediaDataRepository.mediaEntries.value[key] val instanceId = oldEntry?.instanceId ?: logger.getNewInstanceId() val createdTimestampMillis = oldEntry?.createdTimestampMillis ?: 0L val resumeAction: Runnable? = oldEntry?.resumeAction val hasCheckedForResume = oldEntry?.hasCheckedForResume == true val active = oldEntry?.active ?: true // 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 @@ -889,8 +874,31 @@ class MediaDataProcessor( appUid = result.appUid, isExplicit = result.isExplicit, ) if (isSameMediaData(context, mediaController, mediaData, oldEntry)) { 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 != oldEntry?.playbackLocation) { logger.logPlaybackLocationChange( result.appUid, sbn.packageName, instanceId, result.playbackLocation ) } withContext(mainDispatcher) { onMediaDataLoaded(key, oldKey, mediaData) } } @Deprecated("Cleanup when media_load_metadata_via_media_data_loader is cleaned up") Loading Loading @@ -1001,13 +1009,13 @@ class MediaDataProcessor( } // Control buttons // If flag is enabled and controller has a PlaybackState, create actions from session info // If controller has a PlaybackState, create actions from session info // Otherwise, use the notification actions var actionIcons: List<MediaAction> = emptyList() var actionIcons: List<MediaNotificationAction> = emptyList() var actionsToShowCollapsed: List<Int> = emptyList() val semanticActions = createActionsFromState(sbn.packageName, mediaController, sbn.user) if (semanticActions == null) { val actions = createActionsFromNotification(context, activityStarter, sbn) val actions = createActionsFromNotification(context, sbn) actionIcons = actions.first actionsToShowCollapsed = actions.second } Loading @@ -1022,27 +1030,17 @@ class MediaDataProcessor( else MediaData.PLAYBACK_CAST_LOCAL val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } val currentEntry = mediaDataRepository.mediaEntries.value.get(key) val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId() val oldEntry = mediaDataRepository.mediaEntries.value.get(key) val instanceId = oldEntry?.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 createdTimestampMillis = oldEntry?.createdTimestampMillis ?: 0L val resumeAction: Runnable? = mediaDataRepository.mediaEntries.value[key]?.resumeAction val hasCheckedForResume = mediaDataRepository.mediaEntries.value[key]?.hasCheckedForResume == true val active = mediaDataRepository.mediaEntries.value[key]?.active ?: true onMediaDataLoaded( key, oldKey, var mediaData = MediaData( sbn.normalizedUserId, true, Loading Loading @@ -1072,7 +1070,32 @@ class MediaDataProcessor( isExplicit = isExplicit, smartspaceId = SmallHash.hash(appUid + systemClock.currentTimeMillis().toInt()), ) if (isSameMediaData(context, mediaController, mediaData, oldEntry)) { mediaLogger.logDuplicateMediaNotification(key) return } if (isNewlyActiveEntry) { logSingleVsMultipleMediaAdded(appUid, sbn.packageName, instanceId) logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation) } else if (playbackLocation != oldEntry?.playbackLocation) { logger.logPlaybackLocationChange(appUid, sbn.packageName, instanceId, playbackLocation) } foregroundExecutor.execute { val oldResumeAction: Runnable? = mediaDataRepository.mediaEntries.value[key]?.resumeAction val oldHasCheckedForResume = mediaDataRepository.mediaEntries.value[key]?.hasCheckedForResume == true val oldActive = mediaDataRepository.mediaEntries.value[key]?.active ?: true mediaData = mediaData.copy( resumeAction = oldResumeAction, hasCheckedForResume = oldHasCheckedForResume, active = oldActive ) onMediaDataLoaded(key, oldKey, mediaData) } } Loading Loading @@ -1402,7 +1425,7 @@ class MediaDataProcessor( val updated = data.copy( token = null, actions = actions, actions = listOf(), semanticActions = MediaButton(playOrPause = resumeAction), actionsToShowInCompact = listOf(0), active = false, Loading