Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eddb47bf authored by Lucas Dupin's avatar Lucas Dupin Committed by Automerger Merge Worker
Browse files

Merge "Move media expiration to MediaDataManager" into rvc-dev am: 61ee50f7

Change-Id: Iadb40b425398bed0f2a5190135d25af416406727
parents 05eaedeb 61ee50f7
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -35,7 +35,8 @@ data class MediaData(
    val packageName: String?,
    val packageName: String?,
    val token: MediaSession.Token?,
    val token: MediaSession.Token?,
    val clickIntent: PendingIntent?,
    val clickIntent: PendingIntent?,
    val device: MediaDeviceData?
    val device: MediaDeviceData?,
    val notificationKey: String = "INVALID"
)
)


/** State of a media action. */
/** State of a media action. */
+21 −1
Original line number Original line Diff line number Diff line
@@ -35,6 +35,8 @@ import com.android.internal.graphics.ColorUtils
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.statusbar.notification.MediaNotificationProcessor
import com.android.systemui.statusbar.notification.MediaNotificationProcessor
import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON
import com.android.systemui.statusbar.notification.row.HybridGroupManager
import com.android.systemui.statusbar.notification.row.HybridGroupManager
import com.android.systemui.util.Assert
import com.android.systemui.util.Assert
import com.android.systemui.util.Utils
import com.android.systemui.util.Utils
@@ -77,6 +79,8 @@ fun isMediaNotification(sbn: StatusBarNotification): Boolean {
class MediaDataManager @Inject constructor(
class MediaDataManager @Inject constructor(
    private val context: Context,
    private val context: Context,
    private val mediaControllerFactory: MediaControllerFactory,
    private val mediaControllerFactory: MediaControllerFactory,
    private val mediaTimeoutListener: MediaTimeoutListener,
    private val notificationEntryManager: NotificationEntryManager,
    @Background private val backgroundExecutor: Executor,
    @Background private val backgroundExecutor: Executor,
    @Main private val foregroundExecutor: Executor
    @Main private val foregroundExecutor: Executor
) {
) {
@@ -84,6 +88,12 @@ class MediaDataManager @Inject constructor(
    private val listeners: MutableSet<Listener> = mutableSetOf()
    private val listeners: MutableSet<Listener> = mutableSetOf()
    private val mediaEntries: LinkedHashMap<String, MediaData> = LinkedHashMap()
    private val mediaEntries: LinkedHashMap<String, MediaData> = LinkedHashMap()


    init {
        mediaTimeoutListener.timeoutCallback = { token: String, timedOut: Boolean ->
            setTimedOut(token, timedOut) }
        addListener(mediaTimeoutListener)
    }

    fun onNotificationAdded(key: String, sbn: StatusBarNotification) {
    fun onNotificationAdded(key: String, sbn: StatusBarNotification) {
        if (Utils.useQsMediaPlayer(context) && isMediaNotification(sbn)) {
        if (Utils.useQsMediaPlayer(context) && isMediaNotification(sbn)) {
            Assert.isMainThread()
            Assert.isMainThread()
@@ -112,6 +122,16 @@ class MediaDataManager @Inject constructor(
     */
     */
    fun removeListener(listener: Listener) = listeners.remove(listener)
    fun removeListener(listener: Listener) = listeners.remove(listener)


    private fun setTimedOut(token: String, timedOut: Boolean) {
        if (!timedOut) {
            return
        }
        mediaEntries[token]?.let {
            notificationEntryManager.removeNotification(it.notificationKey, null /* ranking */,
                    UNDEFINED_DISMISS_REASON)
        }
    }

    private fun loadMediaDataInBg(key: String, sbn: StatusBarNotification) {
    private fun loadMediaDataInBg(key: String, sbn: StatusBarNotification) {
        val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION)
        val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION)
                as MediaSession.Token?
                as MediaSession.Token?
@@ -223,7 +243,7 @@ class MediaDataManager @Inject constructor(
        foregroundExecutor.execute {
        foregroundExecutor.execute {
            onMediaDataLoaded(key, MediaData(true, bgColor, app, smallIconDrawable, artist, song,
            onMediaDataLoaded(key, MediaData(true, bgColor, app, smallIconDrawable, artist, song,
                    artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token,
                    artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token,
                    notif.contentIntent, null))
                    notif.contentIntent, null, key))
        }
        }
    }
    }


+117 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2020 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

import android.media.session.MediaController
import android.media.session.PlaybackState
import android.os.SystemProperties
import android.util.Log
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
import com.android.systemui.util.concurrency.DelayableExecutor
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton

private const val DEBUG = true
private const val TAG = "MediaTimeout"
private val PAUSED_MEDIA_TIMEOUT = SystemProperties
        .getLong("debug.sysui.media_timeout", TimeUnit.MINUTES.toMillis(10))

/**
 * Controller responsible for keeping track of playback states and expiring inactive streams.
 */
@Singleton
class MediaTimeoutListener @Inject constructor(
    private val mediaControllerFactory: MediaControllerFactory,
    @Main private val mainExecutor: DelayableExecutor
) : MediaDataManager.Listener {

    private val mediaListeners: MutableMap<String, PlaybackStateListener> = mutableMapOf()

    lateinit var timeoutCallback: (String, Boolean) -> Unit

    override fun onMediaDataLoaded(key: String, data: MediaData) {
        if (mediaListeners.containsKey(key)) {
            return
        }
        mediaListeners[key] = PlaybackStateListener(key, data)
    }

    override fun onMediaDataRemoved(key: String) {
        mediaListeners.remove(key)?.destroy()
    }

    fun isTimedOut(key: String): Boolean {
        return mediaListeners[key]?.timedOut ?: false
    }

    private inner class PlaybackStateListener(
        private val key: String,
        data: MediaData
    ) : MediaController.Callback() {

        var timedOut = false

        private val mediaController = mediaControllerFactory.create(data.token)
        private var cancellation: Runnable? = null

        init {
            mediaController.registerCallback(this)
        }

        fun destroy() {
            mediaController.unregisterCallback(this)
        }

        override fun onPlaybackStateChanged(state: PlaybackState?) {
            if (DEBUG) {
                Log.v(TAG, "onPlaybackStateChanged: $state")
            }
            expireMediaTimeout(key, "playback state ativity - $state, $key")

            if (state == null || !isPlayingState(state.state)) {
                if (DEBUG) {
                    Log.v(TAG, "schedule timeout for $key")
                }
                expireMediaTimeout(key, "PLAYBACK STATE CHANGED - $state")
                cancellation = mainExecutor.executeDelayed({
                    cancellation = null
                    if (DEBUG) {
                        Log.v(TAG, "Execute timeout for $key")
                    }
                    timedOut = true
                    timeoutCallback(key, timedOut)
                }, PAUSED_MEDIA_TIMEOUT)
            } else {
                timedOut = false
                timeoutCallback(key, timedOut)
            }
        }

        private fun expireMediaTimeout(mediaNotificationKey: String, reason: String) {
            cancellation?.apply {
                if (DEBUG) {
                    Log.v(TAG,
                            "media timeout cancelled for  $mediaNotificationKey, reason: $reason")
                }
                run()
            }
            cancellation = null
        }
    }
}
 No newline at end of file
+0 −42
Original line number Original line Diff line number Diff line
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar;
package com.android.systemui.statusbar;


import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
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.DEBUG_MEDIA_FAKE_ARTWORK;
import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_WALLPAPER;
import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_WALLPAPER;
import static com.android.systemui.statusbar.phone.StatusBar.SHOW_LOCKSCREEN_MEDIA_ARTWORK;
import static com.android.systemui.statusbar.phone.StatusBar.SHOW_LOCKSCREEN_MEDIA_ARTWORK;
@@ -36,7 +35,6 @@ import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
import android.media.session.PlaybackState;
import android.os.AsyncTask;
import android.os.AsyncTask;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig;
@@ -80,7 +78,6 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.HashSet;
import java.util.List;
import java.util.List;
import java.util.Set;
import java.util.Set;
import java.util.concurrent.TimeUnit;


import dagger.Lazy;
import dagger.Lazy;


@@ -91,8 +88,6 @@ import dagger.Lazy;
public class NotificationMediaManager implements Dumpable {
public class NotificationMediaManager implements Dumpable {
    private static final String TAG = "NotificationMediaManager";
    private static final String TAG = "NotificationMediaManager";
    public static final boolean DEBUG_MEDIA = false;
    public static final boolean DEBUG_MEDIA = false;
    private static final long PAUSED_MEDIA_TIMEOUT = SystemProperties
            .getLong("debug.sysui.media_timeout", TimeUnit.MINUTES.toMillis(10));


    private final StatusBarStateController mStatusBarStateController
    private final StatusBarStateController mStatusBarStateController
            = Dependency.get(StatusBarStateController.class);
            = Dependency.get(StatusBarStateController.class);
@@ -134,7 +129,6 @@ public class NotificationMediaManager implements Dumpable {
    private MediaController mMediaController;
    private MediaController mMediaController;
    private String mMediaNotificationKey;
    private String mMediaNotificationKey;
    private MediaMetadata mMediaMetadata;
    private MediaMetadata mMediaMetadata;
    private Runnable mMediaTimeoutCancellation;


    private BackDropView mBackdrop;
    private BackDropView mBackdrop;
    private ImageView mBackdropFront;
    private ImageView mBackdropFront;
@@ -164,47 +158,11 @@ public class NotificationMediaManager implements Dumpable {
            if (DEBUG_MEDIA) {
            if (DEBUG_MEDIA) {
                Log.v(TAG, "DEBUG_MEDIA: onPlaybackStateChanged: " + state);
                Log.v(TAG, "DEBUG_MEDIA: onPlaybackStateChanged: " + state);
            }
            }
            if (mMediaTimeoutCancellation != null) {
                if (DEBUG_MEDIA) {
                    Log.v(TAG, "DEBUG_MEDIA: media timeout cancelled");
                }
                mMediaTimeoutCancellation.run();
                mMediaTimeoutCancellation = null;
            }
            if (state != null) {
            if (state != null) {
                if (!isPlaybackActive(state.getState())) {
                if (!isPlaybackActive(state.getState())) {
                    clearCurrentMediaNotification();
                    clearCurrentMediaNotification();
                }
                }
                findAndUpdateMediaNotifications();
                findAndUpdateMediaNotifications();
                scheduleMediaTimeout(state);
            }
        }

        private void scheduleMediaTimeout(PlaybackState state) {
            final NotificationEntry entry;
            synchronized (mEntryManager) {
                entry = mEntryManager.getActiveNotificationUnfiltered(mMediaNotificationKey);
            }
            if (entry != null) {
                if (!isPlayingState(state.getState())) {
                    if (DEBUG_MEDIA) {
                        Log.v(TAG, "DEBUG_MEDIA: schedule timeout for "
                                + mMediaNotificationKey);
                    }
                    mMediaTimeoutCancellation = mMainExecutor.executeDelayed(() -> {
                        synchronized (mEntryManager) {
                            if (DEBUG_MEDIA) {
                                Log.v(TAG, "DEBUG_MEDIA: execute timeout for "
                                        + mMediaNotificationKey);
                            }
                            if (mMediaNotificationKey == null) {
                                return;
                            }
                            mEntryManager.removeNotification(mMediaNotificationKey, null,
                                    UNDEFINED_DISMISS_REASON);
                        }
                    }, PAUSED_MEDIA_TIMEOUT);
                }
            }
            }
        }
        }


+1 −1
Original line number Original line Diff line number Diff line
@@ -79,7 +79,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
        mManager.addListener(mListener);
        mManager.addListener(mListener);


        mMediaData = new MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null,
        mMediaData = new MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null,
                new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null);
                new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, KEY);
        mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME);
        mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME);
    }
    }


Loading