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
@@ -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 bf47314..2593065 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 7a92b35..f9efd3c 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 d4ab927..85c7dba 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 c259aa3..7f9ced9 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 76d178c..98142cc 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 0000000..c384636 --- /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); +} |