NotificationMediaManager populates media player when using new pipeline.
Test: manual Change-Id: I25e623c28e991fa907541cb553ba8f9f74e60fe0
This commit is contained in:
@@ -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,14 +346,24 @@ public class NotificationMediaManager implements Dumpable {
|
||||
if (mMediaNotificationKey == null) {
|
||||
return null;
|
||||
}
|
||||
synchronized (mEntryManager) {
|
||||
NotificationEntry entry = mEntryManager
|
||||
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);
|
||||
if (entry == null || entry.getIcons().getShelfIcon() == null) {
|
||||
return null;
|
||||
}
|
||||
if (entry == null || entry.getIcons().getShelfIcon() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return entry.getIcons().getShelfIcon().getSourceIcon();
|
||||
return entry.getIcons().getShelfIcon().getSourceIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,94 +378,110 @@ public class NotificationMediaManager implements Dumpable {
|
||||
}
|
||||
|
||||
public void findAndUpdateMediaNotifications() {
|
||||
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;
|
||||
for (NotificationEntry entry : allNotifications) {
|
||||
if (entry.isMediaNotification()) {
|
||||
final MediaSession.Token token =
|
||||
entry.getSbn().getNotification().extras.getParcelable(
|
||||
Notification.EXTRA_MEDIA_SESSION);
|
||||
if (token != null) {
|
||||
MediaController aController = new MediaController(mContext, token);
|
||||
if (PlaybackState.STATE_PLAYING
|
||||
== getMediaControllerPlaybackState(aController)) {
|
||||
if (DEBUG_MEDIA) {
|
||||
Log.v(TAG, "DEBUG_MEDIA: found mediastyle controller matching "
|
||||
+ entry.getSbn().getKey());
|
||||
}
|
||||
mediaNotification = entry;
|
||||
controller = aController;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mediaNotification == null) {
|
||||
// Still nothing? OK, let's just look for live media sessions and see if they match
|
||||
// one of our notifications. This will catch apps that aren't (yet!) using media
|
||||
// notifications.
|
||||
|
||||
synchronized (mEntryManager) {
|
||||
Collection<NotificationEntry> allNotifications = mEntryManager.getAllNotifs();
|
||||
if (mMediaSessionManager != null) {
|
||||
// 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);
|
||||
|
||||
// Promote the media notification with a controller in 'playing' state, if any.
|
||||
NotificationEntry mediaNotification = null;
|
||||
MediaController controller = null;
|
||||
for (NotificationEntry entry : allNotifications) {
|
||||
if (entry.isMediaNotification()) {
|
||||
final MediaSession.Token token =
|
||||
entry.getSbn().getNotification().extras.getParcelable(
|
||||
Notification.EXTRA_MEDIA_SESSION);
|
||||
if (token != null) {
|
||||
MediaController aController = new MediaController(mContext, token);
|
||||
if (PlaybackState.STATE_PLAYING ==
|
||||
getMediaControllerPlaybackState(aController)) {
|
||||
for (MediaController aController : sessions) {
|
||||
// now to see if we have one like this
|
||||
final String pkg = aController.getPackageName();
|
||||
|
||||
for (NotificationEntry entry : allNotifications) {
|
||||
if (entry.getSbn().getPackageName().equals(pkg)) {
|
||||
if (DEBUG_MEDIA) {
|
||||
Log.v(TAG, "DEBUG_MEDIA: found mediastyle controller matching "
|
||||
Log.v(TAG, "DEBUG_MEDIA: found controller matching "
|
||||
+ entry.getSbn().getKey());
|
||||
}
|
||||
mediaNotification = entry;
|
||||
controller = aController;
|
||||
mediaNotification = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mediaNotification == null) {
|
||||
// Still nothing? OK, let's just look for live media sessions and see if they match
|
||||
// one of our notifications. This will catch apps that aren't (yet!) using media
|
||||
// notifications.
|
||||
}
|
||||
|
||||
if (mMediaSessionManager != null) {
|
||||
// TODO: Should this really be for all users?
|
||||
final List<MediaController> sessions
|
||||
= mMediaSessionManager.getActiveSessionsForUser(
|
||||
null,
|
||||
UserHandle.USER_ALL);
|
||||
|
||||
for (MediaController aController : sessions) {
|
||||
// now to see if we have one like this
|
||||
final String pkg = aController.getPackageName();
|
||||
|
||||
for (NotificationEntry entry : allNotifications) {
|
||||
if (entry.getSbn().getPackageName().equals(pkg)) {
|
||||
if (DEBUG_MEDIA) {
|
||||
Log.v(TAG, "DEBUG_MEDIA: found controller matching "
|
||||
+ entry.getSbn().getKey());
|
||||
}
|
||||
controller = aController;
|
||||
mediaNotification = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller != null && !sameSessions(mMediaController, controller)) {
|
||||
// We have a new media session
|
||||
clearCurrentMediaNotificationSession();
|
||||
mMediaController = controller;
|
||||
mMediaController.registerCallback(mMediaListener);
|
||||
mMediaMetadata = mMediaController.getMetadata();
|
||||
if (DEBUG_MEDIA) {
|
||||
Log.v(TAG, "DEBUG_MEDIA: insert listener, found new controller: "
|
||||
+ mMediaController + ", receive metadata: " + mMediaMetadata);
|
||||
}
|
||||
|
||||
if (controller != null && !sameSessions(mMediaController, controller)) {
|
||||
// We have a new media session
|
||||
clearCurrentMediaNotificationSession();
|
||||
mMediaController = controller;
|
||||
mMediaController.registerCallback(mMediaListener);
|
||||
mMediaMetadata = mMediaController.getMetadata();
|
||||
if (DEBUG_MEDIA) {
|
||||
Log.v(TAG, "DEBUG_MEDIA: insert listener, found new controller: "
|
||||
+ mMediaController + ", receive metadata: " + mMediaMetadata);
|
||||
}
|
||||
metaDataChanged = true;
|
||||
}
|
||||
|
||||
metaDataChanged = true;
|
||||
}
|
||||
|
||||
if (mediaNotification != null
|
||||
&& !mediaNotification.getSbn().getKey().equals(mMediaNotificationKey)) {
|
||||
mMediaNotificationKey = mediaNotification.getSbn().getKey();
|
||||
if (DEBUG_MEDIA) {
|
||||
Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
|
||||
+ mMediaNotificationKey);
|
||||
}
|
||||
if (mediaNotification != null
|
||||
&& !mediaNotification.getSbn().getKey().equals(mMediaNotificationKey)) {
|
||||
mMediaNotificationKey = mediaNotification.getSbn().getKey();
|
||||
if (DEBUG_MEDIA) {
|
||||
Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
|
||||
+ 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=");
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user