Loading packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +25 −12 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ class MediaCarouselController @Inject constructor( private val mediaHostStatesManager: MediaHostStatesManager, private val activityStarter: ActivityStarter, @Main executor: DelayableExecutor, mediaManager: MediaDataManager, private val mediaManager: MediaDataManager, configurationController: ConfigurationController, falsingManager: FalsingManager ) { Loading Loading @@ -110,6 +110,7 @@ class MediaCarouselController @Inject constructor( private val pageIndicator: PageIndicator private val visualStabilityCallback: VisualStabilityManager.Callback private var needsReordering: Boolean = false private var keysNeedRemoval = mutableSetOf<String>() private var isRtl: Boolean = false set(value) { if (value != field) { Loading Loading @@ -161,6 +162,10 @@ class MediaCarouselController @Inject constructor( needsReordering = false reorderAllPlayers() } keysNeedRemoval.forEach { removePlayer(it) } keysNeedRemoval.clear() // Let's reset our scroll position mediaCarouselScrollHandler.scrollToStart() } Loading @@ -168,13 +173,19 @@ class MediaCarouselController @Inject constructor( true /* persistent */) mediaManager.addListener(object : MediaDataManager.Listener { override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) { if (!data.active && !Utils.useMediaResumption(context)) { // This view is inactive, let's remove this! This happens e.g when dismissing / // timing out a view. We still have the data around because resumption could // be on, but we should save the resources and release this. addOrUpdatePlayer(key, oldKey, data) val canRemove = data.isPlaying?.let { !it } ?: data.isClearable if (canRemove && !Utils.useMediaResumption(context)) { // This view isn't playing, let's remove this! This happens e.g when // dismissing/timing out a view. We still have the data around because // resumption could be on, but we should save the resources and release this. if (visualStabilityManager.isReorderingAllowed) { onMediaDataRemoved(key) } else { addOrUpdatePlayer(key, oldKey, data) keysNeedRemoval.add(key) } } else { keysNeedRemoval.remove(key) } } Loading Loading @@ -236,12 +247,12 @@ class MediaCarouselController @Inject constructor( var newPlayer = mediaControlPanelFactory.get() newPlayer.attach(PlayerViewHolder.create(LayoutInflater.from(context), mediaContent)) newPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions MediaPlayerData.addMediaPlayer(key, data, newPlayer) val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) newPlayer.view?.player?.setLayoutParams(lp) newPlayer.bind(data) newPlayer.setListening(currentlyExpanded) MediaPlayerData.addMediaPlayer(key, data, newPlayer) updatePlayerToState(newPlayer, noAnimation = true) reorderAllPlayers() } else { Loading Loading @@ -271,6 +282,9 @@ class MediaCarouselController @Inject constructor( removed.onDestroy() mediaCarouselScrollHandler.onPlayersChanged() updatePageIndicator() // Inform the media manager of a potentially late dismissal mediaManager.dismissMediaData(key, 0L) } } Loading Loading @@ -478,12 +492,11 @@ class MediaCarouselController @Inject constructor( internal object MediaPlayerData { private data class MediaSortKey( val data: MediaData, val updateTime: Long = 0, val isPlaying: Boolean = false val updateTime: Long = 0 ) private val comparator = compareByDescending<MediaSortKey> { it.isPlaying } compareByDescending<MediaSortKey> { it.data.isPlaying } .thenByDescending { it.data.isLocalSession } .thenByDescending { !it.data.resumption } .thenByDescending { it.updateTime } Loading @@ -493,7 +506,7 @@ internal object MediaPlayerData { fun addMediaPlayer(key: String, data: MediaData, player: MediaControlPanel) { removeMediaPlayer(key) val sortKey = MediaSortKey(data, System.currentTimeMillis(), player.isPlaying()) val sortKey = MediaSortKey(data, System.currentTimeMillis()) mediaData.put(key, sortKey) mediaPlayers.put(sortKey, player) } Loading packages/SystemUI/src/com/android/systemui/media/MediaData.kt +11 −1 Original line number Diff line number Diff line Loading @@ -94,7 +94,17 @@ data class MediaData( * Notification key for cancelling a media player after a timeout (when not using resumption.) */ val notificationKey: String? = null, var hasCheckedForResume: Boolean = false var hasCheckedForResume: Boolean = false, /** * If apps do not report PlaybackState, set as null to imply 'undetermined' */ val isPlaying: Boolean? = null, /** * Set from the notification and used as fallback when PlaybackState cannot be determined */ val isClearable: Boolean = true ) /** State of a media action. */ Loading packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt +1 −7 Original line number Diff line number Diff line Loading @@ -136,14 +136,8 @@ class MediaDataFilter @Inject constructor( /** * Are there any media entries we should display? * If resumption is enabled, this will include inactive players * If resumption is disabled, we only want to show active players */ fun hasAnyMedia() = if (mediaResumeListener.isResumptionEnabled()) { userEntries.isNotEmpty() } else { hasActiveMedia() } fun hasAnyMedia() = userEntries.isNotEmpty() /** * Add a listener for filtered [MediaData] changes Loading packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +14 −1 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState import com.android.systemui.statusbar.notification.MediaNotificationProcessor import com.android.systemui.statusbar.notification.row.HybridGroupManager import com.android.systemui.util.Assert Loading Loading @@ -336,6 +337,16 @@ class MediaDataManager( } fun dismissMediaData(key: String, delay: Long) { backgroundExecutor.execute { mediaEntries[key]?.let { mediaData -> if (mediaData.isLocalSession) { mediaData.token?.let { val mediaController = mediaControllerFactory.create(it) mediaController.transportControls.stop() } } } } foregroundExecutor.executeDelayed({ removeEntry(key) }, delay) } Loading Loading @@ -483,6 +494,7 @@ class MediaDataManager( val isLocalSession = mediaController.playbackInfo?.playbackType == MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL ?: true val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null foregroundExecutor.execute { val resumeAction: Runnable? = mediaEntries[key]?.resumeAction Loading @@ -492,7 +504,8 @@ class MediaDataManager( smallIconDrawable, artist, song, artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token, notif.contentIntent, null, active, resumeAction = resumeAction, isLocalSession = isLocalSession, notificationKey = key, hasCheckedForResume = hasCheckedForResume)) notificationKey = key, hasCheckedForResume = hasCheckedForResume, isPlaying = isPlaying, isClearable = sbn.isClearable())) } } Loading packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt +0 −2 Original line number Diff line number Diff line Loading @@ -116,8 +116,6 @@ class MediaResumeListener @Inject constructor( }, Settings.Secure.MEDIA_CONTROLS_RESUME) } fun isResumptionEnabled() = useMediaResumption private fun loadSavedComponents() { // Make sure list is empty (if we switched users) resumeComponents.clear() Loading Loading
packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +25 −12 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ class MediaCarouselController @Inject constructor( private val mediaHostStatesManager: MediaHostStatesManager, private val activityStarter: ActivityStarter, @Main executor: DelayableExecutor, mediaManager: MediaDataManager, private val mediaManager: MediaDataManager, configurationController: ConfigurationController, falsingManager: FalsingManager ) { Loading Loading @@ -110,6 +110,7 @@ class MediaCarouselController @Inject constructor( private val pageIndicator: PageIndicator private val visualStabilityCallback: VisualStabilityManager.Callback private var needsReordering: Boolean = false private var keysNeedRemoval = mutableSetOf<String>() private var isRtl: Boolean = false set(value) { if (value != field) { Loading Loading @@ -161,6 +162,10 @@ class MediaCarouselController @Inject constructor( needsReordering = false reorderAllPlayers() } keysNeedRemoval.forEach { removePlayer(it) } keysNeedRemoval.clear() // Let's reset our scroll position mediaCarouselScrollHandler.scrollToStart() } Loading @@ -168,13 +173,19 @@ class MediaCarouselController @Inject constructor( true /* persistent */) mediaManager.addListener(object : MediaDataManager.Listener { override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) { if (!data.active && !Utils.useMediaResumption(context)) { // This view is inactive, let's remove this! This happens e.g when dismissing / // timing out a view. We still have the data around because resumption could // be on, but we should save the resources and release this. addOrUpdatePlayer(key, oldKey, data) val canRemove = data.isPlaying?.let { !it } ?: data.isClearable if (canRemove && !Utils.useMediaResumption(context)) { // This view isn't playing, let's remove this! This happens e.g when // dismissing/timing out a view. We still have the data around because // resumption could be on, but we should save the resources and release this. if (visualStabilityManager.isReorderingAllowed) { onMediaDataRemoved(key) } else { addOrUpdatePlayer(key, oldKey, data) keysNeedRemoval.add(key) } } else { keysNeedRemoval.remove(key) } } Loading Loading @@ -236,12 +247,12 @@ class MediaCarouselController @Inject constructor( var newPlayer = mediaControlPanelFactory.get() newPlayer.attach(PlayerViewHolder.create(LayoutInflater.from(context), mediaContent)) newPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions MediaPlayerData.addMediaPlayer(key, data, newPlayer) val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) newPlayer.view?.player?.setLayoutParams(lp) newPlayer.bind(data) newPlayer.setListening(currentlyExpanded) MediaPlayerData.addMediaPlayer(key, data, newPlayer) updatePlayerToState(newPlayer, noAnimation = true) reorderAllPlayers() } else { Loading Loading @@ -271,6 +282,9 @@ class MediaCarouselController @Inject constructor( removed.onDestroy() mediaCarouselScrollHandler.onPlayersChanged() updatePageIndicator() // Inform the media manager of a potentially late dismissal mediaManager.dismissMediaData(key, 0L) } } Loading Loading @@ -478,12 +492,11 @@ class MediaCarouselController @Inject constructor( internal object MediaPlayerData { private data class MediaSortKey( val data: MediaData, val updateTime: Long = 0, val isPlaying: Boolean = false val updateTime: Long = 0 ) private val comparator = compareByDescending<MediaSortKey> { it.isPlaying } compareByDescending<MediaSortKey> { it.data.isPlaying } .thenByDescending { it.data.isLocalSession } .thenByDescending { !it.data.resumption } .thenByDescending { it.updateTime } Loading @@ -493,7 +506,7 @@ internal object MediaPlayerData { fun addMediaPlayer(key: String, data: MediaData, player: MediaControlPanel) { removeMediaPlayer(key) val sortKey = MediaSortKey(data, System.currentTimeMillis(), player.isPlaying()) val sortKey = MediaSortKey(data, System.currentTimeMillis()) mediaData.put(key, sortKey) mediaPlayers.put(sortKey, player) } Loading
packages/SystemUI/src/com/android/systemui/media/MediaData.kt +11 −1 Original line number Diff line number Diff line Loading @@ -94,7 +94,17 @@ data class MediaData( * Notification key for cancelling a media player after a timeout (when not using resumption.) */ val notificationKey: String? = null, var hasCheckedForResume: Boolean = false var hasCheckedForResume: Boolean = false, /** * If apps do not report PlaybackState, set as null to imply 'undetermined' */ val isPlaying: Boolean? = null, /** * Set from the notification and used as fallback when PlaybackState cannot be determined */ val isClearable: Boolean = true ) /** State of a media action. */ Loading
packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt +1 −7 Original line number Diff line number Diff line Loading @@ -136,14 +136,8 @@ class MediaDataFilter @Inject constructor( /** * Are there any media entries we should display? * If resumption is enabled, this will include inactive players * If resumption is disabled, we only want to show active players */ fun hasAnyMedia() = if (mediaResumeListener.isResumptionEnabled()) { userEntries.isNotEmpty() } else { hasActiveMedia() } fun hasAnyMedia() = userEntries.isNotEmpty() /** * Add a listener for filtered [MediaData] changes Loading
packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +14 −1 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState import com.android.systemui.statusbar.notification.MediaNotificationProcessor import com.android.systemui.statusbar.notification.row.HybridGroupManager import com.android.systemui.util.Assert Loading Loading @@ -336,6 +337,16 @@ class MediaDataManager( } fun dismissMediaData(key: String, delay: Long) { backgroundExecutor.execute { mediaEntries[key]?.let { mediaData -> if (mediaData.isLocalSession) { mediaData.token?.let { val mediaController = mediaControllerFactory.create(it) mediaController.transportControls.stop() } } } } foregroundExecutor.executeDelayed({ removeEntry(key) }, delay) } Loading Loading @@ -483,6 +494,7 @@ class MediaDataManager( val isLocalSession = mediaController.playbackInfo?.playbackType == MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL ?: true val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null foregroundExecutor.execute { val resumeAction: Runnable? = mediaEntries[key]?.resumeAction Loading @@ -492,7 +504,8 @@ class MediaDataManager( smallIconDrawable, artist, song, artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token, notif.contentIntent, null, active, resumeAction = resumeAction, isLocalSession = isLocalSession, notificationKey = key, hasCheckedForResume = hasCheckedForResume)) notificationKey = key, hasCheckedForResume = hasCheckedForResume, isPlaying = isPlaying, isClearable = sbn.isClearable())) } } Loading
packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt +0 −2 Original line number Diff line number Diff line Loading @@ -116,8 +116,6 @@ class MediaResumeListener @Inject constructor( }, Settings.Secure.MEDIA_CONTROLS_RESUME) } fun isResumptionEnabled() = useMediaResumption private fun loadSavedComponents() { // Make sure list is empty (if we switched users) resumeComponents.clear() Loading