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

Commit 75d60f7a authored by Jeff DeCew's avatar Jeff DeCew
Browse files

NotificationMediaManager populates media player when using new pipeline.

Test: manual
Change-Id: I25e623c28e991fa907541cb553ba8f9f74e60fe0
parent bf881172
Loading
Loading
Loading
Loading
+164 −91
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
import android.util.Log;
import android.view.View;
@@ -57,6 +58,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.dagger.StatusBarModule;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
@@ -77,6 +79,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import dagger.Lazy;
@@ -106,6 +109,8 @@ public class NotificationMediaManager implements Dumpable {

    private final NotificationEntryManager mEntryManager;
    private final MediaDataManager mMediaDataManager;
    private final NotifPipeline mNotifPipeline;
    private final boolean mUsingNotifPipeline;

    @Nullable
    private Lazy<NotificationShadeWindowController> mNotificationShadeWindowController;
@@ -189,6 +194,8 @@ public class NotificationMediaManager implements Dumpable {
            NotificationEntryManager notificationEntryManager,
            MediaArtworkProcessor mediaArtworkProcessor,
            KeyguardBypassController keyguardBypassController,
            NotifPipeline notifPipeline,
            FeatureFlags featureFlags,
            @Main DelayableExecutor mainExecutor,
            DeviceConfigProxy deviceConfig,
            MediaDataManager mediaDataManager) {
@@ -206,17 +213,65 @@ public class NotificationMediaManager implements Dumpable {
        mEntryManager = notificationEntryManager;
        mMainExecutor = mainExecutor;
        mMediaDataManager = mediaDataManager;
        mNotifPipeline = notifPipeline;

        notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
        if (!featureFlags.isNewNotifPipelineRenderingEnabled()) {
            setupNEM();
            mUsingNotifPipeline = false;
        } else {
            setupNotifPipeline();
            mUsingNotifPipeline = true;
        }

        mShowCompactMediaSeekbar = "true".equals(
                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
                    SystemUiDeviceConfigFlags.COMPACT_MEDIA_SEEKBAR_ENABLED));

        deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
                mContext.getMainExecutor(),
                mPropertiesChangedListener);
    }

    private void setupNotifPipeline() {
        mNotifPipeline.addCollectionListener(new NotifCollectionListener() {
            @Override
            public void onEntryAdded(@NonNull NotificationEntry entry) {
                mMediaDataManager.onNotificationAdded(entry.getKey(), entry.getSbn());
            }

            @Override
            public void onEntryUpdated(NotificationEntry entry) {
                mMediaDataManager.onNotificationAdded(entry.getKey(), entry.getSbn());
            }

            @Override
            public void onEntryBind(NotificationEntry entry, StatusBarNotification sbn) {
                findAndUpdateMediaNotifications();
            }

            @Override
            public void onEntryRemoved(@NonNull NotificationEntry entry, int reason) {
                removeEntry(entry);
            }

            @Override
            public void onEntryCleanUp(@NonNull NotificationEntry entry) {
                removeEntry(entry);
            }
        });
    }

    private void setupNEM() {
        mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {

            @Override
            public void onPendingEntryAdded(NotificationEntry entry) {
                mediaDataManager.onNotificationAdded(entry.getKey(), entry.getSbn());
                mMediaDataManager.onNotificationAdded(entry.getKey(), entry.getSbn());
            }

            @Override
            public void onPreEntryUpdated(NotificationEntry entry) {
                mediaDataManager.onNotificationAdded(entry.getKey(), entry.getSbn());
                mMediaDataManager.onNotificationAdded(entry.getKey(), entry.getSbn());
            }

            @Override
@@ -231,8 +286,8 @@ public class NotificationMediaManager implements Dumpable {

            @Override
            public void onEntryRemoved(
                    NotificationEntry entry,
                    NotificationVisibility visibility,
                    @NonNull NotificationEntry entry,
                    @Nullable NotificationVisibility visibility,
                    boolean removedByUser,
                    int reason) {
                removeEntry(entry);
@@ -242,20 +297,12 @@ public class NotificationMediaManager implements Dumpable {
        // Pending entries are never inflated, and will never generate a call to onEntryRemoved().
        // This can happen when notifications are added and canceled before inflation. Add this
        // separate listener for cleanup, since media inflation occurs onPendingEntryAdded().
        notificationEntryManager.addCollectionListener(new NotifCollectionListener() {
        mEntryManager.addCollectionListener(new NotifCollectionListener() {
            @Override
            public void onEntryCleanUp(@NonNull NotificationEntry entry) {
                removeEntry(entry);
            }
        });

        mShowCompactMediaSeekbar = "true".equals(
                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
                    SystemUiDeviceConfigFlags.COMPACT_MEDIA_SEEKBAR_ENABLED));

        deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
                mContext.getMainExecutor(),
                mPropertiesChangedListener);
    }

    private void removeEntry(NotificationEntry entry) {
@@ -299,6 +346,15 @@ public class NotificationMediaManager implements Dumpable {
        if (mMediaNotificationKey == null) {
            return null;
        }
        if (mUsingNotifPipeline) {
            // TODO(b/169655596): Either add O(1) lookup, or cache this icon?
            return mNotifPipeline.getAllNotifs().stream()
                .filter(entry -> Objects.equals(entry.getKey(), mMediaNotificationKey))
                .findAny()
                .map(entry -> entry.getIcons().getShelfIcon())
                .map(StatusBarIconView::getSourceIcon)
                .orElse(null);
        } else {
            synchronized (mEntryManager) {
                NotificationEntry entry = mEntryManager
                    .getActiveNotificationUnfiltered(mMediaNotificationKey);
@@ -309,6 +365,7 @@ public class NotificationMediaManager implements Dumpable {
                return entry.getIcons().getShelfIcon().getSourceIcon();
            }
        }
    }

    public void addCallback(MediaListener callback) {
        mMediaListeners.add(callback);
@@ -321,11 +378,33 @@ public class NotificationMediaManager implements Dumpable {
    }

    public void findAndUpdateMediaNotifications() {
        boolean metaDataChanged = false;

        boolean metaDataChanged;
        if (mUsingNotifPipeline) {
            // TODO(b/169655907): get the semi-filtered notifications for current user
            Collection<NotificationEntry> allNotifications = mNotifPipeline.getAllNotifs();
            metaDataChanged = findPlayingMediaNotification(allNotifications);
        } else {
            synchronized (mEntryManager) {
                Collection<NotificationEntry> allNotifications = mEntryManager.getAllNotifs();
                metaDataChanged = findPlayingMediaNotification(allNotifications);
            }

            if (metaDataChanged) {
                mEntryManager.updateNotifications("NotificationMediaManager - metaDataChanged");
            }

        }
        dispatchUpdateMediaMetaData(metaDataChanged, true /* allowEnterAnimation */);
    }

    /**
     * Find a notification and media controller associated with the playing media session, and
     * update this manager's internal state.
     * @return whether the current MediaMetadata changed (and needs to be announced to listeners).
     */
    private boolean findPlayingMediaNotification(
            @NonNull Collection<NotificationEntry> allNotifications) {
        boolean metaDataChanged = false;
        // Promote the media notification with a controller in 'playing' state, if any.
        NotificationEntry mediaNotification = null;
        MediaController controller = null;
@@ -336,8 +415,8 @@ public class NotificationMediaManager implements Dumpable {
                                Notification.EXTRA_MEDIA_SESSION);
                if (token != null) {
                    MediaController aController = new MediaController(mContext, token);
                        if (PlaybackState.STATE_PLAYING ==
                                getMediaControllerPlaybackState(aController)) {
                    if (PlaybackState.STATE_PLAYING
                            == getMediaControllerPlaybackState(aController)) {
                        if (DEBUG_MEDIA) {
                            Log.v(TAG, "DEBUG_MEDIA: found mediastyle controller matching "
                                    + entry.getSbn().getKey());
@@ -355,11 +434,10 @@ public class NotificationMediaManager implements Dumpable {
            // notifications.

            if (mMediaSessionManager != null) {
                    // TODO: Should this really be for all users?
                    final List<MediaController> sessions
                            = mMediaSessionManager.getActiveSessionsForUser(
                            null,
                            UserHandle.USER_ALL);
                // TODO: Should this really be for all users? It appears that inactive users
                //  can't have active sessions, which would mean it is fine.
                final List<MediaController> sessions =
                        mMediaSessionManager.getActiveSessionsForUser(null, UserHandle.USER_ALL);

                for (MediaController aController : sessions) {
                    // now to see if we have one like this
@@ -402,13 +480,8 @@ public class NotificationMediaManager implements Dumpable {
                        + mMediaNotificationKey);
            }
        }
        }

        if (metaDataChanged) {
            mEntryManager.updateNotifications("NotificationMediaManager - metaDataChanged");
        }

        dispatchUpdateMediaMetaData(metaDataChanged, true /* allowEnterAnimation */);
        return metaDataChanged;
    }

    public void clearCurrentMediaNotification() {
@@ -428,7 +501,7 @@ public class NotificationMediaManager implements Dumpable {
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
        pw.print("    mMediaSessionManager=");
        pw.println(mMediaSessionManager);
        pw.print("    mMediaNotificationKey=");
+6 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import com.android.systemui.media.MediaDataManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.ActionClickLogger;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.MediaArtworkProcessor;
import com.android.systemui.statusbar.NotificationClickNotifier;
import com.android.systemui.statusbar.NotificationListener;
@@ -43,6 +44,7 @@ import com.android.systemui.statusbar.notification.AssistantFeedbackController;
import com.android.systemui.statusbar.notification.DynamicChildBindController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
@@ -108,6 +110,8 @@ public interface StatusBarDependenciesModule {
            NotificationEntryManager notificationEntryManager,
            MediaArtworkProcessor mediaArtworkProcessor,
            KeyguardBypassController keyguardBypassController,
            NotifPipeline notifPipeline,
            FeatureFlags featureFlags,
            @Main DelayableExecutor mainExecutor,
            DeviceConfigProxy deviceConfigProxy,
            MediaDataManager mediaDataManager) {
@@ -118,6 +122,8 @@ public interface StatusBarDependenciesModule {
                notificationEntryManager,
                mediaArtworkProcessor,
                keyguardBypassController,
                notifPipeline,
                featureFlags,
                mainExecutor,
                deviceConfigProxy,
                mediaDataManager);