diff options
| -rw-r--r-- | Android.mk | 2 | ||||
| -rw-r--r-- | CleanSpec.mk | 1 | ||||
| -rw-r--r-- | media/java/android/media/AudioManager.java | 301 | ||||
| -rw-r--r-- | media/java/android/media/AudioService.java | 38 | ||||
| -rw-r--r-- | media/java/android/media/IAudioService.aidl | 9 | ||||
| -rw-r--r-- | media/java/android/media/IRemoteControlClientDispatcher.aidl (renamed from media/java/android/media/IRemoteControlClient.aidl) | 18 | ||||
| -rw-r--r-- | media/java/android/media/RemoteControlClient.java | 243 | 
7 files changed, 402 insertions, 210 deletions
diff --git a/Android.mk b/Android.mk index 752a5f8cdf93..a0b80e4fa5cf 100644 --- a/Android.mk +++ b/Android.mk @@ -183,7 +183,7 @@ LOCAL_SRC_FILES += \  	media/java/android/media/IAudioFocusDispatcher.aidl \  	media/java/android/media/IMediaScannerListener.aidl \  	media/java/android/media/IMediaScannerService.aidl \ -	media/java/android/media/IRemoteControlClient.aidl \ +	media/java/android/media/IRemoteControlClientDispatcher.aidl \  	telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \  	telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \  	telephony/java/com/android/internal/telephony/ITelephony.aidl \ diff --git a/CleanSpec.mk b/CleanSpec.mk index bf473148120e..25930652e51f 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -104,6 +104,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew  $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/nfc)  $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/SystemUI_intermediates)  $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/R/com/android/systemui/R.java) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IAudioService.P)  # ************************************************  # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST  # ************************************************ diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 7a92b35c4f62..f9efd3ca6a69 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -21,6 +21,7 @@ import android.annotation.SdkConstant.SdkConstantType;  import android.content.ComponentName;  import android.content.Context;  import android.database.ContentObserver; +import android.graphics.Bitmap;  import android.os.Binder;  import android.os.Handler;  import android.os.IBinder; @@ -1715,29 +1716,103 @@ public class AudioManager {      }      /** +     * Acts as a proxy between AudioService and the RemoteControlClient +     */ +    private IRemoteControlClientDispatcher mRcClientDispatcher = +            new IRemoteControlClientDispatcher.Stub() { + +        public String getMetadataStringForClient(String clientName, int field) { +            RemoteControlClient realClient; +            synchronized(mRcClientMap) { +                realClient = mRcClientMap.get(clientName); +            } +            if (realClient != null) { +                return realClient.getMetadataString(field); +            } else { +                return null; +            } +        } + +        public int getPlaybackStateForClient(String clientName) { +            RemoteControlClient realClient; +            synchronized(mRcClientMap) { +                realClient = mRcClientMap.get(clientName); +            } +            if (realClient != null) { +                return realClient.getPlaybackState(); +            } else { +                return 0; +            } +        } + +        public int getTransportControlFlagsForClient(String clientName) { +            RemoteControlClient realClient; +            synchronized(mRcClientMap) { +                realClient = mRcClientMap.get(clientName); +            } +            if (realClient != null) { +                return realClient.getTransportControlFlags(); +            } else { +                return 0; +            } +        } + +        public Bitmap getAlbumArtForClient(String clientName, int maxWidth, int maxHeight) { +            RemoteControlClient realClient; +            synchronized(mRcClientMap) { +                realClient = mRcClientMap.get(clientName); +            } +            if (realClient != null) { +                return realClient.getAlbumArt(maxWidth, maxHeight); +            } else { +                return null; +            } +        } +    }; + +    private HashMap<String, RemoteControlClient> mRcClientMap = +            new HashMap<String, RemoteControlClient>(); + +    private String getIdForRcClient(RemoteControlClient client) { +        // client is guaranteed to be non-null +        return client.toString(); +    } + +    /**       * @hide -     * Registers the remote control client for providing information to display on the remotes. +     * Registers the remote control client for providing information to display on the remote +     * controls.       * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}       *      that will receive the media button intent, and associated with the remote control       *      client. This method has no effect if       *      {@link #registerMediaButtonEventReceiver(ComponentName)} hasn't been called       *      with the same eventReceiver, or if       *      {@link #unregisterMediaButtonEventReceiver(ComponentName)} has been called. -     * @param rcClient the client associated with the event receiver, responsible for providing -     *      the information to display on the remote control. +     * @param rcClient the remote control client associated with the event receiver, responsible +     *      for providing the information to display on the remote control.       */      public void registerRemoteControlClient(ComponentName eventReceiver, -            IRemoteControlClient rcClient) { -        if (eventReceiver == null) { +            RemoteControlClient rcClient) { +        if ((eventReceiver == null) || (rcClient == null)) {              return;          } +        String clientKey = getIdForRcClient(rcClient); +        synchronized(mRcClientMap) { +            if (mRcClientMap.containsKey(clientKey)) { +                return; +            } +            mRcClientMap.put(clientKey, rcClient); +        }          IAudioService service = getService();          try { -            service.registerRemoteControlClient(eventReceiver, rcClient, +            service.registerRemoteControlClient(eventReceiver, mRcClientDispatcher, clientKey,                      // used to match media button event receiver and audio focus                      mContext.getPackageName());          } catch (RemoteException e) {              Log.e(TAG, "Dead object in registerRemoteControlClient"+e); +            synchronized(mRcClientMap) { +                mRcClientMap.remove(clientKey); +            }          }      } @@ -1748,17 +1823,28 @@ public class AudioManager {       * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}       *      that receives the media button intent, and associated with the remote control       *      client. -     * @see #registerRemoteControlClient(ComponentName) - +     * @param rcClient the remote control client to unregister +     * @see #registerRemoteControlClient(ComponentName, RemoteControlClient)       */ -    public void unregisterRemoteControlClient(ComponentName eventReceiver) { -        if (eventReceiver == null) { +    public void unregisterRemoteControlClient(ComponentName eventReceiver, +            RemoteControlClient rcClient) { +        if ((eventReceiver == null) || (rcClient == null)) {              return;          }          IAudioService service = getService();          try { -            // unregistering a IRemoteControlClient is equivalent to setting it to null -            service.registerRemoteControlClient(eventReceiver, null, mContext.getPackageName()); +            // remove locally +            boolean unregister = true; +            synchronized(mRcClientMap) { +                if (mRcClientMap.remove(getIdForRcClient(rcClient)) == null) { +                    unregister = false; +                } +            } +            if (unregister) { +                // unregistering a RemoteControlClient is equivalent to setting it to null +                service.registerRemoteControlClient(eventReceiver, null, null, +                        mContext.getPackageName()); +            }          } catch (RemoteException e) {              Log.e(TAG, "Dead object in unregisterRemoteControlClient"+e);          } @@ -1767,17 +1853,17 @@ public class AudioManager {      /**       * @hide       * Returns the current remote control client. -     * @param rcClientId the counter value that matches the extra -     *     {@link AudioManager#EXTRA_REMOTE_CONTROL_CLIENT} in the +     * @param rcClientId the generation counter that matches the extra +     *     {@link AudioManager#EXTRA_REMOTE_CONTROL_CLIENT_GENERATION} in the       *     {@link AudioManager#REMOTE_CONTROL_CLIENT_CHANGED} event -     * @return the current IRemoteControlClient from which information to display on the remote +     * @return the current RemoteControlClient from which information to display on the remote       *     control can be retrieved, or null if rcClientId doesn't match the current generation       *     counter.       */ -    public IRemoteControlClient getRemoteControlClient(int rcClientId) { +    public IRemoteControlClientDispatcher getRemoteControlClientDispatcher(int rcClientId) {          IAudioService service = getService();          try { -            return service.getRemoteControlClient(rcClientId); +            return service.getRemoteControlClientDispatcher(rcClientId);          } catch (RemoteException e) {              Log.e(TAG, "Dead object in getRemoteControlClient "+e);              return null; @@ -1786,160 +1872,6 @@ public class AudioManager {      /**       * @hide -     * Definitions of constants to be used in {@link android.media.IRemoteControlClient}. -     */ -    public final class RemoteControlParameters { -        /** -         * Playback state of an IRemoteControlClient which is stopped. -         * -         * @see android.media.IRemoteControlClient#getPlaybackState() -         */ -        public final static int PLAYSTATE_STOPPED            = 1; -        /** -         * Playback state of an IRemoteControlClient which is paused. -         * -         * @see android.media.IRemoteControlClient#getPlaybackState() -         */ -        public final static int PLAYSTATE_PAUSED             = 2; -        /** -         * Playback state of an IRemoteControlClient which is playing media. -         * -         * @see android.media.IRemoteControlClient#getPlaybackState() -         */ -        public final static int PLAYSTATE_PLAYING            = 3; -        /** -         * Playback state of an IRemoteControlClient which is fast forwarding in the media -         *    it is currently playing. -         * -         * @see android.media.IRemoteControlClient#getPlaybackState() -         */ -        public final static int PLAYSTATE_FAST_FORWARDING    = 4; -        /** -         * Playback state of an IRemoteControlClient which is fast rewinding in the media -         *    it is currently playing. -         * -         * @see android.media.IRemoteControlClient#getPlaybackState() -         */ -        public final static int PLAYSTATE_REWINDING          = 5; -        /** -         * Playback state of an IRemoteControlClient which is skipping to the next -         *    logical chapter (such as a song in a playlist) in the media it is currently playing. -         * -         * @see android.media.IRemoteControlClient#getPlaybackState() -         */ -        public final static int PLAYSTATE_SKIPPING_FORWARDS  = 6; -        /** -         * Playback state of an IRemoteControlClient which is skipping back to the previous -         *    logical chapter (such as a song in a playlist) in the media it is currently playing. -         * -         * @see android.media.IRemoteControlClient#getPlaybackState() -         */ -        public final static int PLAYSTATE_SKIPPING_BACKWARDS = 7; -        /** -         * Playback state of an IRemoteControlClient which is buffering data to play before it can -         *    start or resume playback. -         * -         * @see android.media.IRemoteControlClient#getPlaybackState() -         */ -        public final static int PLAYSTATE_BUFFERING          = 8; -        /** -         * Playback state of an IRemoteControlClient which cannot perform any playback related -         *    operation because of an internal error. Examples of such situations are no network -         *    connectivity when attempting to stream data from a server, or expired user credentials -         *    when trying to play subscription-based content. -         * -         * @see android.media.IRemoteControlClient#getPlaybackState() -         */ -        public final static int PLAYSTATE_ERROR              = 9; - -        /** -         * Flag indicating an IRemoteControlClient makes use of the "previous" media key. -         * -         * @see android.media.IRemoteControlClient#getTransportControlFlags() -         * @see android.view.KeyEvent#KEYCODE_MEDIA_PREVIOUS -         */ -        public final static int FLAG_KEY_MEDIA_PREVIOUS = 1 << 0; -        /** -         * Flag indicating an IRemoteControlClient makes use of the "rewing" media key. -         * -         * @see android.media.IRemoteControlClient#getTransportControlFlags() -         * @see android.view.KeyEvent#KEYCODE_MEDIA_REWIND -         */ -        public final static int FLAG_KEY_MEDIA_REWIND = 1 << 1; -        /** -         * Flag indicating an IRemoteControlClient makes use of the "play" media key. -         * -         * @see android.media.IRemoteControlClient#getTransportControlFlags() -         * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY -         */ -        public final static int FLAG_KEY_MEDIA_PLAY = 1 << 2; -        /** -         * Flag indicating an IRemoteControlClient makes use of the "play/pause" media key. -         * -         * @see android.media.IRemoteControlClient#getTransportControlFlags() -         * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE -         */ -        public final static int FLAG_KEY_MEDIA_PLAY_PAUSE = 1 << 3; -        /** -         * Flag indicating an IRemoteControlClient makes use of the "pause" media key. -         * -         * @see android.media.IRemoteControlClient#getTransportControlFlags() -         * @see android.view.KeyEvent#KEYCODE_MEDIA_PAUSE -         */ -        public final static int FLAG_KEY_MEDIA_PAUSE = 1 << 4; -        /** -         * Flag indicating an IRemoteControlClient makes use of the "stop" media key. -         * -         * @see android.media.IRemoteControlClient#getTransportControlFlags() -         * @see android.view.KeyEvent#KEYCODE_MEDIA_STOP -         */ -        public final static int FLAG_KEY_MEDIA_STOP = 1 << 5; -        /** -         * Flag indicating an IRemoteControlClient makes use of the "fast forward" media key. -         * -         * @see android.media.IRemoteControlClient#getTransportControlFlags() -         * @see android.view.KeyEvent#KEYCODE_MEDIA_FAST_FORWARD -         */ -        public final static int FLAG_KEY_MEDIA_FAST_FORWARD = 1 << 6; -        /** -         * Flag indicating an IRemoteControlClient makes use of the "next" media key. -         * -         * @see android.media.IRemoteControlClient#getTransportControlFlags() -         * @see android.view.KeyEvent#KEYCODE_MEDIA_NEXT -         */ -        public final static int FLAG_KEY_MEDIA_NEXT = 1 << 7; - -        /** -         * Flag used to signal that the metadata exposed by the IRemoteControlClient has changed. -         * -         * @see #notifyRemoteControlInformationChanged(ComponentName, int) -         */ -        public final static int FLAG_INFORMATION_CHANGED_METADATA = 1 << 0; -        /** -         * Flag used to signal that the transport control buttons supported by the -         * IRemoteControlClient have changed. -         * This can for instance happen when playback is at the end of a playlist, and the "next" -         * operation is not supported anymore. -         * -         * @see #notifyRemoteControlInformationChanged(ComponentName, int) -         */ -        public final static int FLAG_INFORMATION_CHANGED_KEY_MEDIA = 1 << 1; -        /** -         * Flag used to signal that the playback state of the IRemoteControlClient has changed. -         * -         * @see #notifyRemoteControlInformationChanged(ComponentName, int) -         */ -        public final static int FLAG_INFORMATION_CHANGED_PLAYSTATE = 1 << 2; -        /** -         * Flag used to signal that the album art for the IRemoteControlClient has changed. -         * -         * @see #notifyRemoteControlInformationChanged(ComponentName, int) -         */ -        public final static int FLAG_INFORMATION_CHANGED_ALBUM_ART = 1 << 3; -    } - -    /** -     * @hide       * Broadcast intent action indicating that the displays on the remote controls       * should be updated because a new remote control client is now active. If there is no       * {@link #EXTRA_REMOTE_CONTROL_CLIENT}, the remote control display should be cleared @@ -1952,16 +1884,27 @@ public class AudioManager {      /**       * @hide -     * The IRemoteControlClient monotonically increasing generation counter. +     * The IRemoteControlClientDispatcher monotonically increasing generation counter. +     * +     * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION +     */ +    public static final String EXTRA_REMOTE_CONTROL_CLIENT_GENERATION = +            "android.media.EXTRA_REMOTE_CONTROL_CLIENT_GENERATION"; + +    /** +     * @hide +     * The name of the RemoteControlClient. +     * This String is passed as the client name when calling methods from the +     * IRemoteControlClientDispatcher interface.       *       * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION       */ -    public static final String EXTRA_REMOTE_CONTROL_CLIENT = -            "android.media.EXTRA_REMOTE_CONTROL_CLIENT"; +    public static final String EXTRA_REMOTE_CONTROL_CLIENT_NAME = +            "android.media.EXTRA_REMOTE_CONTROL_CLIENT_NAME";      /**       * @hide -     * The media button event receiver associated with the IRemoteControlClient. +     * The media button event receiver associated with the RemoteControlClient.       * The {@link android.content.ComponentName} value of the event receiver can be retrieved with       * {@link android.content.ComponentName#unflattenFromString(String)}       * @@ -1992,10 +1935,10 @@ public class AudioManager {       * @param infoFlag the type of information that has changed since this method was last called,       *      or the event receiver was registered. Use one or multiple of the following flags to       *      describe what changed: -     *      {@link RemoteControlParameters#FLAG_INFORMATION_CHANGED_METADATA}, -     *      {@link RemoteControlParameters#FLAG_INFORMATION_CHANGED_KEY_MEDIA}, -     *      {@link RemoteControlParameters#FLAG_INFORMATION_CHANGED_PLAYSTATE}, -     *      {@link RemoteControlParameters#FLAG_INFORMATION_CHANGED_ALBUM_ART}. +     *      {@link RemoteControlClient#FLAG_INFORMATION_CHANGED_METADATA}, +     *      {@link RemoteControlClient#FLAG_INFORMATION_CHANGED_KEY_MEDIA}, +     *      {@link RemoteControlClient#FLAG_INFORMATION_CHANGED_PLAYSTATE}, +     *      {@link RemoteControlClient#FLAG_INFORMATION_CHANGED_ALBUM_ART}.       */      public void notifyRemoteControlInformationChanged(ComponentName eventReceiver, int infoFlag) {          IAudioService service = getService(); diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index d4ab9277cb77..85c7dba423d0 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -34,6 +34,7 @@ import android.content.pm.PackageManager;  import android.database.ContentObserver;  import android.media.MediaPlayer.OnCompletionListener;  import android.media.MediaPlayer.OnErrorListener; +import android.media.IRemoteControlClientDispatcher;  import android.os.Binder;  import android.os.Environment;  import android.os.Handler; @@ -2172,7 +2173,7 @@ public class AudioService extends IAudioService.Stub {                      // TODO remove log before release                      Log.i(TAG, "Clear remote control display");                      Intent clearIntent = new Intent(AudioManager.REMOTE_CONTROL_CLIENT_CHANGED); -                    // no extra means no IRemoteControlClient, which is a request to clear +                    // no extra means no IRemoteControlClientDispatcher, which is a request to clear                      clearIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);                      mContext.sendBroadcast(clearIntent);                      break; @@ -2192,7 +2193,8 @@ public class AudioService extends IAudioService.Stub {                              Log.i(TAG, "Display/update remote control ");                              Intent rcClientIntent = new Intent(                                      AudioManager.REMOTE_CONTROL_CLIENT_CHANGED); -                            rcClientIntent.putExtra(AudioManager.EXTRA_REMOTE_CONTROL_CLIENT, +                            rcClientIntent.putExtra( +                                    AudioManager.EXTRA_REMOTE_CONTROL_CLIENT_GENERATION,                                      mCurrentRcClientGen);                              rcClientIntent.putExtra(                                      AudioManager.EXTRA_REMOTE_CONTROL_CLIENT_INFO_CHANGED, @@ -2200,6 +2202,9 @@ public class AudioService extends IAudioService.Stub {                              rcClientIntent.putExtra(                                      AudioManager.EXTRA_REMOTE_CONTROL_EVENT_RECEIVER,                                      rcse.mReceiverComponent.flattenToString()); +                            rcClientIntent.putExtra( +                                    AudioManager.EXTRA_REMOTE_CONTROL_CLIENT_NAME, +                                    rcse.mRcClientName);                              rcClientIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);                              mContext.sendBroadcast(rcClientIntent);                          } @@ -2895,14 +2900,14 @@ public class AudioService extends IAudioService.Stub {       * This object may be null.       * Access protected by mCurrentRcLock.       */ -    private IRemoteControlClient mCurrentRcClient = null; +    private IRemoteControlClientDispatcher mCurrentRcClient = null;      private final static int RC_INFO_NONE = 0;      private final static int RC_INFO_ALL = -        AudioManager.RemoteControlParameters.FLAG_INFORMATION_CHANGED_ALBUM_ART | -        AudioManager.RemoteControlParameters.FLAG_INFORMATION_CHANGED_KEY_MEDIA | -        AudioManager.RemoteControlParameters.FLAG_INFORMATION_CHANGED_METADATA | -        AudioManager.RemoteControlParameters.FLAG_INFORMATION_CHANGED_PLAYSTATE; +        RemoteControlClient.FLAG_INFORMATION_CHANGED_ALBUM_ART | +        RemoteControlClient.FLAG_INFORMATION_CHANGED_KEY_MEDIA | +        RemoteControlClient.FLAG_INFORMATION_CHANGED_METADATA | +        RemoteControlClient.FLAG_INFORMATION_CHANGED_PLAYSTATE;      /**       * A monotonically increasing generation counter for mCurrentRcClient. @@ -2914,13 +2919,13 @@ public class AudioService extends IAudioService.Stub {      /**       * Returns the current remote control client.       * @param rcClientId the counter value that matches the extra -     *     {@link AudioManager#EXTRA_REMOTE_CONTROL_CLIENT} in the +     *     {@link AudioManager#EXTRA_REMOTE_CONTROL_CLIENT_GENERATION} in the       *     {@link AudioManager#REMOTE_CONTROL_CLIENT_CHANGED} event -     * @return the current IRemoteControlClient from which information to display on the remote -     *     control can be retrieved, or null if rcClientId doesn't match the current generation -     *     counter. +     * @return the current IRemoteControlClientDispatcher from which information to display on the +     *     remote control can be retrieved, or null if rcClientId doesn't match the current +     *     generation counter.       */ -    public IRemoteControlClient getRemoteControlClient(int rcClientId) { +    public IRemoteControlClientDispatcher getRemoteControlClientDispatcher(int rcClientId) {          synchronized(mCurrentRcLock) {              if (rcClientId == mCurrentRcClientGen) {                  return mCurrentRcClient; @@ -2947,7 +2952,7 @@ public class AudioService extends IAudioService.Stub {              Log.w(TAG, "  RemoteControlClient died");              // remote control client died, make sure the displays don't use it anymore              //  by setting its remote control client to null -            registerRemoteControlClient(mRcEventReceiver, null, null/*ignored*/); +            registerRemoteControlClient(mRcEventReceiver, null, null, null/*ignored*/);          }          public IBinder getBinder() { @@ -2959,10 +2964,11 @@ public class AudioService extends IAudioService.Stub {          /** the target for the ACTION_MEDIA_BUTTON events */          public ComponentName mReceiverComponent;// always non null          public String mCallingPackageName; +        public String mRcClientName;          public int mCallingUid;          /** provides access to the information to display on the remote control */ -        public IRemoteControlClient mRcClient; +        public IRemoteControlClientDispatcher mRcClient;          public RcClientDeathHandler mRcClientDeathHandler;          public RemoteControlStackEntry(ComponentName r) { @@ -3217,7 +3223,7 @@ public class AudioService extends IAudioService.Stub {      /** see AudioManager.registerRemoteControlClient(ComponentName eventReceiver, ...) */      public void registerRemoteControlClient(ComponentName eventReceiver, -            IRemoteControlClient rcClient, String callingPackageName) { +            IRemoteControlClientDispatcher rcClient, String clientName, String callingPackageName) {          synchronized(mAudioFocusLock) {              synchronized(mRCStack) {                  // store the new display information @@ -3233,8 +3239,10 @@ public class AudioService extends IAudioService.Stub {                          // save the new remote control client                          rcse.mRcClient = rcClient;                          rcse.mCallingPackageName = callingPackageName; +                        rcse.mRcClientName = clientName;                          rcse.mCallingUid = Binder.getCallingUid();                          if (rcClient == null) { +                            rcse.mRcClientDeathHandler = null;                              break;                          }                          // monitor the new client's death diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index c259aa34706b..7f9ced9f055e 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -18,9 +18,7 @@ package android.media;  import android.content.ComponentName;  import android.media.IAudioFocusDispatcher; -import android.media.IRemoteControlClient; -import android.net.Uri; -import android.os.Bundle; +import android.media.IRemoteControlClientDispatcher;  /**   * {@hide} @@ -91,9 +89,10 @@ interface IAudioService {      void unregisterMediaButtonEventReceiver(in ComponentName eventReceiver);      void registerRemoteControlClient(in ComponentName eventReceiver, -           in IRemoteControlClient rcClient, in String callingPackageName); +           in IRemoteControlClientDispatcher rcClient, in String clientName, +           in String callingPackageName); -    IRemoteControlClient getRemoteControlClient(in int rcClientId); +    IRemoteControlClientDispatcher getRemoteControlClientDispatcher(in int rcClientId);      void notifyRemoteControlInformationChanged(in ComponentName eventReceiver, int infoFlag); diff --git a/media/java/android/media/IRemoteControlClient.aidl b/media/java/android/media/IRemoteControlClientDispatcher.aidl index 76d178c16bcd..98142cc5dd9b 100644 --- a/media/java/android/media/IRemoteControlClient.aidl +++ b/media/java/android/media/IRemoteControlClientDispatcher.aidl @@ -20,13 +20,11 @@ import android.graphics.Bitmap;  /**   * @hide - * Interface for an object that exposes information meant to be consumed by remote controls - * capable of displaying metadata, album art and media transport control buttons. - * Such a remote control client object is associated with a media button event receiver - * when registered through - * {@link AudioManager#registerRemoteControlClient(ComponentName, IRemoteControlClient)}. + * Interface registered by AudioManager to dispatch remote control information requests + * to the RemoteControlClient implementation. This is used by AudioService. + * {@see AudioManager#registerRemoteControlClient(ComponentName, RemoteControlClient)}.   */ -interface IRemoteControlClient +interface IRemoteControlClientDispatcher  {      /**       * Called by a remote control to retrieve a String of information to display. @@ -49,7 +47,7 @@ interface IRemoteControlClient       * @return null if the requested field is not supported, or the String matching the       *       metadata field.       */ -    String getMetadataString(int field); +    String getMetadataStringForClient(String clientName, int field);      /**       * Called by a remote control to retrieve the current playback state. @@ -64,7 +62,7 @@ interface IRemoteControlClient       *       {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_BUFFERING},       *       {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_ERROR}.       */ -    int getPlaybackState(); +    int getPlaybackStateForClient(String clientName);      /**       * Called by a remote control to retrieve the flags for the media transport control buttons @@ -78,7 +76,7 @@ interface IRemoteControlClient       *      {@link android.media.AudioManager.RemoteControlParameters#FLAG_KEY_MEDIA_FAST_FORWARD},       *      {@link android.media.AudioManager.RemoteControlParameters#FLAG_KEY_MEDIA_NEXT}       */ -    int getTransportControlFlags(); +    int getTransportControlFlagsForClient(String clientName);      /**       * Called by a remote control to retrieve the album art picture at the requested size. @@ -90,5 +88,5 @@ interface IRemoteControlClient       * @return the bitmap for the album art, or null if there isn't any.       * @see android.graphics.Bitmap       */ -    Bitmap getAlbumArt(int maxWidth, int maxHeight); +    Bitmap getAlbumArtForClient(String clientName, int maxWidth, int maxHeight);  } diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java new file mode 100644 index 000000000000..c384636ae780 --- /dev/null +++ b/media/java/android/media/RemoteControlClient.java @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2011 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 android.media; + +import android.content.ComponentName; +import android.graphics.Bitmap; + +/** + * @hide + * Interface for an object that exposes information meant to be consumed by remote controls + * capable of displaying metadata, album art and media transport control buttons. + * Such a remote control client object is associated with a media button event receiver + * when registered through + * {@link AudioManager#registerRemoteControlClient(ComponentName, RemoteControlClient)}. + */ +public interface RemoteControlClient +{ +    /** +     * Playback state of a RemoteControlClient which is stopped. +     * +     * @see android.media.RemoteControlClient#getPlaybackState() +     */ +    public final static int PLAYSTATE_STOPPED            = 1; +    /** +     * Playback state of a RemoteControlClient which is paused. +     * +     * @see android.media.RemoteControlClient#getPlaybackState() +     */ +    public final static int PLAYSTATE_PAUSED             = 2; +    /** +     * Playback state of a RemoteControlClient which is playing media. +     * +     * @see android.media.RemoteControlClient#getPlaybackState() +     */ +    public final static int PLAYSTATE_PLAYING            = 3; +    /** +     * Playback state of a RemoteControlClient which is fast forwarding in the media +     *    it is currently playing. +     * +     * @see android.media.RemoteControlClient#getPlaybackState() +     */ +    public final static int PLAYSTATE_FAST_FORWARDING    = 4; +    /** +     * Playback state of a RemoteControlClient which is fast rewinding in the media +     *    it is currently playing. +     * +     * @see android.media.RemoteControlClient#getPlaybackState() +     */ +    public final static int PLAYSTATE_REWINDING          = 5; +    /** +     * Playback state of a RemoteControlClient which is skipping to the next +     *    logical chapter (such as a song in a playlist) in the media it is currently playing. +     * +     * @see android.media.RemoteControlClient#getPlaybackState() +     */ +    public final static int PLAYSTATE_SKIPPING_FORWARDS  = 6; +    /** +     * Playback state of a RemoteControlClient which is skipping back to the previous +     *    logical chapter (such as a song in a playlist) in the media it is currently playing. +     * +     * @see android.media.RemoteControlClient#getPlaybackState() +     */ +    public final static int PLAYSTATE_SKIPPING_BACKWARDS = 7; +    /** +     * Playback state of a RemoteControlClient which is buffering data to play before it can +     *    start or resume playback. +     * +     * @see android.media.RemoteControlClient#getPlaybackState() +     */ +    public final static int PLAYSTATE_BUFFERING          = 8; +    /** +     * Playback state of a RemoteControlClient which cannot perform any playback related +     *    operation because of an internal error. Examples of such situations are no network +     *    connectivity when attempting to stream data from a server, or expired user credentials +     *    when trying to play subscription-based content. +     * +     * @see android.media.RemoteControlClient#getPlaybackState() +     */ +    public final static int PLAYSTATE_ERROR              = 9; + +    /** +     * Flag indicating a RemoteControlClient makes use of the "previous" media key. +     * +     * @see android.media.RemoteControlClient#getTransportControlFlags() +     * @see android.view.KeyEvent#KEYCODE_MEDIA_PREVIOUS +     */ +    public final static int FLAG_KEY_MEDIA_PREVIOUS = 1 << 0; +    /** +     * Flag indicating a RemoteControlClient makes use of the "rewing" media key. +     * +     * @see android.media.RemoteControlClient#getTransportControlFlags() +     * @see android.view.KeyEvent#KEYCODE_MEDIA_REWIND +     */ +    public final static int FLAG_KEY_MEDIA_REWIND = 1 << 1; +    /** +     * Flag indicating a RemoteControlClient makes use of the "play" media key. +     * +     * @see android.media.RemoteControlClient#getTransportControlFlags() +     * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY +     */ +    public final static int FLAG_KEY_MEDIA_PLAY = 1 << 2; +    /** +     * Flag indicating a RemoteControlClient makes use of the "play/pause" media key. +     * +     * @see android.media.RemoteControlClient#getTransportControlFlags() +     * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE +     */ +    public final static int FLAG_KEY_MEDIA_PLAY_PAUSE = 1 << 3; +    /** +     * Flag indicating a RemoteControlClient makes use of the "pause" media key. +     * +     * @see android.media.RemoteControlClient#getTransportControlFlags() +     * @see android.view.KeyEvent#KEYCODE_MEDIA_PAUSE +     */ +    public final static int FLAG_KEY_MEDIA_PAUSE = 1 << 4; +    /** +     * Flag indicating a RemoteControlClient makes use of the "stop" media key. +     * +     * @see android.media.RemoteControlClient#getTransportControlFlags() +     * @see android.view.KeyEvent#KEYCODE_MEDIA_STOP +     */ +    public final static int FLAG_KEY_MEDIA_STOP = 1 << 5; +    /** +     * Flag indicating a RemoteControlClient makes use of the "fast forward" media key. +     * +     * @see android.media.RemoteControlClient#getTransportControlFlags() +     * @see android.view.KeyEvent#KEYCODE_MEDIA_FAST_FORWARD +     */ +    public final static int FLAG_KEY_MEDIA_FAST_FORWARD = 1 << 6; +    /** +     * Flag indicating a RemoteControlClient makes use of the "next" media key. +     * +     * @see android.media.RemoteControlClient#getTransportControlFlags() +     * @see android.view.KeyEvent#KEYCODE_MEDIA_NEXT +     */ +    public final static int FLAG_KEY_MEDIA_NEXT = 1 << 7; + +    /** +     * Flag used to signal that the metadata exposed by the RemoteControlClient has changed. +     * +     * @see #notifyRemoteControlInformationChanged(ComponentName, int) +     */ +    public final static int FLAG_INFORMATION_CHANGED_METADATA = 1 << 0; +    /** +     * Flag used to signal that the transport control buttons supported by the +     * RemoteControlClient have changed. +     * This can for instance happen when playback is at the end of a playlist, and the "next" +     * operation is not supported anymore. +     * +     * @see #notifyRemoteControlInformationChanged(ComponentName, int) +     */ +    public final static int FLAG_INFORMATION_CHANGED_KEY_MEDIA = 1 << 1; +    /** +     * Flag used to signal that the playback state of the RemoteControlClient has changed. +     * +     * @see #notifyRemoteControlInformationChanged(ComponentName, int) +     */ +    public final static int FLAG_INFORMATION_CHANGED_PLAYSTATE = 1 << 2; +    /** +     * Flag used to signal that the album art for the RemoteControlClient has changed. +     * +     * @see #notifyRemoteControlInformationChanged(ComponentName, int) +     */ +    public final static int FLAG_INFORMATION_CHANGED_ALBUM_ART = 1 << 3; + +    /** +     * Called by a remote control to retrieve a String of information to display. +     * @param field the identifier for a metadata field to retrieve. Valid values are +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUM}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUMARTIST}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_ARTIST}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_AUTHOR}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPILATION}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPOSER}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_DATE}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_GENRE}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_WRITER}, +     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_YEAR}. +     * @return null if the requested field is not supported, or the String matching the +     *       metadata field. +     */ +    String getMetadataString(int field); + +    /** +     * Called by a remote control to retrieve the current playback state. +     * @return one of the following values: +     *       {@link #PLAYSTATE_STOPPED}, +     *       {@link #PLAYSTATE_PAUSED}, +     *       {@link #PLAYSTATE_PLAYING}, +     *       {@link #PLAYSTATE_FAST_FORWARDING}, +     *       {@link #PLAYSTATE_REWINDING}, +     *       {@link #PLAYSTATE_SKIPPING_FORWARDS}, +     *       {@link #PLAYSTATE_SKIPPING_BACKWARDS}, +     *       {@link #PLAYSTATE_BUFFERING}, +     *       {@link #PLAYSTATE_ERROR}. +     */ +    int getPlaybackState(); + +    /** +     * Called by a remote control to retrieve the flags for the media transport control buttons +     * that this client supports. +     * @see {@link #FLAG_KEY_MEDIA_PREVIOUS}, +     *      {@link #FLAG_KEY_MEDIA_REWIND}, +     *      {@link #FLAG_KEY_MEDIA_PLAY}, +     *      {@link #FLAG_KEY_MEDIA_PLAY_PAUSE}, +     *      {@link #FLAG_KEY_MEDIA_PAUSE}, +     *      {@link #FLAG_KEY_MEDIA_STOP}, +     *      {@link #FLAG_KEY_MEDIA_FAST_FORWARD}, +     *      {@link #FLAG_KEY_MEDIA_NEXT} +     */ +    int getTransportControlFlags(); + +    /** +     * Called by a remote control to retrieve the album art picture at the requested size. +     * Note that returning a bitmap smaller than the maximum requested dimension is accepted +     * and it will be scaled as needed, but exceeding the maximum dimensions may produce +     * unspecified results, such as the image being cropped or simply not being displayed. +     * @param maxWidth the maximum width of the requested bitmap expressed in pixels. +     * @param maxHeight the maximum height of the requested bitmap expressed in pixels. +     * @return the bitmap for the album art, or null if there isn't any. +     * @see android.graphics.Bitmap +     */ +    Bitmap getAlbumArt(int maxWidth, int maxHeight); +}  |