Loading packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java 0 → 100644 +245 −0 Original line number Diff line number Diff line package com.android.systemui.statusbar; import android.app.Notification; import android.content.Context; import android.media.MediaMetadata; import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.UserHandle; import android.util.Log; import com.android.systemui.Dumpable; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; /** * Handles tasks and state related to media notifications. For example, there is a 'current' media * notification, which this class keeps track of. */ public class NotificationMediaManager implements Dumpable { private static final String TAG = "NotificationMediaManager"; public static final boolean DEBUG_MEDIA = false; private final NotificationPresenter mPresenter; private final Context mContext; private final MediaSessionManager mMediaSessionManager; private MediaController mMediaController; private String mMediaNotificationKey; private MediaMetadata mMediaMetadata; private final MediaController.Callback mMediaListener = new MediaController.Callback() { @Override public void onPlaybackStateChanged(PlaybackState state) { super.onPlaybackStateChanged(state); if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: onPlaybackStateChanged: " + state); } if (state != null) { if (!isPlaybackActive(state.getState())) { clearCurrentMediaNotification(); mPresenter.updateMediaMetaData(true, true); } } } @Override public void onMetadataChanged(MediaMetadata metadata) { super.onMetadataChanged(metadata); if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: onMetadataChanged: " + metadata); } mMediaMetadata = metadata; mPresenter.updateMediaMetaData(true, true); } }; public NotificationMediaManager(NotificationPresenter presenter, Context context) { mPresenter = presenter; mContext = context; mMediaSessionManager = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE); // TODO: use MediaSessionManager.SessionListener to hook us up to future updates // in session state } public void onNotificationRemoved(String key) { if (key.equals(mMediaNotificationKey)) { clearCurrentMediaNotification(); mPresenter.updateMediaMetaData(true, true); } } public String getMediaNotificationKey() { return mMediaNotificationKey; } public MediaMetadata getMediaMetadata() { return mMediaMetadata; } public void findAndUpdateMediaNotifications() { boolean metaDataChanged = false; synchronized (mPresenter.getNotificationData()) { ArrayList<NotificationData.Entry> activeNotifications = mPresenter .getNotificationData().getActiveNotifications(); final int N = activeNotifications.size(); // Promote the media notification with a controller in 'playing' state, if any. NotificationData.Entry mediaNotification = null; MediaController controller = null; for (int i = 0; i < N; i++) { final NotificationData.Entry entry = activeNotifications.get(i); if (isMediaNotification(entry)) { final MediaSession.Token token = entry.notification.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.notification.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. 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) { if (PlaybackState.STATE_PLAYING == getMediaControllerPlaybackState(aController)) { // now to see if we have one like this final String pkg = aController.getPackageName(); for (int i = 0; i < N; i++) { final NotificationData.Entry entry = activeNotifications.get(i); if (entry.notification.getPackageName().equals(pkg)) { if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: found controller matching " + entry.notification.getKey()); } controller = aController; mediaNotification = entry; break; } } } } } } if (controller != null && !sameSessions(mMediaController, controller)) { // We have a new media session clearCurrentMediaNotification(); mMediaController = controller; mMediaController.registerCallback(mMediaListener); mMediaMetadata = mMediaController.getMetadata(); if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: insert listener, receive metadata: " + mMediaMetadata); } if (mediaNotification != null) { mMediaNotificationKey = mediaNotification.notification.getKey(); if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key=" + mMediaNotificationKey + " controller=" + mMediaController); } } metaDataChanged = true; } } if (metaDataChanged) { mPresenter.updateNotifications(); } mPresenter.updateMediaMetaData(metaDataChanged, true); } public void clearCurrentMediaNotification() { mMediaNotificationKey = null; mMediaMetadata = null; if (mMediaController != null) { if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: " + mMediaController.getPackageName()); } mMediaController.unregisterCallback(mMediaListener); } mMediaController = null; } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.print(" mMediaSessionManager="); pw.println(mMediaSessionManager); pw.print(" mMediaNotificationKey="); pw.println(mMediaNotificationKey); pw.print(" mMediaController="); pw.print(mMediaController); if (mMediaController != null) { pw.print(" state=" + mMediaController.getPlaybackState()); } pw.println(); pw.print(" mMediaMetadata="); pw.print(mMediaMetadata); if (mMediaMetadata != null) { pw.print(" title=" + mMediaMetadata.getText(MediaMetadata.METADATA_KEY_TITLE)); } pw.println(); } private boolean isPlaybackActive(int state) { return state != PlaybackState.STATE_STOPPED && state != PlaybackState.STATE_ERROR && state != PlaybackState.STATE_NONE; } private boolean sameSessions(MediaController a, MediaController b) { if (a == b) { return true; } if (a == null) { return false; } return a.controlsSameSession(b); } private int getMediaControllerPlaybackState(MediaController controller) { if (controller != null) { final PlaybackState playbackState = controller.getPlaybackState(); if (playbackState != null) { return playbackState.getState(); } } return PlaybackState.STATE_NONE; } private boolean isMediaNotification(NotificationData.Entry entry) { // TODO: confirm that there's a valid media key return entry.getExpandedContentView() != null && entry.getExpandedContentView() .findViewById(com.android.internal.R.id.media_actions) != null; } } packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java +16 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,22 @@ public interface NotificationPresenter { */ void startNotificationGutsIntent(Intent intent, int appUid); /** * Returns NotificationData. */ NotificationData getNotificationData(); // TODO: Create NotificationEntryManager and move this method to there. /** * Signals that some notifications have changed, and NotificationPresenter should update itself. */ void updateNotifications(); /** * Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper. */ void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation); // TODO: Create NotificationUpdateHandler and move this method to there. /** * Removes a notification. Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +31 −197 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java 0 → 100644 +245 −0 Original line number Diff line number Diff line package com.android.systemui.statusbar; import android.app.Notification; import android.content.Context; import android.media.MediaMetadata; import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.UserHandle; import android.util.Log; import com.android.systemui.Dumpable; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; /** * Handles tasks and state related to media notifications. For example, there is a 'current' media * notification, which this class keeps track of. */ public class NotificationMediaManager implements Dumpable { private static final String TAG = "NotificationMediaManager"; public static final boolean DEBUG_MEDIA = false; private final NotificationPresenter mPresenter; private final Context mContext; private final MediaSessionManager mMediaSessionManager; private MediaController mMediaController; private String mMediaNotificationKey; private MediaMetadata mMediaMetadata; private final MediaController.Callback mMediaListener = new MediaController.Callback() { @Override public void onPlaybackStateChanged(PlaybackState state) { super.onPlaybackStateChanged(state); if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: onPlaybackStateChanged: " + state); } if (state != null) { if (!isPlaybackActive(state.getState())) { clearCurrentMediaNotification(); mPresenter.updateMediaMetaData(true, true); } } } @Override public void onMetadataChanged(MediaMetadata metadata) { super.onMetadataChanged(metadata); if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: onMetadataChanged: " + metadata); } mMediaMetadata = metadata; mPresenter.updateMediaMetaData(true, true); } }; public NotificationMediaManager(NotificationPresenter presenter, Context context) { mPresenter = presenter; mContext = context; mMediaSessionManager = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE); // TODO: use MediaSessionManager.SessionListener to hook us up to future updates // in session state } public void onNotificationRemoved(String key) { if (key.equals(mMediaNotificationKey)) { clearCurrentMediaNotification(); mPresenter.updateMediaMetaData(true, true); } } public String getMediaNotificationKey() { return mMediaNotificationKey; } public MediaMetadata getMediaMetadata() { return mMediaMetadata; } public void findAndUpdateMediaNotifications() { boolean metaDataChanged = false; synchronized (mPresenter.getNotificationData()) { ArrayList<NotificationData.Entry> activeNotifications = mPresenter .getNotificationData().getActiveNotifications(); final int N = activeNotifications.size(); // Promote the media notification with a controller in 'playing' state, if any. NotificationData.Entry mediaNotification = null; MediaController controller = null; for (int i = 0; i < N; i++) { final NotificationData.Entry entry = activeNotifications.get(i); if (isMediaNotification(entry)) { final MediaSession.Token token = entry.notification.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.notification.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. 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) { if (PlaybackState.STATE_PLAYING == getMediaControllerPlaybackState(aController)) { // now to see if we have one like this final String pkg = aController.getPackageName(); for (int i = 0; i < N; i++) { final NotificationData.Entry entry = activeNotifications.get(i); if (entry.notification.getPackageName().equals(pkg)) { if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: found controller matching " + entry.notification.getKey()); } controller = aController; mediaNotification = entry; break; } } } } } } if (controller != null && !sameSessions(mMediaController, controller)) { // We have a new media session clearCurrentMediaNotification(); mMediaController = controller; mMediaController.registerCallback(mMediaListener); mMediaMetadata = mMediaController.getMetadata(); if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: insert listener, receive metadata: " + mMediaMetadata); } if (mediaNotification != null) { mMediaNotificationKey = mediaNotification.notification.getKey(); if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key=" + mMediaNotificationKey + " controller=" + mMediaController); } } metaDataChanged = true; } } if (metaDataChanged) { mPresenter.updateNotifications(); } mPresenter.updateMediaMetaData(metaDataChanged, true); } public void clearCurrentMediaNotification() { mMediaNotificationKey = null; mMediaMetadata = null; if (mMediaController != null) { if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: " + mMediaController.getPackageName()); } mMediaController.unregisterCallback(mMediaListener); } mMediaController = null; } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.print(" mMediaSessionManager="); pw.println(mMediaSessionManager); pw.print(" mMediaNotificationKey="); pw.println(mMediaNotificationKey); pw.print(" mMediaController="); pw.print(mMediaController); if (mMediaController != null) { pw.print(" state=" + mMediaController.getPlaybackState()); } pw.println(); pw.print(" mMediaMetadata="); pw.print(mMediaMetadata); if (mMediaMetadata != null) { pw.print(" title=" + mMediaMetadata.getText(MediaMetadata.METADATA_KEY_TITLE)); } pw.println(); } private boolean isPlaybackActive(int state) { return state != PlaybackState.STATE_STOPPED && state != PlaybackState.STATE_ERROR && state != PlaybackState.STATE_NONE; } private boolean sameSessions(MediaController a, MediaController b) { if (a == b) { return true; } if (a == null) { return false; } return a.controlsSameSession(b); } private int getMediaControllerPlaybackState(MediaController controller) { if (controller != null) { final PlaybackState playbackState = controller.getPlaybackState(); if (playbackState != null) { return playbackState.getState(); } } return PlaybackState.STATE_NONE; } private boolean isMediaNotification(NotificationData.Entry entry) { // TODO: confirm that there's a valid media key return entry.getExpandedContentView() != null && entry.getExpandedContentView() .findViewById(com.android.internal.R.id.media_actions) != null; } }
packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java +16 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,22 @@ public interface NotificationPresenter { */ void startNotificationGutsIntent(Intent intent, int appUid); /** * Returns NotificationData. */ NotificationData getNotificationData(); // TODO: Create NotificationEntryManager and move this method to there. /** * Signals that some notifications have changed, and NotificationPresenter should update itself. */ void updateNotifications(); /** * Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper. */ void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation); // TODO: Create NotificationUpdateHandler and move this method to there. /** * Removes a notification. Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +31 −197 File changed.Preview size limit exceeded, changes collapsed. Show changes