diff --git a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt index 524c6955ba4a0..4ee4ad46d4c7e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt @@ -67,5 +67,4 @@ class KeyguardMediaController @Inject constructor( statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER) view?.visibility = if (shouldBeVisible) View.VISIBLE else View.GONE } -} - +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index 90c558a1ee971..f950d41f02b17 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -65,7 +65,7 @@ class MediaDataManager @Inject constructor( private val context: Context, private val mediaControllerFactory: MediaControllerFactory, @Background private val backgroundExecutor: Executor, - @Main private val foregroundExcecutor: Executor + @Main private val foregroundExecutor: Executor ) { private val listeners: MutableSet = mutableSetOf() @@ -201,7 +201,7 @@ class MediaDataManager @Inject constructor( } } - foregroundExcecutor.execute { + foregroundExecutor.execute { onMediaDataLoaded(key, MediaData(true, bgColor, app, smallIconDrawable, artist, song, artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token, notif.contentIntent)) @@ -288,7 +288,7 @@ class MediaDataManager @Inject constructor( /** * Are there any media notifications active? */ - fun hasActiveMedia() = mediaEntries.size > 0 + fun hasActiveMedia() = mediaEntries.isNotEmpty() fun hasAnyMedia(): Boolean { // TODO: implement this when we implemented resumption diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt index 6e7b6bcb75029..240e44cb8db4b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt @@ -26,8 +26,8 @@ class MediaHost @Inject constructor( /** * Get the current Media state. This also updates the location on screen */ - val currentState : MediaState - get () { + val currentState: MediaState + get() { hostView.getLocationOnScreen(tmpLocationOnScreen) var left = tmpLocationOnScreen[0] + hostView.paddingLeft var top = tmpLocationOnScreen[1] + hostView.paddingTop @@ -37,11 +37,11 @@ class MediaHost @Inject constructor( // the above could return negative widths, which is wrong if (right < left) { left = 0 - right = 0; + right = 0 } if (bottom < top) { bottom = 0 - top = 0; + top = 0 } state.boundsOnScreen.set(left, top, right, bottom) return state @@ -64,7 +64,7 @@ class MediaHost @Inject constructor( * transitions. */ fun init(@MediaLocation location: Int) { - this.location = location; + this.location = location hostView = mediaHierarchyManager.register(this) hostView.addOnAttachStateChangeListener(object : OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View?) { @@ -95,7 +95,7 @@ class MediaHost @Inject constructor( override var showsOnlyActiveMedia: Boolean = false override val boundsOnScreen: Rect = Rect() - override fun copy() : MediaState { + override fun copy(): MediaState { val mediaHostState = MediaHostState() mediaHostState.expansion = expansion mediaHostState.showsOnlyActiveMedia = showsOnlyActiveMedia @@ -104,7 +104,7 @@ class MediaHost @Inject constructor( return mediaHostState } - override fun interpolate(other: MediaState, amount: Float) : MediaState { + override fun interpolate(other: MediaState, amount: Float): MediaState { val result = MediaHostState() result.expansion = MathUtils.lerp(expansion, other.expansion, amount) val left = MathUtils.lerp(boundsOnScreen.left.toFloat(), @@ -121,10 +121,10 @@ class MediaHost @Inject constructor( if (other is MediaHostState) { result.measurementInput = other.measurementInput } - } else { + } else { result.measurementInput } - return result + return result } override fun getMeasuringInput(input: MeasurementInput): MediaMeasurementInput { @@ -138,8 +138,8 @@ interface MediaState { var expansion: Float var showsOnlyActiveMedia: Boolean val boundsOnScreen: Rect - fun copy() : MediaState - fun interpolate(other: MediaState, amount: Float) : MediaState + fun copy(): MediaState + fun interpolate(other: MediaState, amount: Float): MediaState fun getMeasuringInput(input: MeasurementInput): MediaMeasurementInput } /** @@ -147,7 +147,8 @@ interface MediaState { */ data class MediaMeasurementInput( private val viewInput: MeasurementInput, - val expansion: Float) : MeasurementInput by viewInput { + val expansion: Float +) : MeasurementInput by viewInput { override fun sameAs(input: MeasurementInput?): Boolean { if (!(input is MediaMeasurementInput)) { @@ -155,5 +156,4 @@ data class MediaMeasurementInput( } return width == input.width && expansion == input.expansion } -} - +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index 9f4932e74eaae..0fa1f553c1f31 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; +import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON; import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_MEDIA_FAKE_ARTWORK; import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_WALLPAPER; import static com.android.systemui.statusbar.phone.StatusBar.SHOW_LOCKSCREEN_MEDIA_ARTWORK; @@ -44,8 +45,6 @@ import android.util.Log; import android.view.View; import android.widget.ImageView; -import androidx.annotation.NonNull; - import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.Dependency; @@ -53,7 +52,6 @@ import com.android.systemui.Dumpable; import com.android.systemui.Interpolators; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.media.MediaData; import com.android.systemui.media.MediaDataManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.dagger.StatusBarModule; @@ -70,6 +68,7 @@ import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.Utils; +import com.android.systemui.util.concurrency.DelayableExecutor; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -79,7 +78,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; import dagger.Lazy; @@ -90,6 +89,7 @@ import dagger.Lazy; public class NotificationMediaManager implements Dumpable { private static final String TAG = "NotificationMediaManager"; public static final boolean DEBUG_MEDIA = false; + private static final long PAUSED_MEDIA_TIMEOUT = TimeUnit.MINUTES.toMillis(10); private final StatusBarStateController mStatusBarStateController = Dependency.get(StatusBarStateController.class); @@ -106,6 +106,7 @@ public class NotificationMediaManager implements Dumpable { } private final NotificationEntryManager mEntryManager; + private final MediaDataManager mMediaDataManager; @Nullable private Lazy mNotificationShadeWindowController; @@ -117,7 +118,7 @@ public class NotificationMediaManager implements Dumpable { @Nullable private LockscreenWallpaper mLockscreenWallpaper; - private final Executor mMainExecutor; + private final DelayableExecutor mMainExecutor; private final Context mContext; private final MediaSessionManager mMediaSessionManager; @@ -130,6 +131,7 @@ public class NotificationMediaManager implements Dumpable { private MediaController mMediaController; private String mMediaNotificationKey; private MediaMetadata mMediaMetadata; + private Runnable mMediaTimeoutCancellation; private BackDropView mBackdrop; private ImageView mBackdropFront; @@ -159,11 +161,36 @@ public class NotificationMediaManager implements Dumpable { if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: onPlaybackStateChanged: " + state); } + if (mMediaTimeoutCancellation != null) { + mMediaTimeoutCancellation.run(); + mMediaTimeoutCancellation = null; + } if (state != null) { if (!isPlaybackActive(state.getState())) { clearCurrentMediaNotification(); } findAndUpdateMediaNotifications(); + scheduleMediaTimeout(state); + } + } + + private void scheduleMediaTimeout(PlaybackState state) { + final NotificationEntry entry; + synchronized (mEntryManager) { + entry = mEntryManager.getActiveNotificationUnfiltered(mMediaNotificationKey); + } + if (entry != null) { + if (!isPlayingState(state.getState())) { + mMediaTimeoutCancellation = mMainExecutor.executeDelayed(() -> { + synchronized (mEntryManager) { + if (mMediaNotificationKey == null) { + return; + } + mEntryManager.removeNotification(mMediaNotificationKey, null, + UNDEFINED_DISMISS_REASON); + } + }, PAUSED_MEDIA_TIMEOUT); + } } } @@ -189,7 +216,7 @@ public class NotificationMediaManager implements Dumpable { NotificationEntryManager notificationEntryManager, MediaArtworkProcessor mediaArtworkProcessor, KeyguardBypassController keyguardBypassController, - @Main Executor mainExecutor, + @Main DelayableExecutor mainExecutor, DeviceConfigProxy deviceConfig, MediaDataManager mediaDataManager) { mContext = context; @@ -205,6 +232,7 @@ public class NotificationMediaManager implements Dumpable { mNotificationShadeWindowController = notificationShadeWindowController; mEntryManager = notificationEntryManager; mMainExecutor = mainExecutor; + mMediaDataManager = mediaDataManager; notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java index f0fed13114ba8..1a7bbe37290a3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java @@ -46,6 +46,7 @@ import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.RemoteInputUriController; import com.android.systemui.tracing.ProtoTracer; import com.android.systemui.util.DeviceConfigProxy; +import com.android.systemui.util.concurrency.DelayableExecutor; import java.util.concurrent.Executor; @@ -95,7 +96,7 @@ public interface StatusBarDependenciesModule { NotificationEntryManager notificationEntryManager, MediaArtworkProcessor mediaArtworkProcessor, KeyguardBypassController keyguardBypassController, - @Main Executor mainExecutor, + @Main DelayableExecutor mainExecutor, DeviceConfigProxy deviceConfigProxy, MediaDataManager mediaDataManager) { return new NotificationMediaManager(