Merge "Bug 5300223 RemoteControlClient uses PendingIntent for media button events" into ics-factoryrom
diff --git a/core/java/com/android/internal/widget/TransportControlView.java b/core/java/com/android/internal/widget/TransportControlView.java
index 29ad15b..f9c2cce 100644
--- a/core/java/com/android/internal/widget/TransportControlView.java
+++ b/core/java/com/android/internal/widget/TransportControlView.java
@@ -21,6 +21,8 @@
import com.android.internal.widget.LockScreenWidgetCallback;
import com.android.internal.widget.LockScreenWidgetInterface;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -68,7 +70,7 @@
private int mClientGeneration;
private Metadata mMetadata = new Metadata();
private boolean mAttached;
- private ComponentName mClientName;
+ private PendingIntent mClientIntent;
private int mTransportControlFlags;
private int mPlayState;
private AudioManager mAudioManager;
@@ -116,7 +118,7 @@
}
}
mClientGeneration = msg.arg1;
- mClientName = (ComponentName) msg.obj;
+ mClientIntent = (PendingIntent) msg.obj;
break;
}
@@ -174,12 +176,12 @@
}
}
- public void setCurrentClientId(int clientGeneration, ComponentName clientEventReceiver,
+ public void setCurrentClientId(int clientGeneration, PendingIntent mediaIntent,
boolean clearing) throws RemoteException {
Handler handler = mLocalHandler.get();
if (handler != null) {
handler.obtainMessage(MSG_SET_GENERATION_ID,
- clientGeneration, (clearing ? 1 : 0), clientEventReceiver).sendToTarget();
+ clientGeneration, (clearing ? 1 : 0), mediaIntent).sendToTarget();
}
}
};
@@ -365,16 +367,27 @@
}
private void sendMediaButtonClick(int keyCode) {
- // TODO: target to specific player based on mClientName
+ // use the registered PendingIntent that will be processed by the registered
+ // media button event receiver, which is the component of mClientIntent
KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
- getContext().sendOrderedBroadcast(intent, null);
+ try {
+ mClientIntent.send(getContext(), 0, intent);
+ } catch (CanceledException e) {
+ Log.e(TAG, "Error sending intent for media button down: "+e);
+ e.printStackTrace();
+ }
keyEvent = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
- getContext().sendOrderedBroadcast(intent, null);
+ try {
+ mClientIntent.send(getContext(), 0, intent);
+ } catch (CanceledException e) {
+ Log.e(TAG, "Error sending intent for media button up: "+e);
+ e.printStackTrace();
+ }
}
public void setCallback(LockScreenWidgetCallback callback) {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index cd8bb1d..a0881a7 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -18,8 +18,10 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.os.Binder;
@@ -1684,17 +1686,42 @@
* Register a component to be the sole receiver of MEDIA_BUTTON intents.
* @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
* that will receive the media button intent. This broadcast receiver must be declared
- * in the application manifest.
+ * in the application manifest. The package of the component must match that of
+ * the context you're registering from.
*/
public void registerMediaButtonEventReceiver(ComponentName eventReceiver) {
if (eventReceiver == null) {
return;
}
+ if (!eventReceiver.getPackageName().equals(mContext.getPackageName())) {
+ Log.e(TAG, "registerMediaButtonEventReceiver() error: " +
+ "receiver and context package names don't match");
+ return;
+ }
+ // construct a PendingIntent for the media button and register it
+ Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+ // the associated intent will be handled by the component being registered
+ mediaButtonIntent.setComponent(eventReceiver);
+ PendingIntent pi = PendingIntent.getBroadcast(mContext,
+ 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
+ registerMediaButtonIntent(pi, eventReceiver);
+ }
+
+ /**
+ * @hide
+ * no-op if (pi == null) or (eventReceiver == null)
+ */
+ public void registerMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver) {
+ if ((pi == null) || (eventReceiver == null)) {
+ Log.e(TAG, "Cannot call registerMediaButtonIntent() with a null parameter");
+ return;
+ }
IAudioService service = getService();
try {
- service.registerMediaButtonEventReceiver(eventReceiver);
+ // pi != null
+ service.registerMediaButtonIntent(pi, eventReceiver);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in registerMediaButtonEventReceiver"+e);
+ Log.e(TAG, "Dead object in registerMediaButtonIntent"+e);
}
}
@@ -1707,14 +1734,26 @@
if (eventReceiver == null) {
return;
}
- IAudioService service = getService();
- try {
- service.unregisterMediaButtonEventReceiver(eventReceiver);
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in unregisterMediaButtonEventReceiver"+e);
- }
+ // construct a PendingIntent for the media button and unregister it
+ Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+ // the associated intent will be handled by the component being registered
+ mediaButtonIntent.setComponent(eventReceiver);
+ PendingIntent pi = PendingIntent.getBroadcast(mContext,
+ 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
+ unregisterMediaButtonIntent(pi, eventReceiver);
}
+ /**
+ * @hide
+ */
+ public void unregisterMediaButtonIntent(PendingIntent pi, ComponentName eventReceiver) {
+ IAudioService service = getService();
+ try {
+ service.unregisterMediaButtonIntent(pi, eventReceiver);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in unregisterMediaButtonIntent"+e);
+ }
+ }
/**
* Registers the remote control client for providing information to display on the remote
@@ -1724,14 +1763,13 @@
* @see RemoteControlClient
*/
public void registerRemoteControlClient(RemoteControlClient rcClient) {
- if ((rcClient == null) || (rcClient.getRcEventReceiver() == null)) {
+ if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) {
return;
}
IAudioService service = getService();
try {
- service.registerRemoteControlClient(rcClient.getRcEventReceiver(), /* eventReceiver */
+ service.registerRemoteControlClient(rcClient.getRcMediaIntent(), /* mediaIntent */
rcClient.getIRemoteControlClient(), /* rcClient */
- rcClient.toString(), /* clientName */
// used to match media button event receiver and audio focus
mContext.getPackageName()); /* packageName */
} catch (RemoteException e) {
@@ -1746,13 +1784,13 @@
* @see #registerRemoteControlClient(RemoteControlClient)
*/
public void unregisterRemoteControlClient(RemoteControlClient rcClient) {
- if ((rcClient == null) || (rcClient.getRcEventReceiver() == null)) {
+ if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) {
return;
}
IAudioService service = getService();
try {
- service.unregisterRemoteControlClient(rcClient.getRcEventReceiver(), /* eventReceiver */
- rcClient.getIRemoteControlClient()); /* rcClient */
+ service.unregisterRemoteControlClient(rcClient.getRcMediaIntent(), /* mediaIntent */
+ rcClient.getIRemoteControlClient()); /* rcClient */
} catch (RemoteException e) {
Log.e(TAG, "Dead object in unregisterRemoteControlClient"+e);
}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index db27cfd..8895c9e 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -18,6 +18,8 @@
import android.app.ActivityManagerNative;
import android.app.KeyguardManager;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
@@ -35,6 +37,7 @@
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Binder;
+import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
@@ -2084,7 +2087,7 @@
}
}
- private void persistMediaButtonReceiver(ComponentName receiver) {
+ private void onHandlePersistMediaButtonReceiver(ComponentName receiver) {
Settings.System.putString(mContentResolver, Settings.System.MEDIA_BUTTON_RECEIVER,
receiver == null ? "" : receiver.flattenToString());
}
@@ -2201,7 +2204,7 @@
break;
case MSG_PERSIST_MEDIABUTTONRECEIVER:
- persistMediaButtonReceiver( (ComponentName) msg.obj );
+ onHandlePersistMediaButtonReceiver( (ComponentName) msg.obj );
break;
case MSG_RCDISPLAY_CLEAR:
@@ -2894,14 +2897,22 @@
}
synchronized(mRCStack) {
if (!mRCStack.empty()) {
- // create a new intent specifically aimed at the current registered listener
+ // create a new intent to fill in the extras of the registered PendingIntent
Intent targetedIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
- targetedIntent.putExtras(intent.getExtras());
- targetedIntent.setComponent(mRCStack.peek().mReceiverComponent);
- // trap the current broadcast
- abortBroadcast();
- //Log.v(TAG, " Sending intent" + targetedIntent);
- context.sendBroadcast(targetedIntent, null);
+ Bundle extras = intent.getExtras();
+ if (extras != null) {
+ targetedIntent.putExtras(extras);
+ // trap the current broadcast
+ abortBroadcast();
+ //Log.v(TAG, " Sending intent" + targetedIntent);
+ // send the intent that was registered by the client
+ try {
+ mRCStack.peek().mMediaIntent.send(context, 0, targetedIntent);
+ } catch (CanceledException e) {
+ Log.e(TAG, "Error sending pending intent " + mRCStack.peek());
+ e.printStackTrace();
+ }
+ }
}
}
}
@@ -2936,18 +2947,18 @@
*/
private class RcClientDeathHandler implements IBinder.DeathRecipient {
private IBinder mCb; // To be notified of client's death
- private ComponentName mRcEventReceiver;
+ private PendingIntent mMediaIntent;
- RcClientDeathHandler(IBinder cb, ComponentName eventReceiver) {
+ RcClientDeathHandler(IBinder cb, PendingIntent pi) {
mCb = cb;
- mRcEventReceiver = eventReceiver;
+ mMediaIntent = pi;
}
public void binderDied() {
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, null/*ignored*/);
+ registerRemoteControlClient(mMediaIntent, null, null/*ignored*/);
}
public IBinder getBinder() {
@@ -2956,18 +2967,29 @@
}
private static class RemoteControlStackEntry {
- /** the target for the ACTION_MEDIA_BUTTON events */
- public ComponentName mReceiverComponent;// always non null
+ /**
+ * The target for the ACTION_MEDIA_BUTTON events.
+ * Always non null.
+ */
+ public PendingIntent mMediaIntent;
+ /**
+ * The registered media button event receiver.
+ * Always non null.
+ */
+ public ComponentName mReceiverComponent;
public String mCallingPackageName;
- public String mRcClientName;
public int mCallingUid;
-
- /** provides access to the information to display on the remote control */
+ /**
+ * Provides access to the information to display on the remote control.
+ * May be null (when a media button event receiver is registered,
+ * but no remote control client has been registered) */
public IRemoteControlClient mRcClient;
public RcClientDeathHandler mRcClientDeathHandler;
- public RemoteControlStackEntry(ComponentName r) {
- mReceiverComponent = r;
+ /** precondition: mediaIntent != null, eventReceiver != null */
+ public RemoteControlStackEntry(PendingIntent mediaIntent, ComponentName eventReceiver) {
+ mMediaIntent = mediaIntent;
+ mReceiverComponent = eventReceiver;
mCallingUid = -1;
mRcClient = null;
}
@@ -3003,7 +3025,8 @@
Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
while(stackIterator.hasNext()) {
RemoteControlStackEntry rcse = stackIterator.next();
- pw.println(" receiver: " + rcse.mReceiverComponent +
+ pw.println(" pi: " + rcse.mMediaIntent +
+ " -- ercvr: " + rcse.mReceiverComponent +
" -- client: " + rcse.mRcClient +
" -- uid: " + rcse.mCallingUid);
}
@@ -3035,7 +3058,6 @@
mAudioHandler.sendMessage(
mAudioHandler.obtainMessage(MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0,
null));
- return;
} else if (oldTop != mRCStack.peek()) {
// the top of the stack has changed, save it in the system settings
// by posting a message to persist it
@@ -3049,25 +3071,32 @@
/**
* Helper function:
- * Restore remote control receiver from the system settings
+ * Restore remote control receiver from the system settings.
*/
private void restoreMediaButtonReceiver() {
String receiverName = Settings.System.getString(mContentResolver,
Settings.System.MEDIA_BUTTON_RECEIVER);
if ((null != receiverName) && !receiverName.isEmpty()) {
- ComponentName receiverComponentName = ComponentName.unflattenFromString(receiverName);
- registerMediaButtonEventReceiver(receiverComponentName);
+ ComponentName eventReceiver = ComponentName.unflattenFromString(receiverName);
+ // construct a PendingIntent targeted to the restored component name
+ // for the media button and register it
+ Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+ // the associated intent will be handled by the component being registered
+ mediaButtonIntent.setComponent(eventReceiver);
+ PendingIntent pi = PendingIntent.getBroadcast(mContext,
+ 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
+ registerMediaButtonIntent(pi, eventReceiver);
}
- // upon restoring (e.g. after boot), do we want to refresh all remotes?
}
/**
* Helper function:
- * Set the new remote control receiver at the top of the RC focus stack
+ * Set the new remote control receiver at the top of the RC focus stack.
+ * precondition: mediaIntent != null, target != null
*/
- private void pushMediaButtonReceiver(ComponentName newReceiver) {
+ private void pushMediaButtonReceiver(PendingIntent mediaIntent, ComponentName target) {
// already at top of stack?
- if (!mRCStack.empty() && mRCStack.peek().mReceiverComponent.equals(newReceiver)) {
+ if (!mRCStack.empty() && mRCStack.peek().mMediaIntent.equals(mediaIntent)) {
return;
}
Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
@@ -3075,31 +3104,32 @@
boolean wasInsideStack = false;
while(stackIterator.hasNext()) {
rcse = (RemoteControlStackEntry)stackIterator.next();
- if(rcse.mReceiverComponent.equals(newReceiver)) {
+ if(rcse.mMediaIntent.equals(mediaIntent)) {
wasInsideStack = true;
stackIterator.remove();
break;
}
}
if (!wasInsideStack) {
- rcse = new RemoteControlStackEntry(newReceiver);
+ rcse = new RemoteControlStackEntry(mediaIntent, target);
}
mRCStack.push(rcse);
// post message to persist the default media button receiver
mAudioHandler.sendMessage( mAudioHandler.obtainMessage(
- MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, newReceiver/*obj*/) );
+ MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, target/*obj*/) );
}
/**
* Helper function:
- * Remove the remote control receiver from the RC focus stack
+ * Remove the remote control receiver from the RC focus stack.
+ * precondition: pi != null
*/
- private void removeMediaButtonReceiver(ComponentName newReceiver) {
+ private void removeMediaButtonReceiver(PendingIntent pi) {
Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
while(stackIterator.hasNext()) {
RemoteControlStackEntry rcse = (RemoteControlStackEntry)stackIterator.next();
- if(rcse.mReceiverComponent.equals(newReceiver)) {
+ if(rcse.mMediaIntent.equals(pi)) {
stackIterator.remove();
break;
}
@@ -3110,8 +3140,8 @@
* Helper function:
* Called synchronized on mRCStack
*/
- private boolean isCurrentRcController(ComponentName eventReceiver) {
- if (!mRCStack.empty() && mRCStack.peek().mReceiverComponent.equals(eventReceiver)) {
+ private boolean isCurrentRcController(PendingIntent pi) {
+ if (!mRCStack.empty() && mRCStack.peek().mMediaIntent.equals(pi)) {
return true;
}
return false;
@@ -3124,12 +3154,12 @@
* Update the remote control displays with the new "focused" client generation
*/
private void setNewRcClientOnDisplays_syncRcsCurrc(int newClientGeneration,
- ComponentName newClientEventReceiver, boolean clearing) {
+ PendingIntent newMediaIntent, boolean clearing) {
// NOTE: Only one IRemoteControlDisplay supported in this implementation
if (mRcDisplay != null) {
try {
mRcDisplay.setCurrentClientId(
- newClientGeneration, newClientEventReceiver, clearing);
+ newClientGeneration, newMediaIntent, clearing);
} catch (RemoteException e) {
Log.e(TAG, "Dead display in setNewRcClientOnDisplays_syncRcsCurrc() "+e);
// if we had a display before, stop monitoring its death
@@ -3167,10 +3197,9 @@
* where the display should be cleared.
*/
private void setNewRcClient_syncRcsCurrc(int newClientGeneration,
- ComponentName newClientEventReceiver, boolean clearing) {
+ PendingIntent newMediaIntent, boolean clearing) {
// send the new valid client generation ID to all displays
- setNewRcClientOnDisplays_syncRcsCurrc(newClientGeneration, newClientEventReceiver,
- clearing);
+ setNewRcClientOnDisplays_syncRcsCurrc(newClientGeneration, newMediaIntent, clearing);
// send the new valid client generation ID to all clients
setNewRcClientGenerationOnClients_syncRcsCurrc(newClientGeneration);
}
@@ -3186,7 +3215,7 @@
mCurrentRcClientGen++;
// synchronously update the displays and clients with the new client generation
setNewRcClient_syncRcsCurrc(mCurrentRcClientGen,
- null /*event receiver*/, true /*clearing*/);
+ null /*newMediaIntent*/, true /*clearing*/);
}
}
}
@@ -3204,7 +3233,7 @@
// synchronously update the displays and clients with
// the new client generation
setNewRcClient_syncRcsCurrc(mCurrentRcClientGen,
- rcse.mReceiverComponent /*event receiver*/,
+ rcse.mMediaIntent /*newMediaIntent*/,
false /*clearing*/);
// tell the current client that it needs to send info
@@ -3301,27 +3330,34 @@
updateRemoteControlDisplay_syncAfRcs(infoChangedFlags);
}
- /** see AudioManager.registerMediaButtonEventReceiver(ComponentName eventReceiver) */
- public void registerMediaButtonEventReceiver(ComponentName eventReceiver) {
- Log.i(TAG, " Remote Control registerMediaButtonEventReceiver() for " + eventReceiver);
+ /**
+ * see AudioManager.registerMediaButtonIntent(PendingIntent pi, ComponentName c)
+ * precondition: mediaIntent != null, target != null
+ */
+ public void registerMediaButtonIntent(PendingIntent mediaIntent, ComponentName eventReceiver) {
+ Log.i(TAG, " Remote Control registerMediaButtonIntent() for " + mediaIntent);
synchronized(mAudioFocusLock) {
synchronized(mRCStack) {
- pushMediaButtonReceiver(eventReceiver);
+ pushMediaButtonReceiver(mediaIntent, eventReceiver);
// new RC client, assume every type of information shall be queried
checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
}
}
}
- /** see AudioManager.unregisterMediaButtonEventReceiver(ComponentName eventReceiver) */
- public void unregisterMediaButtonEventReceiver(ComponentName eventReceiver) {
- Log.i(TAG, " Remote Control unregisterMediaButtonEventReceiver() for " + eventReceiver);
+ /**
+ * see AudioManager.unregisterMediaButtonIntent(PendingIntent mediaIntent)
+ * precondition: mediaIntent != null, eventReceiver != null
+ */
+ public void unregisterMediaButtonIntent(PendingIntent mediaIntent, ComponentName eventReceiver)
+ {
+ Log.i(TAG, " Remote Control unregisterMediaButtonIntent() for " + mediaIntent);
synchronized(mAudioFocusLock) {
synchronized(mRCStack) {
- boolean topOfStackWillChange = isCurrentRcController(eventReceiver);
- removeMediaButtonReceiver(eventReceiver);
+ boolean topOfStackWillChange = isCurrentRcController(mediaIntent);
+ removeMediaButtonReceiver(mediaIntent);
if (topOfStackWillChange) {
// current RC client will change, assume every type of info needs to be queried
checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
@@ -3331,8 +3367,8 @@
}
/** see AudioManager.registerRemoteControlClient(ComponentName eventReceiver, ...) */
- public void registerRemoteControlClient(ComponentName eventReceiver,
- IRemoteControlClient rcClient, String clientName, String callingPackageName) {
+ public void registerRemoteControlClient(PendingIntent mediaIntent,
+ IRemoteControlClient rcClient, String callingPackageName) {
if (DEBUG_RC) Log.i(TAG, "Register remote control client rcClient="+rcClient);
synchronized(mAudioFocusLock) {
synchronized(mRCStack) {
@@ -3340,7 +3376,7 @@
Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
while(stackIterator.hasNext()) {
RemoteControlStackEntry rcse = stackIterator.next();
- if(rcse.mReceiverComponent.equals(eventReceiver)) {
+ if(rcse.mMediaIntent.equals(mediaIntent)) {
// already had a remote control client?
if (rcse.mRcClientDeathHandler != null) {
// stop monitoring the old client's death
@@ -3357,7 +3393,6 @@
}
}
rcse.mCallingPackageName = callingPackageName;
- rcse.mRcClientName = clientName;
rcse.mCallingUid = Binder.getCallingUid();
if (rcClient == null) {
rcse.mRcClientDeathHandler = null;
@@ -3366,7 +3401,7 @@
// monitor the new client's death
IBinder b = rcClient.asBinder();
RcClientDeathHandler rcdh =
- new RcClientDeathHandler(b, rcse.mReceiverComponent);
+ new RcClientDeathHandler(b, rcse.mMediaIntent);
try {
b.linkToDeath(rcdh, 0);
} catch (RemoteException e) {
@@ -3380,7 +3415,7 @@
}
// if the eventReceiver is at the top of the stack
// then check for potential refresh of the remote controls
- if (isCurrentRcController(eventReceiver)) {
+ if (isCurrentRcController(mediaIntent)) {
checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
}
}
@@ -3388,24 +3423,23 @@
}
/**
- * see AudioManager.unregisterRemoteControlClient(ComponentName eventReceiver, ...)
+ * see AudioManager.unregisterRemoteControlClient(PendingIntent pi, ...)
* rcClient is guaranteed non-null
*/
- public void unregisterRemoteControlClient(ComponentName eventReceiver,
+ public void unregisterRemoteControlClient(PendingIntent mediaIntent,
IRemoteControlClient rcClient) {
synchronized(mAudioFocusLock) {
synchronized(mRCStack) {
Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
while(stackIterator.hasNext()) {
RemoteControlStackEntry rcse = stackIterator.next();
- if ((rcse.mReceiverComponent.equals(eventReceiver))
+ if ((rcse.mMediaIntent.equals(mediaIntent))
&& rcClient.equals(rcse.mRcClient)) {
// we found the IRemoteControlClient to unregister
// stop monitoring its death
rcse.unlinkToRcClientDeath();
// reset the client-related fields
rcse.mRcClient = null;
- rcse.mRcClientName = null;
rcse.mRcClientDeathHandler = null;
rcse.mCallingPackageName = null;
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 7bf9814..5294d36 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -16,6 +16,7 @@
package android.media;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.media.IAudioFocusDispatcher;
import android.media.IRemoteControlClient;
@@ -85,13 +86,12 @@
void unregisterAudioFocusClient(String clientId);
- void registerMediaButtonEventReceiver(in ComponentName eventReceiver);
+ oneway void registerMediaButtonIntent(in PendingIntent pi, in ComponentName c);
+ oneway void unregisterMediaButtonIntent(in PendingIntent pi, in ComponentName c);
- void unregisterMediaButtonEventReceiver(in ComponentName eventReceiver);
-
- oneway void registerRemoteControlClient(in ComponentName eventReceiver,
- in IRemoteControlClient rcClient, in String clientName, in String callingPackageName);
- oneway void unregisterRemoteControlClient(in ComponentName eventReceiver,
+ oneway void registerRemoteControlClient(in PendingIntent mediaIntent,
+ in IRemoteControlClient rcClient, in String callingPackageName);
+ oneway void unregisterRemoteControlClient(in PendingIntent mediaIntent,
in IRemoteControlClient rcClient);
oneway void registerRemoteControlDisplay(in IRemoteControlDisplay rcd);
diff --git a/media/java/android/media/IRemoteControlDisplay.aidl b/media/java/android/media/IRemoteControlDisplay.aidl
index fd50b7e..e15b07c 100644
--- a/media/java/android/media/IRemoteControlDisplay.aidl
+++ b/media/java/android/media/IRemoteControlDisplay.aidl
@@ -16,6 +16,7 @@
package android.media;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.graphics.Bitmap;
import android.os.Bundle;
@@ -31,14 +32,12 @@
/**
* Sets the generation counter of the current client that is displayed on the remote control.
* @param clientGeneration the new RemoteControlClient generation
- * @param clientEventReceiver the media button event receiver associated with the client.
- * May be null, which implies there is no registered media button event receiver. This
- * parameter is supplied as an optimization so a display can directly target media button
- * events to the client.
+ * @param clientMediaIntent the PendingIntent associated with the client.
+ * May be null, which implies there is no registered media button event receiver.
* @param clearing true if the new client generation value maps to a remote control update
* where the display should be cleared.
*/
- void setCurrentClientId(int clientGeneration, in ComponentName clientEventReceiver,
+ void setCurrentClientId(int clientGeneration, in PendingIntent clientMediaIntent,
boolean clearing);
void setPlaybackState(int generationId, int state);
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index cdebba0..5dea87f 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -34,6 +34,7 @@
import java.lang.IllegalArgumentException;
/**
+ * TODO javadoc update for ComponentName - PendingIntent change
* RemoteControlClient enables exposing information meant to be consumed by remote controls
* capable of displaying metadata, artwork and media transport control buttons.
* A remote control client object is associated with a media button event receiver. This
@@ -205,50 +206,6 @@
public final static int FLAG_INFORMATION_REQUEST_ALBUM_ART = 1 << 3;
/**
- * @hide
- * TODO remove after modifying known (internal) media apps using this API
- * Class constructor.
- * @param mediaButtonEventReceiver The receiver for the media button events. It needs to have
- * been registered with {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)}
- * before this new RemoteControlClient can itself be registered with
- * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}.
- * @see AudioManager#registerMediaButtonEventReceiver(ComponentName)
- * @see AudioManager#registerRemoteControlClient(RemoteControlClient)
- */
- public RemoteControlClient(ComponentName mediaButtonEventReceiver) {
- mRcEventReceiver = mediaButtonEventReceiver;
-
- Looper looper;
- if ((looper = Looper.myLooper()) != null) {
- mEventHandler = new EventHandler(this, looper);
- } else if ((looper = Looper.getMainLooper()) != null) {
- mEventHandler = new EventHandler(this, looper);
- } else {
- mEventHandler = null;
- Log.e(TAG, "RemoteControlClient() couldn't find main application thread");
- }
- }
-
- /**
- * @hide
- * TODO remove after modifying known (internal) media apps using this API
- * Class constructor for a remote control client whose internal event handling
- * happens on a user-provided Looper.
- * @param mediaButtonEventReceiver The receiver for the media button events. It needs to have
- * been registered with {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)}
- * before this new RemoteControlClient can itself be registered with
- * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}.
- * @param looper The Looper running the event loop.
- * @see AudioManager#registerMediaButtonEventReceiver(ComponentName)
- * @see AudioManager#registerRemoteControlClient(RemoteControlClient)
- */
- public RemoteControlClient(ComponentName mediaButtonEventReceiver, Looper looper) {
- mRcEventReceiver = mediaButtonEventReceiver;
-
- mEventHandler = new EventHandler(this, looper);
- }
-
- /**
* Class constructor.
* @param mediaButtonIntent The intent that will be sent for the media button events sent
* by remote controls.
@@ -262,8 +219,7 @@
* @see AudioManager#registerRemoteControlClient(RemoteControlClient)
*/
public RemoteControlClient(PendingIntent mediaButtonIntent) {
- // TODO implement using PendingIntent instead of ComponentName
- mRcEventReceiver = null;
+ mRcMediaIntent = mediaButtonIntent;
Looper looper;
if ((looper = Looper.myLooper()) != null) {
@@ -292,8 +248,7 @@
* @see AudioManager#registerRemoteControlClient(RemoteControlClient)
*/
public RemoteControlClient(PendingIntent mediaButtonIntent, Looper looper) {
- // TODO implement using PendingIntent instead of ComponentName
- mRcEventReceiver = null;
+ mRcMediaIntent = mediaButtonIntent;
mEventHandler = new EventHandler(this, looper);
}
@@ -614,9 +569,10 @@
private int mInternalClientGenId = -2;
/**
- * The media button event receiver associated with this remote control client
+ * The media button intent description associated with this remote control client
+ * (can / should include target component for intent handling)
*/
- private final ComponentName mRcEventReceiver;
+ private final PendingIntent mRcMediaIntent;
/**
* The remote control display to which this client will send information.
@@ -626,10 +582,10 @@
/**
* @hide
- * Accessor to media button event receiver
+ * Accessor to media button intent description (includes target component)
*/
- public ComponentName getRcEventReceiver() {
- return mRcEventReceiver;
+ public PendingIntent getRcMediaIntent() {
+ return mRcMediaIntent;
}
/**
* @hide