diff options
9 files changed, 110 insertions, 57 deletions
diff --git a/api/current.txt b/api/current.txt index 9b211c28201f..f5a4973f578a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -14142,10 +14142,10 @@ package android.media { method public void loadSoundEffects(); method public void playSoundEffect(int); method public void playSoundEffect(int, float); - method public void registerMediaButtonEventReceiver(android.content.ComponentName); - method public void registerMediaButtonEventReceiver(android.app.PendingIntent); - method public void registerRemoteControlClient(android.media.RemoteControlClient); - method public boolean registerRemoteController(android.media.RemoteController); + method public deprecated void registerMediaButtonEventReceiver(android.content.ComponentName); + method public deprecated void registerMediaButtonEventReceiver(android.app.PendingIntent); + method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient); + method public deprecated boolean registerRemoteController(android.media.RemoteController); method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int); method public deprecated void setBluetoothA2dpOn(boolean); method public void setBluetoothScoOn(boolean); @@ -14164,10 +14164,10 @@ package android.media { method public void startBluetoothSco(); method public void stopBluetoothSco(); method public void unloadSoundEffects(); - method public void unregisterMediaButtonEventReceiver(android.content.ComponentName); - method public void unregisterMediaButtonEventReceiver(android.app.PendingIntent); - method public void unregisterRemoteControlClient(android.media.RemoteControlClient); - method public void unregisterRemoteController(android.media.RemoteController); + method public deprecated void unregisterMediaButtonEventReceiver(android.content.ComponentName); + method public deprecated void unregisterMediaButtonEventReceiver(android.app.PendingIntent); + method public deprecated void unregisterRemoteControlClient(android.media.RemoteControlClient); + method public deprecated void unregisterRemoteController(android.media.RemoteController); field public static final java.lang.String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY"; field public static final deprecated java.lang.String ACTION_SCO_AUDIO_STATE_CHANGED = "android.media.SCO_AUDIO_STATE_CHANGED"; field public static final java.lang.String ACTION_SCO_AUDIO_STATE_UPDATED = "android.media.ACTION_SCO_AUDIO_STATE_UPDATED"; @@ -16643,6 +16643,7 @@ package android.media.session { method public void setExtras(android.os.Bundle); method public void setFlags(int); method public void setLaunchActivity(android.app.PendingIntent); + method public void setMediaButtonReceiver(android.app.PendingIntent); method public void setMediaRouter(android.media.routing.MediaRouter); method public void setMetadata(android.media.MediaMetadata); method public void setPlaybackState(android.media.session.PlaybackState); @@ -16705,6 +16706,7 @@ package android.media.session { public final class MediaSessionManager { method public void addActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener, android.content.ComponentName); method public java.util.List<android.media.session.MediaController> getActiveSessions(android.content.ComponentName); + method public void removeActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener); } public static abstract class MediaSessionManager.SessionListener { diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 20ac8e9ef6fd..111612756c95 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -27,7 +27,10 @@ import android.content.Intent; import android.media.RemoteController.OnClientUpdateListener; import android.media.audiopolicy.AudioPolicy; import android.media.audiopolicy.AudioPolicyConfig; +import android.media.session.MediaController; +import android.media.session.MediaSession; import android.media.session.MediaSessionLegacyHelper; +import android.media.session.MediaSessionManager; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -2218,7 +2221,9 @@ public class AudioManager { * that will receive the media button intent. This broadcast receiver must be declared * in the application manifest. The package of the component must match that of * the context you're registering from. + * @deprecated Use {@link MediaSession#setMediaButtonReceiver(PendingIntent)} instead. */ + @Deprecated public void registerMediaButtonEventReceiver(ComponentName eventReceiver) { if (eventReceiver == null) { return; @@ -2244,9 +2249,12 @@ public class AudioManager { * you know you will continue running for the full time until unregistering the * PendingIntent. * @param eventReceiver target that will receive media button intents. The PendingIntent - * will be sent as-is when a media button action occurs, with {@link Intent#EXTRA_KEY_EVENT} - * added and holding the key code of the media button that was pressed. + * will be sent an {@link Intent#ACTION_MEDIA_BUTTON} event when a media button action + * occurs, with {@link Intent#EXTRA_KEY_EVENT} added and holding the key code of the + * media button that was pressed. + * @deprecated Use {@link MediaSession#setMediaButtonReceiver(PendingIntent)} instead. */ + @Deprecated public void registerMediaButtonEventReceiver(PendingIntent eventReceiver) { if (eventReceiver == null) { return; @@ -2271,7 +2279,9 @@ public class AudioManager { * Unregister the receiver of MEDIA_BUTTON intents. * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver} * that was registered with {@link #registerMediaButtonEventReceiver(ComponentName)}. + * @deprecated Use {@link MediaSession} instead. */ + @Deprecated public void unregisterMediaButtonEventReceiver(ComponentName eventReceiver) { if (eventReceiver == null) { return; @@ -2289,7 +2299,9 @@ public class AudioManager { * Unregister the receiver of MEDIA_BUTTON intents. * @param eventReceiver same PendingIntent that was registed with * {@link #registerMediaButtonEventReceiver(PendingIntent)}. + * @deprecated Use {@link MediaSession} instead. */ + @Deprecated public void unregisterMediaButtonEventReceiver(PendingIntent eventReceiver) { if (eventReceiver == null) { return; @@ -2311,7 +2323,9 @@ public class AudioManager { * @param rcClient The remote control client from which remote controls will receive * information to display. * @see RemoteControlClient + * @deprecated Use {@link MediaSession} instead. */ + @Deprecated public void registerRemoteControlClient(RemoteControlClient rcClient) { if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) { return; @@ -2324,7 +2338,9 @@ public class AudioManager { * remote controls. * @param rcClient The remote control client to unregister. * @see #registerRemoteControlClient(RemoteControlClient) + * @deprecated Use {@link MediaSession} instead. */ + @Deprecated public void unregisterRemoteControlClient(RemoteControlClient rcClient) { if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) { return; @@ -2342,7 +2358,11 @@ public class AudioManager { * @param rctlr the object to register. * @return true if the {@link RemoteController} was successfully registered, false if an * error occurred, due to an internal system error, or insufficient permissions. + * @deprecated Use + * {@link MediaSessionManager#addActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener, ComponentName)} + * and {@link MediaController} instead. */ + @Deprecated public boolean registerRemoteController(RemoteController rctlr) { if (rctlr == null) { return false; @@ -2355,7 +2375,11 @@ public class AudioManager { * Unregisters a {@link RemoteController}, causing it to no longer receive media metadata and * playback state information, and no longer be capable of controlling playback. * @param rctlr the object to unregister. + * @deprecated Use + * {@link MediaSessionManager#removeActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener)} + * instead. */ + @Deprecated public void unregisterRemoteController(RemoteController rctlr) { if (rctlr == null) { return; diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java index 5d2f3bd58870..3f7ebce89170 100644 --- a/media/java/android/media/MediaMetadata.java +++ b/media/java/android/media/MediaMetadata.java @@ -19,6 +19,7 @@ import android.graphics.Bitmap; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.text.format.Time; import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; @@ -73,7 +74,8 @@ public final class MediaMetadata implements Parcelable { public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION"; /** - * The date the media was created or published as TODO determine format. + * The date the media was created or published. The format is unspecified + * but RFC 3339 is recommended. */ public static final String METADATA_KEY_DATE = "android.media.metadata.DATE"; diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl index 0b8b0d4a139e..af3b72e7f49f 100644 --- a/media/java/android/media/session/ISession.aidl +++ b/media/java/android/media/session/ISession.aidl @@ -16,7 +16,6 @@ package android.media.session; import android.app.PendingIntent; -import android.content.ComponentName; import android.content.pm.ParceledListSlice; import android.media.AudioAttributes; import android.media.MediaMetadata; @@ -37,7 +36,7 @@ interface ISession { void setFlags(int flags); void setActive(boolean active); void setMediaRouter(in IMediaRouter router); - void setMediaButtonReceiver(in ComponentName mbr); + void setMediaButtonReceiver(in PendingIntent mbr); void setLaunchPendingIntent(in PendingIntent pi); void destroy(); diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index 5833492cf566..a8786335fa67 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -254,13 +254,14 @@ public final class MediaSession { } /** - * Set a media button event receiver component to use to restart playback - * after an app has been stopped. + * Set a pending intent for your media button receiver to allow restarting + * playback after the session has been stopped. If your app is started in + * this way an {@link Intent#ACTION_MEDIA_BUTTON} intent will be sent via + * the pending intent. * - * @param mbr The receiver component to send the media button event to. - * @hide + * @param mbr The {@link PendingIntent} to send the media button event to. */ - public void setMediaButtonReceiver(@Nullable ComponentName mbr) { + public void setMediaButtonReceiver(@Nullable PendingIntent mbr) { try { mBinder.setMediaButtonReceiver(mbr); } catch (RemoteException e) { diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java index a6963cfe98af..8ea2039625bc 100644 --- a/media/java/android/media/session/MediaSessionLegacyHelper.java +++ b/media/java/android/media/session/MediaSessionLegacyHelper.java @@ -304,7 +304,7 @@ public class MediaSessionLegacyHelper { holder.mMediaButtonReceiver = new MediaButtonReceiver(pi, context); holder.mSession.addCallback(holder.mMediaButtonReceiver, mHandler); - holder.mSession.setMediaButtonReceiver(mbrComponent); + holder.mSession.setMediaButtonReceiver(pi); if (DEBUG) { Log.d(TAG, "addMediaButtonListener added " + pi); } diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index 824b39708d49..ca41965e6ded 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -175,7 +175,6 @@ public final class MediaSessionManager { * Stop receiving active sessions updates on the specified listener. * * @param listener The listener to remove. - * @hide */ public void removeActiveSessionsListener(@NonNull SessionListener listener) { if (listener == null) { diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 4ceb21307aaa..d0bcfd408ff9 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -99,7 +99,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { private long mFlags; private IMediaRouter mMediaRouter; - private ComponentName mMediaButtonReceiver; + private PendingIntent mMediaButtonReceiver; private PendingIntent mLaunchIntent; // TransportPerformer fields @@ -170,7 +170,12 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { return mSessionInfo; } - public ComponentName getMediaButtonReceiver() { + /** + * Get the intent the app set for their media button receiver. + * + * @return The pending intent set by the app or null. + */ + public PendingIntent getMediaButtonReceiver() { return mMediaButtonReceiver; } @@ -648,8 +653,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override - public void setMediaButtonReceiver(ComponentName mbr) { - mMediaButtonReceiver = mbr; + public void setMediaButtonReceiver(PendingIntent pi) { + mMediaButtonReceiver = pi; } @Override diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index b0ccd622715a..ce2899d3f24e 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -20,6 +20,8 @@ import android.Manifest; import android.app.Activity; import android.app.ActivityManager; import android.app.KeyguardManager; +import android.app.PendingIntent; +import android.app.PendingIntent.CanceledException; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -407,16 +409,6 @@ public class MediaSessionService extends SystemService implements Monitor { return user; } - private int findIndexOfSessionForIdLocked(String sessionId) { - for (int i = mAllSessions.size() - 1; i >= 0; i--) { - MediaSessionRecord session = mAllSessions.get(i); - if (TextUtils.equals(session.getSessionInfo().getId(), sessionId)) { - return i; - } - } - return -1; - } - private int findIndexOfSessionsListenerLocked(IActiveSessionsListener listener) { for (int i = mSessionsListeners.size() - 1; i >= 0; i--) { if (mSessionsListeners.get(i).mListener == listener) { @@ -436,7 +428,7 @@ public class MediaSessionService extends SystemService implements Monitor { List<MediaSessionRecord> records = mPriorityStack.getActiveSessions(userId); int size = records.size(); if (size > 0) { - persistMediaButtonReceiverLocked(records.get(0)); + rememberMediaButtonReceiverLocked(records.get(0)); } ArrayList<MediaSession.Token> tokens = new ArrayList<MediaSession.Token>(); for (int i = 0; i < size; i++) { @@ -469,13 +461,11 @@ public class MediaSessionService extends SystemService implements Monitor { } } - private void persistMediaButtonReceiverLocked(MediaSessionRecord record) { - ComponentName receiver = record.getMediaButtonReceiver(); - if (receiver != null) { - Settings.System.putStringForUser(mContentResolver, - Settings.System.MEDIA_BUTTON_RECEIVER, - receiver == null ? "" : receiver.flattenToString(), - UserHandle.USER_CURRENT); + private void rememberMediaButtonReceiverLocked(MediaSessionRecord record) { + PendingIntent receiver = record.getMediaButtonReceiver(); + UserRecord user = mUserRecords.get(record.getUserId()); + if (receiver != null && user != null) { + user.mLastMediaButtonReceiver = receiver; } } @@ -486,6 +476,7 @@ public class MediaSessionService extends SystemService implements Monitor { final class UserRecord { private final int mUserId; private final ArrayList<MediaSessionRecord> mSessions = new ArrayList<MediaSessionRecord>(); + private PendingIntent mLastMediaButtonReceiver; public UserRecord(Context context, int userId) { mUserId = userId; @@ -521,6 +512,7 @@ public class MediaSessionService extends SystemService implements Monitor { public void dumpLocked(PrintWriter pw, String prefix) { pw.println(prefix + "Record for user " + mUserId); String indent = prefix + " "; + pw.println(indent + "MediaButtonReceiver:" + mLastMediaButtonReceiver); int size = mSessions.size(); pw.println(indent + size + " Sessions:"); for (int i = 0; i < size; i++) { @@ -843,21 +835,43 @@ public class MediaSessionService extends SystemService implements Monitor { needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1, mKeyEventReceiver); } else { - if (needWakeLock) { - mMediaEventWakeLock.acquire(); - } - if (DEBUG) { - Log.d(TAG, "Sending media key ordered broadcast"); - } - // Fallback to legacy behavior - Intent keyIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); - keyIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent); - if (needWakeLock) { - keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED, - WAKELOCK_RELEASE_ON_FINISHED); + // Launch the last PendingIntent we had with priority + int userId = ActivityManager.getCurrentUser(); + UserRecord user = mUserRecords.get(userId); + if (user.mLastMediaButtonReceiver != null) { + if (DEBUG) { + Log.d(TAG, "Sending media key to last known PendingIntent"); + } + if (needWakeLock) { + mKeyEventReceiver.aquireWakeLockLocked(); + } + Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); + mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent); + try { + user.mLastMediaButtonReceiver.send(getContext(), + needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1, + mediaButtonIntent, mKeyEventReceiver, null); + } catch (CanceledException e) { + Log.i(TAG, "Error sending key event to media button receiver " + + user.mLastMediaButtonReceiver, e); + } + } else { + if (DEBUG) { + Log.d(TAG, "Sending media key ordered broadcast"); + } + if (needWakeLock) { + mMediaEventWakeLock.acquire(); + } + // Fallback to legacy behavior + Intent keyIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); + keyIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent); + if (needWakeLock) { + keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED, + WAKELOCK_RELEASE_ON_FINISHED); + } + getContext().sendOrderedBroadcastAsUser(keyIntent, UserHandle.ALL, + null, mKeyEventDone, mHandler, Activity.RESULT_OK, null, null); } - getContext().sendOrderedBroadcastAsUser(keyIntent, UserHandle.ALL, - null, mKeyEventDone, mHandler, Activity.RESULT_OK, null, null); } } @@ -904,7 +918,8 @@ public class MediaSessionService extends SystemService implements Monitor { private KeyEventWakeLockReceiver mKeyEventReceiver = new KeyEventWakeLockReceiver(mHandler); - class KeyEventWakeLockReceiver extends ResultReceiver implements Runnable { + class KeyEventWakeLockReceiver extends ResultReceiver implements Runnable, + PendingIntent.OnFinished { private final Handler mHandler; private int mRefCount = 0; private int mLastTimeoutId = 0; @@ -963,6 +978,12 @@ public class MediaSessionService extends SystemService implements Monitor { mMediaEventWakeLock.release(); mHandler.removeCallbacks(this); } + + @Override + public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, + String resultData, Bundle resultExtras) { + onReceiveResult(resultCode, null); + } }; BroadcastReceiver mKeyEventDone = new BroadcastReceiver() { |