Merge "Differentiate MediaController in a process for MediaSession" into pi-dev

This commit is contained in:
TreeHugger Robot
2018-05-22 00:11:49 +00:00
committed by Android (Google) Code Review
8 changed files with 513 additions and 418 deletions

View File

@@ -171,7 +171,6 @@ public class Media extends BaseCommand {
showError("Error: unknown dispatch code '" + cmd + "'"); showError("Error: unknown dispatch code '" + cmd + "'");
return; return;
} }
final long now = SystemClock.uptimeMillis(); final long now = SystemClock.uptimeMillis();
sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0, 0, sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD)); KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
@@ -189,7 +188,6 @@ public class Media extends BaseCommand {
@Override @Override
public void onSessionDestroyed() { public void onSessionDestroyed() {
System.out.println("onSessionDestroyed. Enter q to quit."); System.out.println("onSessionDestroyed. Enter q to quit.");
} }
@Override @Override
@@ -246,7 +244,7 @@ public class Media extends BaseCommand {
@Override @Override
protected void onLooperPrepared() { protected void onLooperPrepared() {
try { try {
mController.registerCallbackListener(ControllerMonitor.this); mController.registerCallbackListener(PACKAGE_NAME, ControllerMonitor.this);
} catch (RemoteException e) { } catch (RemoteException e) {
System.out.println("Error registering monitor callback"); System.out.println("Error registering monitor callback");
} }
@@ -266,13 +264,13 @@ public class Media extends BaseCommand {
} else if ("q".equals(line) || "quit".equals(line)) { } else if ("q".equals(line) || "quit".equals(line)) {
break; break;
} else if ("play".equals(line)) { } else if ("play".equals(line)) {
mController.play(PACKAGE_NAME); dispatchKeyCode(KeyEvent.KEYCODE_MEDIA_PLAY);
} else if ("pause".equals(line)) { } else if ("pause".equals(line)) {
mController.pause(PACKAGE_NAME); dispatchKeyCode(KeyEvent.KEYCODE_MEDIA_PAUSE);
} else if ("next".equals(line)) { } else if ("next".equals(line)) {
mController.next(PACKAGE_NAME); dispatchKeyCode(KeyEvent.KEYCODE_MEDIA_NEXT);
} else if ("previous".equals(line)) { } else if ("previous".equals(line)) {
mController.previous(PACKAGE_NAME); dispatchKeyCode(KeyEvent.KEYCODE_MEDIA_PREVIOUS);
} else { } else {
System.out.println("Invalid command: " + line); System.out.println("Invalid command: " + line);
} }
@@ -295,6 +293,20 @@ public class Media extends BaseCommand {
} }
} }
} }
private void dispatchKeyCode(int keyCode) {
final long now = SystemClock.uptimeMillis();
KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD);
KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD);
try {
mController.sendMediaButton(PACKAGE_NAME, null, false, down);
mController.sendMediaButton(PACKAGE_NAME, null, false, up);
} catch (RemoteException e) {
System.out.println("Failed to dispatch " + keyCode);
}
}
} }
private void runListSessions() { private void runListSessions() {

View File

@@ -17,6 +17,7 @@ package android.media.session;
import android.content.Intent; import android.content.Intent;
import android.media.Rating; import android.media.Rating;
import android.media.session.ISessionControllerCallback;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.ResultReceiver; import android.os.ResultReceiver;
@@ -25,33 +26,46 @@ import android.os.ResultReceiver;
* @hide * @hide
*/ */
oneway interface ISessionCallback { oneway interface ISessionCallback {
void onCommand(String packageName, int pid, int uid, String command, in Bundle args, void onCommand(String packageName, int pid, int uid, ISessionControllerCallback caller,
in ResultReceiver cb); String command, in Bundle args, in ResultReceiver cb);
void onMediaButton(String packageName, int pid, int uid, in Intent mediaButtonIntent, void onMediaButton(String packageName, int pid, int uid, in Intent mediaButtonIntent,
int sequenceNumber, in ResultReceiver cb); int sequenceNumber, in ResultReceiver cb);
void onMediaButtonFromController(String packageName, int pid, int uid,
ISessionControllerCallback caller, in Intent mediaButtonIntent);
// These callbacks are for the TransportPerformer // These callbacks are for the TransportPerformer
void onPrepare(String packageName, int pid, int uid); void onPrepare(String packageName, int pid, int uid, ISessionControllerCallback caller);
void onPrepareFromMediaId(String packageName, int pid, int uid, String mediaId, void onPrepareFromMediaId(String packageName, int pid, int uid,
in Bundle extras); ISessionControllerCallback caller, String mediaId, in Bundle extras);
void onPrepareFromSearch(String packageName, int pid, int uid, String query, in Bundle extras); void onPrepareFromSearch(String packageName, int pid, int uid,
void onPrepareFromUri(String packageName, int pid, int uid, in Uri uri, in Bundle extras); ISessionControllerCallback caller, String query, in Bundle extras);
void onPlay(String packageName, int pid, int uid); void onPrepareFromUri(String packageName, int pid, int uid, ISessionControllerCallback caller,
void onPlayFromMediaId(String packageName, int pid, int uid, String mediaId, in Bundle extras); in Uri uri, in Bundle extras);
void onPlayFromSearch(String packageName, int pid, int uid, String query, in Bundle extras); void onPlay(String packageName, int pid, int uid, ISessionControllerCallback caller);
void onPlayFromUri(String packageName, int pid, int uid, in Uri uri, in Bundle extras); void onPlayFromMediaId(String packageName, int pid, int uid, ISessionControllerCallback caller,
void onSkipToTrack(String packageName, int pid, int uid, long id); String mediaId, in Bundle extras);
void onPause(String packageName, int pid, int uid); void onPlayFromSearch(String packageName, int pid, int uid, ISessionControllerCallback caller,
void onStop(String packageName, int pid, int uid); String query, in Bundle extras);
void onNext(String packageName, int pid, int uid); void onPlayFromUri(String packageName, int pid, int uid, ISessionControllerCallback caller,
void onPrevious(String packageName, int pid, int uid); in Uri uri, in Bundle extras);
void onFastForward(String packageName, int pid, int uid); void onSkipToTrack(String packageName, int pid, int uid, ISessionControllerCallback caller,
void onRewind(String packageName, int pid, int uid); long id);
void onSeekTo(String packageName, int pid, int uid, long pos); void onPause(String packageName, int pid, int uid, ISessionControllerCallback caller);
void onRate(String packageName, int pid, int uid, in Rating rating); void onStop(String packageName, int pid, int uid, ISessionControllerCallback caller);
void onCustomAction(String packageName, int pid, int uid, String action, in Bundle args); void onNext(String packageName, int pid, int uid, ISessionControllerCallback caller);
void onPrevious(String packageName, int pid, int uid, ISessionControllerCallback caller);
void onFastForward(String packageName, int pid, int uid, ISessionControllerCallback caller);
void onRewind(String packageName, int pid, int uid, ISessionControllerCallback caller);
void onSeekTo(String packageName, int pid, int uid, ISessionControllerCallback caller,
long pos);
void onRate(String packageName, int pid, int uid, ISessionControllerCallback caller,
in Rating rating);
void onCustomAction(String packageName, int pid, int uid, ISessionControllerCallback caller,
String action, in Bundle args);
// These callbacks are for volume handling // These callbacks are for volume handling
void onAdjustVolume(String packageName, int pid, int uid, int direction); void onAdjustVolume(String packageName, int pid, int uid, ISessionControllerCallback caller,
void onSetVolumeTo(String packageName, int pid, int uid, int value); int direction);
void onSetVolumeTo(String packageName, int pid, int uid,
ISessionControllerCallback caller, int value);
} }

View File

@@ -32,42 +32,53 @@ import android.view.KeyEvent;
import java.util.List; import java.util.List;
/** /**
* Interface to a MediaSession in the system. * Interface to MediaSessionRecord in the system.
* @hide * @hide
*/ */
interface ISessionController { interface ISessionController {
void sendCommand(String packageName, String command, in Bundle args, in ResultReceiver cb); void sendCommand(String packageName, ISessionControllerCallback caller,
boolean sendMediaButton(String packageName, boolean asSystemService, in KeyEvent mediaButton); String command, in Bundle args, in ResultReceiver cb);
void registerCallbackListener(in ISessionControllerCallback cb); boolean sendMediaButton(String packageName, ISessionControllerCallback caller,
void unregisterCallbackListener(in ISessionControllerCallback cb); boolean asSystemService, in KeyEvent mediaButton);
void registerCallbackListener(String packageName, ISessionControllerCallback cb);
void unregisterCallbackListener(ISessionControllerCallback cb);
boolean isTransportControlEnabled(); boolean isTransportControlEnabled();
String getPackageName(); String getPackageName();
String getTag(); String getTag();
PendingIntent getLaunchPendingIntent(); PendingIntent getLaunchPendingIntent();
long getFlags(); long getFlags();
ParcelableVolumeInfo getVolumeAttributes(); ParcelableVolumeInfo getVolumeAttributes();
void adjustVolume(String packageName, boolean asSystemService, int direction, int flags); void adjustVolume(String packageName, ISessionControllerCallback caller,
void setVolumeTo(String packageName, int value, int flags); boolean asSystemService, int direction, int flags);
void setVolumeTo(String packageName, ISessionControllerCallback caller,
int value, int flags);
// These commands are for the TransportControls // These commands are for the TransportControls
void prepare(String packageName); void prepare(String packageName, ISessionControllerCallback caller);
void prepareFromMediaId(String packageName, String mediaId, in Bundle extras); void prepareFromMediaId(String packageName, ISessionControllerCallback caller,
void prepareFromSearch(String packageName, String string, in Bundle extras); String mediaId, in Bundle extras);
void prepareFromUri(String packageName, in Uri uri, in Bundle extras); void prepareFromSearch(String packageName, ISessionControllerCallback caller,
void play(String packageName); String string, in Bundle extras);
void playFromMediaId(String packageName, String mediaId, in Bundle extras); void prepareFromUri(String packageName, ISessionControllerCallback caller,
void playFromSearch(String packageName, String string, in Bundle extras); in Uri uri, in Bundle extras);
void playFromUri(String packageName, in Uri uri, in Bundle extras); void play(String packageName, ISessionControllerCallback caller);
void skipToQueueItem(String packageName, long id); void playFromMediaId(String packageName, ISessionControllerCallback caller,
void pause(String packageName); String mediaId, in Bundle extras);
void stop(String packageName); void playFromSearch(String packageName, ISessionControllerCallback caller,
void next(String packageName); String string, in Bundle extras);
void previous(String packageName); void playFromUri(String packageName, ISessionControllerCallback caller,
void fastForward(String packageName); in Uri uri, in Bundle extras);
void rewind(String packageName); void skipToQueueItem(String packageName, ISessionControllerCallback caller, long id);
void seekTo(String packageName, long pos); void pause(String packageName, ISessionControllerCallback caller);
void rate(String packageName, in Rating rating); void stop(String packageName, ISessionControllerCallback caller);
void sendCustomAction(String packageName, String action, in Bundle args); void next(String packageName, ISessionControllerCallback caller);
void previous(String packageName, ISessionControllerCallback caller);
void fastForward(String packageName, ISessionControllerCallback caller);
void rewind(String packageName, ISessionControllerCallback caller);
void seekTo(String packageName, ISessionControllerCallback caller, long pos);
void rate(String packageName, ISessionControllerCallback caller, in Rating rating);
void sendCustomAction(String packageName, ISessionControllerCallback caller,
String action, in Bundle args);
MediaMetadata getMetadata(); MediaMetadata getMetadata();
PlaybackState getPlaybackState(); PlaybackState getPlaybackState();
ParceledListSlice getQueue(); ParceledListSlice getQueue();

View File

@@ -126,7 +126,7 @@ public final class MediaController {
* @return true if the event was sent to the session, false otherwise. * @return true if the event was sent to the session, false otherwise.
*/ */
public boolean dispatchMediaButtonEvent(@NonNull KeyEvent keyEvent) { public boolean dispatchMediaButtonEvent(@NonNull KeyEvent keyEvent) {
return dispatchMediButtonEventInternal(false, keyEvent); return dispatchMediaButtonEventInternal(false, keyEvent);
} }
/** /**
@@ -142,10 +142,10 @@ public final class MediaController {
* @hide * @hide
*/ */
public boolean dispatchMediaButtonEventAsSystemService(@NonNull KeyEvent keyEvent) { public boolean dispatchMediaButtonEventAsSystemService(@NonNull KeyEvent keyEvent) {
return dispatchMediButtonEventInternal(true, keyEvent); return dispatchMediaButtonEventInternal(true, keyEvent);
} }
private boolean dispatchMediButtonEventInternal(boolean asSystemService, private boolean dispatchMediaButtonEventInternal(boolean asSystemService,
@NonNull KeyEvent keyEvent) { @NonNull KeyEvent keyEvent) {
if (keyEvent == null) { if (keyEvent == null) {
throw new IllegalArgumentException("KeyEvent may not be null"); throw new IllegalArgumentException("KeyEvent may not be null");
@@ -154,8 +154,8 @@ public final class MediaController {
return false; return false;
} }
try { try {
return mSessionBinder.sendMediaButton(mContext.getPackageName(), asSystemService, return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub,
keyEvent); asSystemService, keyEvent);
} catch (RemoteException e) { } catch (RemoteException e) {
// System is dead. =( // System is dead. =(
} }
@@ -189,7 +189,7 @@ public final class MediaController {
break; break;
} }
try { try {
mSessionBinder.adjustVolume(mContext.getPackageName(), true, direction, mSessionBinder.adjustVolume(mContext.getPackageName(), mCbStub, true, direction,
AudioManager.FLAG_SHOW_UI); AudioManager.FLAG_SHOW_UI);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy", e); Log.wtf(TAG, "Error calling adjustVolumeBy", e);
@@ -200,7 +200,7 @@ public final class MediaController {
final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
| AudioManager.FLAG_FROM_KEY; | AudioManager.FLAG_FROM_KEY;
try { try {
mSessionBinder.adjustVolume(mContext.getPackageName(), true, 0, flags); mSessionBinder.adjustVolume(mContext.getPackageName(), mCbStub, true, 0, flags);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy", e); Log.wtf(TAG, "Error calling adjustVolumeBy", e);
} }
@@ -369,7 +369,7 @@ public final class MediaController {
*/ */
public void setVolumeTo(int value, int flags) { public void setVolumeTo(int value, int flags) {
try { try {
mSessionBinder.setVolumeTo(mContext.getPackageName(), value, flags); mSessionBinder.setVolumeTo(mContext.getPackageName(), mCbStub, value, flags);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling setVolumeTo.", e); Log.wtf(TAG, "Error calling setVolumeTo.", e);
} }
@@ -390,7 +390,8 @@ public final class MediaController {
*/ */
public void adjustVolume(int direction, int flags) { public void adjustVolume(int direction, int flags) {
try { try {
mSessionBinder.adjustVolume(mContext.getPackageName(), false, direction, flags); mSessionBinder.adjustVolume(mContext.getPackageName(), mCbStub, false, direction,
flags);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy.", e); Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
} }
@@ -456,7 +457,7 @@ public final class MediaController {
throw new IllegalArgumentException("command cannot be null or empty"); throw new IllegalArgumentException("command cannot be null or empty");
} }
try { try {
mSessionBinder.sendCommand(mContext.getPackageName(), command, args, cb); mSessionBinder.sendCommand(mContext.getPackageName(), mCbStub, command, args, cb);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.d(TAG, "Dead object in sendCommand.", e); Log.d(TAG, "Dead object in sendCommand.", e);
} }
@@ -521,7 +522,7 @@ public final class MediaController {
if (!mCbRegistered) { if (!mCbRegistered) {
try { try {
mSessionBinder.registerCallbackListener(mCbStub); mSessionBinder.registerCallbackListener(mContext.getPackageName(), mCbStub);
mCbRegistered = true; mCbRegistered = true;
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "Dead object in registerCallback", e); Log.e(TAG, "Dead object in registerCallback", e);
@@ -668,7 +669,7 @@ public final class MediaController {
*/ */
public void prepare() { public void prepare() {
try { try {
mSessionBinder.prepare(mContext.getPackageName()); mSessionBinder.prepare(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare.", e); Log.wtf(TAG, "Error calling prepare.", e);
} }
@@ -692,7 +693,8 @@ public final class MediaController {
"You must specify a non-empty String for prepareFromMediaId."); "You must specify a non-empty String for prepareFromMediaId.");
} }
try { try {
mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mediaId, extras); mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
extras);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e); Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
} }
@@ -718,7 +720,7 @@ public final class MediaController {
query = ""; query = "";
} }
try { try {
mSessionBinder.prepareFromSearch(mContext.getPackageName(), query, extras); mSessionBinder.prepareFromSearch(mContext.getPackageName(), mCbStub, query, extras);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + query + ").", e); Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
} }
@@ -742,7 +744,7 @@ public final class MediaController {
"You must specify a non-empty Uri for prepareFromUri."); "You must specify a non-empty Uri for prepareFromUri.");
} }
try { try {
mSessionBinder.prepareFromUri(mContext.getPackageName(), uri, extras); mSessionBinder.prepareFromUri(mContext.getPackageName(), mCbStub, uri, extras);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + uri + ").", e); Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
} }
@@ -753,7 +755,7 @@ public final class MediaController {
*/ */
public void play() { public void play() {
try { try {
mSessionBinder.play(mContext.getPackageName()); mSessionBinder.play(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling play.", e); Log.wtf(TAG, "Error calling play.", e);
} }
@@ -772,7 +774,7 @@ public final class MediaController {
"You must specify a non-empty String for playFromMediaId."); "You must specify a non-empty String for playFromMediaId.");
} }
try { try {
mSessionBinder.playFromMediaId(mContext.getPackageName(), mediaId, extras); mSessionBinder.playFromMediaId(mContext.getPackageName(), mCbStub, mediaId, extras);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + mediaId + ").", e); Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
} }
@@ -794,7 +796,7 @@ public final class MediaController {
query = ""; query = "";
} }
try { try {
mSessionBinder.playFromSearch(mContext.getPackageName(), query, extras); mSessionBinder.playFromSearch(mContext.getPackageName(), mCbStub, query, extras);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + query + ").", e); Log.wtf(TAG, "Error calling play(" + query + ").", e);
} }
@@ -813,7 +815,7 @@ public final class MediaController {
"You must specify a non-empty Uri for playFromUri."); "You must specify a non-empty Uri for playFromUri.");
} }
try { try {
mSessionBinder.playFromUri(mContext.getPackageName(), uri, extras); mSessionBinder.playFromUri(mContext.getPackageName(), mCbStub, uri, extras);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + uri + ").", e); Log.wtf(TAG, "Error calling play(" + uri + ").", e);
} }
@@ -825,7 +827,7 @@ public final class MediaController {
*/ */
public void skipToQueueItem(long id) { public void skipToQueueItem(long id) {
try { try {
mSessionBinder.skipToQueueItem(mContext.getPackageName(), id); mSessionBinder.skipToQueueItem(mContext.getPackageName(), mCbStub, id);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e); Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
} }
@@ -837,7 +839,7 @@ public final class MediaController {
*/ */
public void pause() { public void pause() {
try { try {
mSessionBinder.pause(mContext.getPackageName()); mSessionBinder.pause(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling pause.", e); Log.wtf(TAG, "Error calling pause.", e);
} }
@@ -849,7 +851,7 @@ public final class MediaController {
*/ */
public void stop() { public void stop() {
try { try {
mSessionBinder.stop(mContext.getPackageName()); mSessionBinder.stop(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling stop.", e); Log.wtf(TAG, "Error calling stop.", e);
} }
@@ -862,7 +864,7 @@ public final class MediaController {
*/ */
public void seekTo(long pos) { public void seekTo(long pos) {
try { try {
mSessionBinder.seekTo(mContext.getPackageName(), pos); mSessionBinder.seekTo(mContext.getPackageName(), mCbStub, pos);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling seekTo.", e); Log.wtf(TAG, "Error calling seekTo.", e);
} }
@@ -874,7 +876,7 @@ public final class MediaController {
*/ */
public void fastForward() { public void fastForward() {
try { try {
mSessionBinder.fastForward(mContext.getPackageName()); mSessionBinder.fastForward(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling fastForward.", e); Log.wtf(TAG, "Error calling fastForward.", e);
} }
@@ -885,7 +887,7 @@ public final class MediaController {
*/ */
public void skipToNext() { public void skipToNext() {
try { try {
mSessionBinder.next(mContext.getPackageName()); mSessionBinder.next(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling next.", e); Log.wtf(TAG, "Error calling next.", e);
} }
@@ -897,7 +899,7 @@ public final class MediaController {
*/ */
public void rewind() { public void rewind() {
try { try {
mSessionBinder.rewind(mContext.getPackageName()); mSessionBinder.rewind(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling rewind.", e); Log.wtf(TAG, "Error calling rewind.", e);
} }
@@ -908,7 +910,7 @@ public final class MediaController {
*/ */
public void skipToPrevious() { public void skipToPrevious() {
try { try {
mSessionBinder.previous(mContext.getPackageName()); mSessionBinder.previous(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling previous.", e); Log.wtf(TAG, "Error calling previous.", e);
} }
@@ -923,7 +925,7 @@ public final class MediaController {
*/ */
public void setRating(Rating rating) { public void setRating(Rating rating) {
try { try {
mSessionBinder.rate(mContext.getPackageName(), rating); mSessionBinder.rate(mContext.getPackageName(), mCbStub, rating);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error calling rate.", e); Log.wtf(TAG, "Error calling rate.", e);
} }
@@ -937,7 +939,7 @@ public final class MediaController {
* custom action. * custom action.
*/ */
public void sendCustomAction(@NonNull PlaybackState.CustomAction customAction, public void sendCustomAction(@NonNull PlaybackState.CustomAction customAction,
@Nullable Bundle args) { @Nullable Bundle args) {
if (customAction == null) { if (customAction == null) {
throw new IllegalArgumentException("CustomAction cannot be null."); throw new IllegalArgumentException("CustomAction cannot be null.");
} }
@@ -958,7 +960,7 @@ public final class MediaController {
throw new IllegalArgumentException("CustomAction cannot be null."); throw new IllegalArgumentException("CustomAction cannot be null.");
} }
try { try {
mSessionBinder.sendCustomAction(mContext.getPackageName(), action, args); mSessionBinder.sendCustomAction(mContext.getPackageName(), mCbStub, action, args);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.d(TAG, "Dead object in sendCustomAction.", e); Log.d(TAG, "Dead object in sendCustomAction.", e);
} }
@@ -1124,8 +1126,8 @@ public final class MediaController {
public void onVolumeInfoChanged(ParcelableVolumeInfo pvi) { public void onVolumeInfoChanged(ParcelableVolumeInfo pvi) {
MediaController controller = mController.get(); MediaController controller = mController.get();
if (controller != null) { if (controller != null) {
PlaybackInfo info = new PlaybackInfo(pvi.volumeType, pvi.audioAttrs, pvi.controlType, PlaybackInfo info = new PlaybackInfo(pvi.volumeType, pvi.audioAttrs,
pvi.maxVolume, pvi.currentVolume); pvi.controlType, pvi.maxVolume, pvi.currentVolume);
controller.postMessage(MSG_UPDATE_VOLUME, info, null); controller.postMessage(MSG_UPDATE_VOLUME, info, null);
} }
} }

View File

@@ -43,6 +43,7 @@ import android.media.session.MediaSessionManager.RemoteUserInfo;
import android.service.media.MediaBrowserService; import android.service.media.MediaBrowserService;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.ViewConfiguration; import android.view.ViewConfiguration;
@@ -122,15 +123,6 @@ public final class MediaSession {
FLAG_EXCLUSIVE_GLOBAL_PRIORITY }) FLAG_EXCLUSIVE_GLOBAL_PRIORITY })
public @interface SessionFlags { } public @interface SessionFlags { }
private static final String EXTRA_KEY_CALLING_PACKAGE =
"android.media.session.extra.CALLING_PACKAGE";
private static final String EXTRA_KEY_CALLING_PID =
"android.media.session.extra.CALLING_PID";
private static final String EXTRA_KEY_CALLING_UID =
"android.media.session.extra.CALLING_UID";
private static final String EXTRA_KEY_ORIGINAL_BUNDLE =
"android.media.session.extra.ORIGINAL_BUNDLE";
private final Object mLock = new Object(); private final Object mLock = new Object();
private final int mMaxBitmapSize; private final int mMaxBitmapSize;
@@ -529,15 +521,11 @@ public final class MediaSession {
* @see MediaSessionManager#isTrustedForMediaControl(RemoteUserInfo) * @see MediaSessionManager#isTrustedForMediaControl(RemoteUserInfo)
*/ */
public final @NonNull RemoteUserInfo getCurrentControllerInfo() { public final @NonNull RemoteUserInfo getCurrentControllerInfo() {
return createRemoteUserInfo(getCurrentData()); if (mCallback == null || mCallback.mCurrentControllerInfo == null) {
}
private @NonNull Bundle getCurrentData() {
if (mCallback == null || mCallback.mCurrentData == null) {
throw new IllegalStateException( throw new IllegalStateException(
"This should be called inside of MediaSession.Callback methods"); "This should be called inside of MediaSession.Callback methods");
} }
return mCallback.mCurrentData; return mCallback.mCurrentControllerInfo;
} }
/** /**
@@ -568,160 +556,121 @@ public final class MediaSession {
* @hide * @hide
*/ */
public String getCallingPackage() { public String getCallingPackage() {
if (mCallback != null) { if (mCallback != null && mCallback.mCurrentControllerInfo != null) {
return createRemoteUserInfo(mCallback.mCurrentData).getPackageName(); return mCallback.mCurrentControllerInfo.getPackageName();
} }
return null; return null;
} }
private void dispatchPrepare(Bundle extras) { private void dispatchPrepare(RemoteUserInfo caller) {
postToCallback(CallbackMessageHandler.MSG_PREPARE, null, extras); postToCallback(caller, CallbackMessageHandler.MSG_PREPARE, null, null);
} }
private void dispatchPrepareFromMediaId(String mediaId, Bundle extras) { private void dispatchPrepareFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) {
postToCallback(CallbackMessageHandler.MSG_PREPARE_MEDIA_ID, mediaId, extras); postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_MEDIA_ID, mediaId, extras);
} }
private void dispatchPrepareFromSearch(String query, Bundle extras) { private void dispatchPrepareFromSearch(RemoteUserInfo caller, String query, Bundle extras) {
postToCallback(CallbackMessageHandler.MSG_PREPARE_SEARCH, query, extras); postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_SEARCH, query, extras);
} }
private void dispatchPrepareFromUri(Uri uri, Bundle extras) { private void dispatchPrepareFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) {
postToCallback(CallbackMessageHandler.MSG_PREPARE_URI, uri, extras); postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_URI, uri, extras);
} }
private void dispatchPlay(Bundle extras) { private void dispatchPlay(RemoteUserInfo caller) {
postToCallback(CallbackMessageHandler.MSG_PLAY, null, extras); postToCallback(caller, CallbackMessageHandler.MSG_PLAY, null, null);
} }
private void dispatchPlayFromMediaId(String mediaId, Bundle extras) { private void dispatchPlayFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) {
postToCallback(CallbackMessageHandler.MSG_PLAY_MEDIA_ID, mediaId, extras); postToCallback(caller, CallbackMessageHandler.MSG_PLAY_MEDIA_ID, mediaId, extras);
} }
private void dispatchPlayFromSearch(String query, Bundle extras) { private void dispatchPlayFromSearch(RemoteUserInfo caller, String query, Bundle extras) {
postToCallback(CallbackMessageHandler.MSG_PLAY_SEARCH, query, extras); postToCallback(caller, CallbackMessageHandler.MSG_PLAY_SEARCH, query, extras);
} }
private void dispatchPlayFromUri(Uri uri, Bundle extras) { private void dispatchPlayFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) {
postToCallback(CallbackMessageHandler.MSG_PLAY_URI, uri, extras); postToCallback(caller, CallbackMessageHandler.MSG_PLAY_URI, uri, extras);
} }
private void dispatchSkipToItem(long id, Bundle extras) { private void dispatchSkipToItem(RemoteUserInfo caller, long id) {
postToCallback(CallbackMessageHandler.MSG_SKIP_TO_ITEM, id, extras); postToCallback(caller, CallbackMessageHandler.MSG_SKIP_TO_ITEM, id, null);
} }
private void dispatchPause(Bundle extras) { private void dispatchPause(RemoteUserInfo caller) {
postToCallback(CallbackMessageHandler.MSG_PAUSE, null, extras); postToCallback(caller, CallbackMessageHandler.MSG_PAUSE, null, null);
} }
private void dispatchStop(Bundle extras) { private void dispatchStop(RemoteUserInfo caller) {
postToCallback(CallbackMessageHandler.MSG_STOP, null, extras); postToCallback(caller, CallbackMessageHandler.MSG_STOP, null, null);
} }
private void dispatchNext(Bundle extras) { private void dispatchNext(RemoteUserInfo caller) {
postToCallback(CallbackMessageHandler.MSG_NEXT, null, extras); postToCallback(caller, CallbackMessageHandler.MSG_NEXT, null, null);
} }
private void dispatchPrevious(Bundle extras) { private void dispatchPrevious(RemoteUserInfo caller) {
postToCallback(CallbackMessageHandler.MSG_PREVIOUS, null, extras); postToCallback(caller, CallbackMessageHandler.MSG_PREVIOUS, null, null);
} }
private void dispatchFastForward(Bundle extras) { private void dispatchFastForward(RemoteUserInfo caller) {
postToCallback(CallbackMessageHandler.MSG_FAST_FORWARD, null, extras); postToCallback(caller, CallbackMessageHandler.MSG_FAST_FORWARD, null, null);
} }
private void dispatchRewind(Bundle extras) { private void dispatchRewind(RemoteUserInfo caller) {
postToCallback(CallbackMessageHandler.MSG_REWIND, null, extras); postToCallback(caller, CallbackMessageHandler.MSG_REWIND, null, null);
} }
private void dispatchSeekTo(long pos, Bundle extras) { private void dispatchSeekTo(RemoteUserInfo caller, long pos) {
postToCallback(CallbackMessageHandler.MSG_SEEK_TO, pos, extras); postToCallback(caller, CallbackMessageHandler.MSG_SEEK_TO, pos, null);
} }
private void dispatchRate(Rating rating, Bundle extras) { private void dispatchRate(RemoteUserInfo caller, Rating rating) {
postToCallback(CallbackMessageHandler.MSG_RATE, rating, extras); postToCallback(caller, CallbackMessageHandler.MSG_RATE, rating, null);
} }
private void dispatchCustomAction(String action, Bundle extras) { private void dispatchCustomAction(RemoteUserInfo caller, String action, Bundle args) {
postToCallback(CallbackMessageHandler.MSG_CUSTOM_ACTION, action, extras); postToCallback(caller, CallbackMessageHandler.MSG_CUSTOM_ACTION, action, args);
} }
private void dispatchMediaButton(Intent mediaButtonIntent, Bundle extras) { private void dispatchMediaButton(RemoteUserInfo caller, Intent mediaButtonIntent) {
postToCallback(CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent, extras); postToCallback(caller, CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent, null);
} }
private void dispatchAdjustVolume(int direction, Bundle extras) { private void dispatchMediaButtonDelayed(RemoteUserInfo info, Intent mediaButtonIntent,
postToCallback(CallbackMessageHandler.MSG_ADJUST_VOLUME, direction, extras); long delay) {
postToCallbackDelayed(info, CallbackMessageHandler.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT,
mediaButtonIntent, null, delay);
} }
private void dispatchSetVolumeTo(int volume, Bundle extras) { private void dispatchAdjustVolume(RemoteUserInfo caller, int direction) {
postToCallback(CallbackMessageHandler.MSG_SET_VOLUME, volume, extras); postToCallback(caller, CallbackMessageHandler.MSG_ADJUST_VOLUME, direction, null);
} }
private void postCommand(String command, Bundle args, ResultReceiver resultCb, Bundle extras) { private void dispatchSetVolumeTo(RemoteUserInfo caller, int volume) {
postToCallback(caller, CallbackMessageHandler.MSG_SET_VOLUME, volume, null);
}
private void dispatchCommand(RemoteUserInfo caller, String command, Bundle args,
ResultReceiver resultCb) {
Command cmd = new Command(command, args, resultCb); Command cmd = new Command(command, args, resultCb);
postToCallback(CallbackMessageHandler.MSG_COMMAND, cmd, extras); postToCallback(caller, CallbackMessageHandler.MSG_COMMAND, cmd, null);
} }
private void postToCallback(int what, Object obj, Bundle extras) { private void postToCallback(RemoteUserInfo caller, int what, Object obj, Bundle data) {
postToCallbackDelayed(caller, what, obj, data, 0);
}
private void postToCallbackDelayed(RemoteUserInfo caller, int what, Object obj, Bundle data,
long delay) {
synchronized (mLock) { synchronized (mLock) {
if (mCallback != null) { if (mCallback != null) {
mCallback.post(what, obj, extras); mCallback.post(caller, what, obj, data, delay);
} }
} }
} }
/**
* Creates the extra bundle that includes the caller information.
*
* @return An extraBundle that contains caller information
*/
private static Bundle createExtraBundle(String packageName, int pid, int uid) {
return createExtraBundle(packageName, pid, uid, null);
}
/**
* Creates the extra bundle that includes the caller information.
*
* @param originalBundle bundle
* @return An extraBundle that contains caller information
*/
private static Bundle createExtraBundle(String packageName, int pid, int uid,
Bundle originalBundle) {
Bundle bundle = new Bundle();
bundle.putString(EXTRA_KEY_CALLING_PACKAGE, packageName);
bundle.putInt(EXTRA_KEY_CALLING_PID, pid);
bundle.putInt(EXTRA_KEY_CALLING_UID, uid);
if (originalBundle != null) {
bundle.putBundle(EXTRA_KEY_ORIGINAL_BUNDLE, originalBundle);
}
return bundle;
}
/**
* Creates the {@link RemoteUserInfo} from the extra bundle created by
* {@link #createExtraBundle}.
*
* @param extraBundle that previously created by createExtraBundle()
* @return a RemoteUserInfo
*/
private static RemoteUserInfo createRemoteUserInfo(Bundle extraBundle) {
return new RemoteUserInfo(
extraBundle.getString(EXTRA_KEY_CALLING_PACKAGE),
extraBundle.getInt(EXTRA_KEY_CALLING_PID, INVALID_PID),
extraBundle.getInt(EXTRA_KEY_CALLING_UID, INVALID_UID));
}
/**
* Gets the original bundle from the extra bundle created by {@link #createExtraBundle}.
*
* @param extraBundle that previously created by createExtraBundle()
* @return a Bundle
*/
private static Bundle getOriginalBundle(Bundle extraBundle) {
return extraBundle.getBundle(EXTRA_KEY_ORIGINAL_BUNDLE);
}
/** /**
* Return true if this is considered an active playback state. * Return true if this is considered an active playback state.
* *
@@ -872,10 +821,9 @@ public final class MediaSession {
} }
} else { } else {
mMediaPlayPauseKeyPending = true; mMediaPlayPauseKeyPending = true;
mHandler.postDelayed(CallbackMessageHandler mSession.dispatchMediaButtonDelayed(
.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT, mSession.getCurrentControllerInfo(),
mSession.getCurrentData(), mediaButtonIntent, ViewConfiguration.getDoubleTapTimeout());
ViewConfiguration.getDoubleTapTimeout());
} }
return true; return true;
default: default:
@@ -1109,12 +1057,19 @@ public final class MediaSession {
mMediaSession = new WeakReference<>(session); mMediaSession = new WeakReference<>(session);
} }
private static RemoteUserInfo createRemoteUserInfo(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
return new RemoteUserInfo(packageName, pid, uid,
caller != null ? caller.asBinder() : null);
}
@Override @Override
public void onCommand(String packageName, int pid, int uid, String command, Bundle args, public void onCommand(String packageName, int pid, int uid,
ResultReceiver cb) { ISessionControllerCallback caller, String command, Bundle args, ResultReceiver cb) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.postCommand(command, args, cb, createExtraBundle(packageName, pid, uid)); session.dispatchCommand(createRemoteUserInfo(packageName, pid, uid, caller),
command, args, cb);
} }
} }
@@ -1124,8 +1079,8 @@ public final class MediaSession {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
try { try {
if (session != null) { if (session != null) {
session.dispatchMediaButton( session.dispatchMediaButton(createRemoteUserInfo(packageName, pid, uid, null),
mediaButtonIntent, createExtraBundle(packageName, pid, uid)); mediaButtonIntent);
} }
} finally { } finally {
if (cb != null) { if (cb != null) {
@@ -1135,173 +1090,205 @@ public final class MediaSession {
} }
@Override @Override
public void onPrepare(String packageName, int pid, int uid) { public void onMediaButtonFromController(String packageName, int pid, int uid,
ISessionControllerCallback caller, Intent mediaButtonIntent) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchPrepare(createExtraBundle(packageName, pid, uid)); session.dispatchMediaButton(createRemoteUserInfo(packageName, pid, uid, caller),
mediaButtonIntent);
} }
} }
@Override @Override
public void onPrepareFromMediaId(String packageName, int pid, int uid, String mediaId, public void onPrepare(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchPrepare(createRemoteUserInfo(packageName, pid, uid, caller));
}
}
@Override
public void onPrepareFromMediaId(String packageName, int pid, int uid,
ISessionControllerCallback caller, String mediaId,
Bundle extras) { Bundle extras) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchPrepareFromMediaId( session.dispatchPrepareFromMediaId(
mediaId, createExtraBundle(packageName, pid, uid, extras)); createRemoteUserInfo(packageName, pid, uid, caller), mediaId, extras);
} }
} }
@Override @Override
public void onPrepareFromSearch(String packageName, int pid, int uid, String query, public void onPrepareFromSearch(String packageName, int pid, int uid,
ISessionControllerCallback caller, String query,
Bundle extras) { Bundle extras) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchPrepareFromSearch( session.dispatchPrepareFromSearch(
query, createExtraBundle(packageName, pid, uid, extras)); createRemoteUserInfo(packageName, pid, uid, caller), query, extras);
} }
} }
@Override @Override
public void onPrepareFromUri(String packageName, int pid, int uid, Uri uri, Bundle extras) { public void onPrepareFromUri(String packageName, int pid, int uid,
ISessionControllerCallback caller, Uri uri, Bundle extras) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchPrepareFromUri(uri, session.dispatchPrepareFromUri(createRemoteUserInfo(packageName, pid, uid, caller),
createExtraBundle(packageName, pid, uid, extras)); uri, extras);
} }
} }
@Override @Override
public void onPlay(String packageName, int pid, int uid) { public void onPlay(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchPlay(createExtraBundle(packageName, pid, uid)); session.dispatchPlay(createRemoteUserInfo(packageName, pid, uid, caller));
} }
} }
@Override @Override
public void onPlayFromMediaId(String packageName, int pid, int uid, String mediaId, public void onPlayFromMediaId(String packageName, int pid, int uid,
ISessionControllerCallback caller, String mediaId,
Bundle extras) { Bundle extras) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchPlayFromMediaId( session.dispatchPlayFromMediaId(createRemoteUserInfo(packageName, pid, uid, caller),
mediaId, createExtraBundle(packageName, pid, uid, extras)); mediaId, extras);
} }
} }
@Override @Override
public void onPlayFromSearch(String packageName, int pid, int uid, String query, public void onPlayFromSearch(String packageName, int pid, int uid,
ISessionControllerCallback caller, String query,
Bundle extras) { Bundle extras) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchPlayFromSearch(query, createExtraBundle(packageName, pid, uid, session.dispatchPlayFromSearch(createRemoteUserInfo(packageName, pid, uid, caller),
extras)); query, extras);
} }
} }
@Override @Override
public void onPlayFromUri(String packageName, int pid, int uid, Uri uri, Bundle extras) { public void onPlayFromUri(String packageName, int pid, int uid,
ISessionControllerCallback caller, Uri uri, Bundle extras) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchPlayFromUri(uri, createExtraBundle(packageName, pid, uid, extras)); session.dispatchPlayFromUri(createRemoteUserInfo(packageName, pid, uid, caller),
uri, extras);
} }
} }
@Override @Override
public void onSkipToTrack(String packageName, int pid, int uid, long id) { public void onSkipToTrack(String packageName, int pid, int uid,
ISessionControllerCallback caller, long id) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchSkipToItem(id, createExtraBundle(packageName, pid, uid)); session.dispatchSkipToItem(createRemoteUserInfo(packageName, pid, uid, caller), id);
} }
} }
@Override @Override
public void onPause(String packageName, int pid, int uid) { public void onPause(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchPause(createExtraBundle(packageName, pid, uid)); session.dispatchPause(createRemoteUserInfo(packageName, pid, uid, caller));
} }
} }
@Override @Override
public void onStop(String packageName, int pid, int uid) { public void onStop(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchStop(createExtraBundle(packageName, pid, uid)); session.dispatchStop(createRemoteUserInfo(packageName, pid, uid, caller));
} }
} }
@Override @Override
public void onNext(String packageName, int pid, int uid) { public void onNext(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchNext(createExtraBundle(packageName, pid, uid)); session.dispatchNext(createRemoteUserInfo(packageName, pid, uid, caller));
} }
} }
@Override @Override
public void onPrevious(String packageName, int pid, int uid) { public void onPrevious(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchPrevious(createExtraBundle(packageName, pid, uid)); session.dispatchPrevious(createRemoteUserInfo(packageName, pid, uid, caller));
} }
} }
@Override @Override
public void onFastForward(String packageName, int pid, int uid) { public void onFastForward(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchFastForward(createExtraBundle(packageName, pid, uid)); session.dispatchFastForward(createRemoteUserInfo(packageName, pid, uid, caller));
} }
} }
@Override @Override
public void onRewind(String packageName, int pid, int uid) { public void onRewind(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchRewind(createExtraBundle(packageName, pid, uid)); session.dispatchRewind(createRemoteUserInfo(packageName, pid, uid, caller));
} }
} }
@Override @Override
public void onSeekTo(String packageName, int pid, int uid, long pos) { public void onSeekTo(String packageName, int pid, int uid,
ISessionControllerCallback caller, long pos) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchSeekTo(pos, createExtraBundle(packageName, pid, uid)); session.dispatchSeekTo(createRemoteUserInfo(packageName, pid, uid, caller), pos);
} }
} }
@Override @Override
public void onRate(String packageName, int pid, int uid, Rating rating) { public void onRate(String packageName, int pid, int uid, ISessionControllerCallback caller,
Rating rating) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchRate(rating, createExtraBundle(packageName, pid, uid)); session.dispatchRate(createRemoteUserInfo(packageName, pid, uid, caller), rating);
} }
} }
@Override @Override
public void onCustomAction(String packageName, int pid, int uid, String action, public void onCustomAction(String packageName, int pid, int uid,
Bundle args) { ISessionControllerCallback caller, String action, Bundle args) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchCustomAction( session.dispatchCustomAction(createRemoteUserInfo(packageName, pid, uid, caller),
action, createExtraBundle(packageName, pid, uid, args)); action, args);
} }
} }
@Override @Override
public void onAdjustVolume(String packageName, int pid, int uid, int direction) { public void onAdjustVolume(String packageName, int pid, int uid,
ISessionControllerCallback caller, int direction) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchAdjustVolume(direction, createExtraBundle(packageName, pid, uid)); session.dispatchAdjustVolume(createRemoteUserInfo(packageName, pid, uid, caller),
direction);
} }
} }
@Override @Override
public void onSetVolumeTo(String packageName, int pid, int uid, int value) { public void onSetVolumeTo(String packageName, int pid, int uid,
ISessionControllerCallback caller, int value) {
MediaSession session = mMediaSession.get(); MediaSession session = mMediaSession.get();
if (session != null) { if (session != null) {
session.dispatchSetVolumeTo(value, createExtraBundle(packageName, pid, uid)); session.dispatchSetVolumeTo(createRemoteUserInfo(packageName, pid, uid, caller),
value);
} }
} }
} }
@@ -1424,7 +1411,6 @@ public final class MediaSession {
} }
private class CallbackMessageHandler extends Handler { private class CallbackMessageHandler extends Handler {
private static final int MSG_COMMAND = 1; private static final int MSG_COMMAND = 1;
private static final int MSG_MEDIA_BUTTON = 2; private static final int MSG_MEDIA_BUTTON = 2;
private static final int MSG_PREPARE = 3; private static final int MSG_PREPARE = 3;
@@ -1450,7 +1436,7 @@ public final class MediaSession {
private static final int MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT = 23; private static final int MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT = 23;
private MediaSession.Callback mCallback; private MediaSession.Callback mCallback;
private Bundle mCurrentData; private RemoteUserInfo mCurrentControllerInfo;
public CallbackMessageHandler(Looper looper, MediaSession.Callback callback) { public CallbackMessageHandler(Looper looper, MediaSession.Callback callback) {
super(looper, null, true); super(looper, null, true);
@@ -1458,60 +1444,58 @@ public final class MediaSession {
mCallback.mHandler = this; mCallback.mHandler = this;
} }
public void post(int what, Object obj, Bundle data) { public void post(RemoteUserInfo caller, int what, Object obj, Bundle data, long delayMs) {
Message msg = obtainMessage(what, obj); Pair<RemoteUserInfo, Object> objWithCaller = Pair.create(caller, obj);
Message msg = obtainMessage(what, objWithCaller);
msg.setData(data); msg.setData(data);
msg.sendToTarget(); if (delayMs > 0) {
} sendMessageDelayed(msg, delayMs);
} else {
public void postDelayed(int what, Bundle data, long delayMs) { sendMessage(msg);
Message msg = obtainMessage(what); }
msg.setData(data);
sendMessageDelayed(msg, delayMs);
} }
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
VolumeProvider vp; mCurrentControllerInfo = ((Pair<RemoteUserInfo, Object>) msg.obj).first;
Bundle data = msg.getData();
Bundle originalBundle = getOriginalBundle(data);
mCurrentData = data; VolumeProvider vp;
Object obj = ((Pair<RemoteUserInfo, Object>) msg.obj).second;
switch (msg.what) { switch (msg.what) {
case MSG_COMMAND: case MSG_COMMAND:
Command cmd = (Command) msg.obj; Command cmd = (Command) obj;
mCallback.onCommand(cmd.command, cmd.extras, cmd.stub); mCallback.onCommand(cmd.command, cmd.extras, cmd.stub);
break; break;
case MSG_MEDIA_BUTTON: case MSG_MEDIA_BUTTON:
mCallback.onMediaButtonEvent((Intent) msg.obj); mCallback.onMediaButtonEvent((Intent) obj);
break; break;
case MSG_PREPARE: case MSG_PREPARE:
mCallback.onPrepare(); mCallback.onPrepare();
break; break;
case MSG_PREPARE_MEDIA_ID: case MSG_PREPARE_MEDIA_ID:
mCallback.onPrepareFromMediaId((String) msg.obj, originalBundle); mCallback.onPrepareFromMediaId((String) obj, msg.getData());
break; break;
case MSG_PREPARE_SEARCH: case MSG_PREPARE_SEARCH:
mCallback.onPrepareFromSearch((String) msg.obj, originalBundle); mCallback.onPrepareFromSearch((String) obj, msg.getData());
break; break;
case MSG_PREPARE_URI: case MSG_PREPARE_URI:
mCallback.onPrepareFromUri((Uri) msg.obj, originalBundle); mCallback.onPrepareFromUri((Uri) obj, msg.getData());
break; break;
case MSG_PLAY: case MSG_PLAY:
mCallback.onPlay(); mCallback.onPlay();
break; break;
case MSG_PLAY_MEDIA_ID: case MSG_PLAY_MEDIA_ID:
mCallback.onPlayFromMediaId((String) msg.obj, originalBundle); mCallback.onPlayFromMediaId((String) obj, msg.getData());
break; break;
case MSG_PLAY_SEARCH: case MSG_PLAY_SEARCH:
mCallback.onPlayFromSearch((String) msg.obj, originalBundle); mCallback.onPlayFromSearch((String) obj, msg.getData());
break; break;
case MSG_PLAY_URI: case MSG_PLAY_URI:
mCallback.onPlayFromUri((Uri) msg.obj, originalBundle); mCallback.onPlayFromUri((Uri) obj, msg.getData());
break; break;
case MSG_SKIP_TO_ITEM: case MSG_SKIP_TO_ITEM:
mCallback.onSkipToQueueItem((Long) msg.obj); mCallback.onSkipToQueueItem((Long) obj);
break; break;
case MSG_PAUSE: case MSG_PAUSE:
mCallback.onPause(); mCallback.onPause();
@@ -1532,20 +1516,20 @@ public final class MediaSession {
mCallback.onRewind(); mCallback.onRewind();
break; break;
case MSG_SEEK_TO: case MSG_SEEK_TO:
mCallback.onSeekTo((Long) msg.obj); mCallback.onSeekTo((Long) obj);
break; break;
case MSG_RATE: case MSG_RATE:
mCallback.onSetRating((Rating) msg.obj); mCallback.onSetRating((Rating) obj);
break; break;
case MSG_CUSTOM_ACTION: case MSG_CUSTOM_ACTION:
mCallback.onCustomAction((String) msg.obj, originalBundle); mCallback.onCustomAction((String) obj, msg.getData());
break; break;
case MSG_ADJUST_VOLUME: case MSG_ADJUST_VOLUME:
synchronized (mLock) { synchronized (mLock) {
vp = mVolumeProvider; vp = mVolumeProvider;
} }
if (vp != null) { if (vp != null) {
vp.onAdjustVolume((int) msg.obj); vp.onAdjustVolume((int) obj);
} }
break; break;
case MSG_SET_VOLUME: case MSG_SET_VOLUME:
@@ -1553,14 +1537,14 @@ public final class MediaSession {
vp = mVolumeProvider; vp = mVolumeProvider;
} }
if (vp != null) { if (vp != null) {
vp.onSetVolumeTo((int) msg.obj); vp.onSetVolumeTo((int) obj);
} }
break; break;
case MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT: case MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT:
mCallback.handleMediaPlayPauseKeySingleTapIfPending(); mCallback.handleMediaPlayPauseKeySingleTapIfPending();
break; break;
} }
mCurrentData = null; mCurrentControllerInfo = null;
} }
} }
} }

View File

@@ -30,6 +30,7 @@ import android.media.ISessionTokensListener;
import android.media.MediaSession2; import android.media.MediaSession2;
import android.media.MediaSessionService2; import android.media.MediaSessionService2;
import android.media.SessionToken2; import android.media.SessionToken2;
import android.media.browse.MediaBrowser;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
@@ -818,19 +819,31 @@ public final class MediaSessionManager {
/** /**
* Information of a remote user of {@link MediaSession} or {@link MediaBrowserService}. * Information of a remote user of {@link MediaSession} or {@link MediaBrowserService}.
* This can be used to decide whether the remote user is trusted app. * This can be used to decide whether the remote user is trusted app, and also differentiate
* caller of {@link MediaSession} and {@link MediaBrowserService} callbacks.
* <p>
* See {@link #equals(Object)} to take a look at how it differentiate media controller.
* *
* @see #isTrustedForMediaControl(RemoteUserInfo) * @see #isTrustedForMediaControl(RemoteUserInfo)
*/ */
public static final class RemoteUserInfo { public static final class RemoteUserInfo {
private String mPackageName; private final String mPackageName;
private int mPid; private final int mPid;
private int mUid; private final int mUid;
private final IBinder mCallerBinder;
public RemoteUserInfo(String packageName, int pid, int uid) { public RemoteUserInfo(@NonNull String packageName, int pid, int uid) {
this(packageName, pid, uid, null);
}
/**
* @hide
*/
public RemoteUserInfo(String packageName, int pid, int uid, IBinder callerBinder) {
mPackageName = packageName; mPackageName = packageName;
mPid = pid; mPid = pid;
mUid = uid; mUid = uid;
mCallerBinder = callerBinder;
} }
/** /**
@@ -854,15 +867,29 @@ public final class MediaSessionManager {
return mUid; return mUid;
} }
/**
* Returns equality of two RemoteUserInfo. Two RemoteUserInfos are the same only if they're
* sent to the same controller (either {@link MediaController} or
* {@link MediaBrowser}. If it's not nor one of them is triggered by the key presses, they
* would be considered as different one.
* <p>
* If you only want to compare the caller's package, compare them with the
* {@link #getPackageName()}, {@link #getPid()}, and/or {@link #getUid()} directly.
*
* @param obj the reference object with which to compare.
* @return {@code true} if equals, {@code false} otherwise
*/
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof RemoteUserInfo)) { if (!(obj instanceof RemoteUserInfo)) {
return false; return false;
} }
if (this == obj) {
return true;
}
RemoteUserInfo otherUserInfo = (RemoteUserInfo) obj; RemoteUserInfo otherUserInfo = (RemoteUserInfo) obj;
return TextUtils.equals(mPackageName, otherUserInfo.mPackageName) return (mCallerBinder == null || otherUserInfo.mCallerBinder == null) ? false
&& mPid == otherUserInfo.mPid : mCallerBinder.equals(otherUserInfo.mCallerBinder);
&& mUid == otherUserInfo.mUid;
} }
@Override @Override

View File

@@ -235,6 +235,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
* @param packageName The package that made the original volume request. * @param packageName The package that made the original volume request.
* @param pid The pid that made the original volume request. * @param pid The pid that made the original volume request.
* @param uid The uid that made the original volume request. * @param uid The uid that made the original volume request.
* @param caller caller binder. can be {@code null} if it's from the volume key.
* @param asSystemService {@code true} if the event sent to the session as if it was come from * @param asSystemService {@code true} if the event sent to the session as if it was come from
* the system service instead of the app process. This helps sessions to distinguish * the system service instead of the app process. This helps sessions to distinguish
* between the key injection by the app and key events from the hardware devices. * between the key injection by the app and key events from the hardware devices.
@@ -244,8 +245,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
* @param flags Any of the flags from {@link AudioManager}. * @param flags Any of the flags from {@link AudioManager}.
* @param useSuggested True to use adjustSuggestedStreamVolume instead of * @param useSuggested True to use adjustSuggestedStreamVolume instead of
*/ */
public void adjustVolume(String packageName, int pid, int uid, boolean asSystemService, public void adjustVolume(String packageName, int pid, int uid,
int direction, int flags, boolean useSuggested) { ISessionControllerCallback caller, boolean asSystemService, int direction, int flags,
boolean useSuggested) {
int previousFlagPlaySound = flags & AudioManager.FLAG_PLAY_SOUND; int previousFlagPlaySound = flags & AudioManager.FLAG_PLAY_SOUND;
if (isPlaybackActive() || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) { if (isPlaybackActive() || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) {
flags &= ~AudioManager.FLAG_PLAY_SOUND; flags &= ~AudioManager.FLAG_PLAY_SOUND;
@@ -266,7 +268,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
Log.w(TAG, "Muting remote playback is not supported"); Log.w(TAG, "Muting remote playback is not supported");
return; return;
} }
mSessionCb.adjustVolume(packageName, pid, uid, asSystemService, direction); mSessionCb.adjustVolume(packageName, pid, uid, caller, asSystemService, direction);
int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume); int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
mOptimisticVolume = volumeBefore + direction; mOptimisticVolume = volumeBefore + direction;
@@ -285,7 +287,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
} }
} }
public void setVolumeTo(String packageName, int pid, int uid, int value, int flags) { private void setVolumeTo(String packageName, int pid, int uid,
ISessionControllerCallback caller, int value, int flags) {
if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) { if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs); int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
mAudioManagerInternal.setStreamVolumeForUid(stream, value, flags, packageName, uid); mAudioManagerInternal.setStreamVolumeForUid(stream, value, flags, packageName, uid);
@@ -295,7 +298,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
return; return;
} }
value = Math.max(0, Math.min(value, mMaxVolume)); value = Math.max(0, Math.min(value, mMaxVolume));
mSessionCb.setVolumeTo(packageName, pid, uid, value); mSessionCb.setVolumeTo(packageName, pid, uid, caller, value);
int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume); int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
mOptimisticVolume = Math.max(0, Math.min(value, mMaxVolume)); mOptimisticVolume = Math.max(0, Math.min(value, mMaxVolume));
@@ -611,6 +614,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
try { try {
holder.mCallback.onVolumeInfoChanged(info); holder.mCallback.onVolumeInfoChanged(info);
} catch (DeadObjectException e) { } catch (DeadObjectException e) {
mControllerCallbackHolders.remove(i);
logCallbackException("Removing dead callback in pushVolumeUpdate", holder, e); logCallbackException("Removing dead callback in pushVolumeUpdate", holder, e);
} catch (RemoteException e) { } catch (RemoteException e) {
logCallbackException("Unexpected exception in pushVolumeUpdate", holder, e); logCallbackException("Unexpected exception in pushVolumeUpdate", holder, e);
@@ -629,8 +633,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
try { try {
holder.mCallback.onEvent(event, data); holder.mCallback.onEvent(event, data);
} catch (DeadObjectException e) { } catch (DeadObjectException e) {
logCallbackException("Removing dead callback in pushEvent", holder, e);
mControllerCallbackHolders.remove(i); mControllerCallbackHolders.remove(i);
logCallbackException("Removing dead callback in pushEvent", holder, e);
} catch (RemoteException e) { } catch (RemoteException e) {
logCallbackException("unexpected exception in pushEvent", holder, e); logCallbackException("unexpected exception in pushEvent", holder, e);
} }
@@ -705,14 +709,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
return -1; return -1;
} }
private String getPackageName(int uid) {
String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
if (packages != null && packages.length > 0) {
return packages[0];
}
return null;
}
private final Runnable mClearOptimisticVolumeRunnable = new Runnable() { private final Runnable mClearOptimisticVolumeRunnable = new Runnable() {
@Override @Override
public void run() { public void run() {
@@ -913,14 +909,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
public boolean sendMediaButton(String packageName, int pid, int uid, public boolean sendMediaButton(String packageName, int pid, int uid,
boolean asSystemService, KeyEvent keyEvent, int sequenceId, ResultReceiver cb) { boolean asSystemService, KeyEvent keyEvent, int sequenceId, ResultReceiver cb) {
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
try { try {
if (asSystemService) { if (asSystemService) {
mCb.onMediaButton(mContext.getPackageName(), Process.myPid(), mCb.onMediaButton(mContext.getPackageName(), Process.myPid(),
Process.SYSTEM_UID, mediaButtonIntent, sequenceId, cb); Process.SYSTEM_UID, createMediaButtonIntent(keyEvent), sequenceId, cb);
} else { } else {
mCb.onMediaButton(packageName, pid, uid, mediaButtonIntent, sequenceId, cb); mCb.onMediaButton(packageName, pid, uid,
createMediaButtonIntent(keyEvent), sequenceId, cb);
} }
return true; return true;
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -929,205 +924,239 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
return false; return false;
} }
public void sendCommand(String packageName, int pid, int uid, String command, Bundle args, public boolean sendMediaButton(String packageName, int pid, int uid,
ResultReceiver cb) { ISessionControllerCallback caller, boolean asSystemService,
KeyEvent keyEvent) {
try { try {
mCb.onCommand(packageName, pid, uid, command, args, cb); if (asSystemService) {
mCb.onMediaButton(mContext.getPackageName(), Process.myPid(),
Process.SYSTEM_UID, createMediaButtonIntent(keyEvent), 0, null);
} else {
mCb.onMediaButtonFromController(packageName, pid, uid, caller,
createMediaButtonIntent(keyEvent));
}
return true;
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in sendMediaRequest.", e);
}
return false;
}
public void sendCommand(String packageName, int pid, int uid,
ISessionControllerCallback caller, String command, Bundle args, ResultReceiver cb) {
try {
mCb.onCommand(packageName, pid, uid, caller, command, args, cb);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in sendCommand.", e); Slog.e(TAG, "Remote failure in sendCommand.", e);
} }
} }
public void sendCustomAction(String packageName, int pid, int uid, String action, public void sendCustomAction(String packageName, int pid, int uid,
ISessionControllerCallback caller, String action,
Bundle args) { Bundle args) {
try { try {
mCb.onCustomAction(packageName, pid, uid, action, args); mCb.onCustomAction(packageName, pid, uid, caller, action, args);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in sendCustomAction.", e); Slog.e(TAG, "Remote failure in sendCustomAction.", e);
} }
} }
public void prepare(String packageName, int pid, int uid) { public void prepare(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
try { try {
mCb.onPrepare(packageName, pid, uid); mCb.onPrepare(packageName, pid, uid, caller);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in prepare.", e); Slog.e(TAG, "Remote failure in prepare.", e);
} }
} }
public void prepareFromMediaId(String packageName, int pid, int uid, String mediaId, public void prepareFromMediaId(String packageName, int pid, int uid,
Bundle extras) { ISessionControllerCallback caller, String mediaId, Bundle extras) {
try { try {
mCb.onPrepareFromMediaId(packageName, pid, uid, mediaId, extras); mCb.onPrepareFromMediaId(packageName, pid, uid, caller, mediaId, extras);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in prepareFromMediaId.", e); Slog.e(TAG, "Remote failure in prepareFromMediaId.", e);
} }
} }
public void prepareFromSearch(String packageName, int pid, int uid, String query, public void prepareFromSearch(String packageName, int pid, int uid,
Bundle extras) { ISessionControllerCallback caller, String query, Bundle extras) {
try { try {
mCb.onPrepareFromSearch(packageName, pid, uid, query, extras); mCb.onPrepareFromSearch(packageName, pid, uid, caller, query, extras);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in prepareFromSearch.", e); Slog.e(TAG, "Remote failure in prepareFromSearch.", e);
} }
} }
public void prepareFromUri(String packageName, int pid, int uid, Uri uri, public void prepareFromUri(String packageName, int pid, int uid,
Bundle extras) { ISessionControllerCallback caller, Uri uri, Bundle extras) {
try { try {
mCb.onPrepareFromUri(packageName, pid, uid, uri, extras); mCb.onPrepareFromUri(packageName, pid, uid, caller, uri, extras);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in prepareFromUri.", e); Slog.e(TAG, "Remote failure in prepareFromUri.", e);
} }
} }
public void play(String packageName, int pid, int uid) { public void play(String packageName, int pid, int uid, ISessionControllerCallback caller) {
try { try {
mCb.onPlay(packageName, pid, uid); mCb.onPlay(packageName, pid, uid, caller);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in play.", e); Slog.e(TAG, "Remote failure in play.", e);
} }
} }
public void playFromMediaId(String packageName, int pid, int uid, String mediaId, public void playFromMediaId(String packageName, int pid, int uid,
Bundle extras) { ISessionControllerCallback caller, String mediaId, Bundle extras) {
try { try {
mCb.onPlayFromMediaId(packageName, pid, uid, mediaId, extras); mCb.onPlayFromMediaId(packageName, pid, uid, caller, mediaId, extras);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in playFromMediaId.", e); Slog.e(TAG, "Remote failure in playFromMediaId.", e);
} }
} }
public void playFromSearch(String packageName, int pid, int uid, String query, public void playFromSearch(String packageName, int pid, int uid,
Bundle extras) { ISessionControllerCallback caller, String query, Bundle extras) {
try { try {
mCb.onPlayFromSearch(packageName, pid, uid, query, extras); mCb.onPlayFromSearch(packageName, pid, uid, caller, query, extras);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in playFromSearch.", e); Slog.e(TAG, "Remote failure in playFromSearch.", e);
} }
} }
public void playFromUri(String packageName, int pid, int uid, Uri uri, Bundle extras) { public void playFromUri(String packageName, int pid, int uid,
ISessionControllerCallback caller, Uri uri, Bundle extras) {
try { try {
mCb.onPlayFromUri(packageName, pid, uid, uri, extras); mCb.onPlayFromUri(packageName, pid, uid, caller, uri, extras);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in playFromUri.", e); Slog.e(TAG, "Remote failure in playFromUri.", e);
} }
} }
public void skipToTrack(String packageName, int pid, int uid, long id) { public void skipToTrack(String packageName, int pid, int uid,
ISessionControllerCallback caller, long id) {
try { try {
mCb.onSkipToTrack(packageName, pid, uid, id); mCb.onSkipToTrack(packageName, pid, uid, caller, id);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in skipToTrack", e); Slog.e(TAG, "Remote failure in skipToTrack", e);
} }
} }
public void pause(String packageName, int pid, int uid) { public void pause(String packageName, int pid, int uid, ISessionControllerCallback caller) {
try { try {
mCb.onPause(packageName, pid, uid); mCb.onPause(packageName, pid, uid, caller);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in pause.", e); Slog.e(TAG, "Remote failure in pause.", e);
} }
} }
public void stop(String packageName, int pid, int uid) { public void stop(String packageName, int pid, int uid, ISessionControllerCallback caller) {
try { try {
mCb.onStop(packageName, pid, uid); mCb.onStop(packageName, pid, uid, caller);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in stop.", e); Slog.e(TAG, "Remote failure in stop.", e);
} }
} }
public void next(String packageName, int pid, int uid) { public void next(String packageName, int pid, int uid, ISessionControllerCallback caller) {
try { try {
mCb.onNext(packageName, pid, uid); mCb.onNext(packageName, pid, uid, caller);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in next.", e); Slog.e(TAG, "Remote failure in next.", e);
} }
} }
public void previous(String packageName, int pid, int uid) { public void previous(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
try { try {
mCb.onPrevious(packageName, pid, uid); mCb.onPrevious(packageName, pid, uid, caller);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in previous.", e); Slog.e(TAG, "Remote failure in previous.", e);
} }
} }
public void fastForward(String packageName, int pid, int uid) { public void fastForward(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
try { try {
mCb.onFastForward(packageName, pid, uid); mCb.onFastForward(packageName, pid, uid, caller);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in fastForward.", e); Slog.e(TAG, "Remote failure in fastForward.", e);
} }
} }
public void rewind(String packageName, int pid, int uid) { public void rewind(String packageName, int pid, int uid,
ISessionControllerCallback caller) {
try { try {
mCb.onRewind(packageName, pid, uid); mCb.onRewind(packageName, pid, uid, caller);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in rewind.", e); Slog.e(TAG, "Remote failure in rewind.", e);
} }
} }
public void seekTo(String packageName, int pid, int uid, long pos) { public void seekTo(String packageName, int pid, int uid, ISessionControllerCallback caller,
long pos) {
try { try {
mCb.onSeekTo(packageName, pid, uid, pos); mCb.onSeekTo(packageName, pid, uid, caller, pos);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in seekTo.", e); Slog.e(TAG, "Remote failure in seekTo.", e);
} }
} }
public void rate(String packageName, int pid, int uid, Rating rating) { public void rate(String packageName, int pid, int uid, ISessionControllerCallback caller,
Rating rating) {
try { try {
mCb.onRate(packageName, pid, uid, rating); mCb.onRate(packageName, pid, uid, caller, rating);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in rate.", e); Slog.e(TAG, "Remote failure in rate.", e);
} }
} }
public void adjustVolume(String packageName, int pid, int uid, boolean asSystemService, public void adjustVolume(String packageName, int pid, int uid,
int direction) { ISessionControllerCallback caller, boolean asSystemService, int direction) {
try { try {
if (asSystemService) { if (asSystemService) {
mCb.onAdjustVolume(mContext.getPackageName(), Process.myPid(), mCb.onAdjustVolume(mContext.getPackageName(), Process.myPid(),
Process.SYSTEM_UID, direction); Process.SYSTEM_UID, null, direction);
} else { } else {
mCb.onAdjustVolume(packageName, pid, uid, direction); mCb.onAdjustVolume(packageName, pid, uid, caller, direction);
} }
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in adjustVolume.", e); Slog.e(TAG, "Remote failure in adjustVolume.", e);
} }
} }
public void setVolumeTo(String packageName, int pid, int uid, int value) { public void setVolumeTo(String packageName, int pid, int uid,
ISessionControllerCallback caller, int value) {
try { try {
mCb.onSetVolumeTo(packageName, pid, uid, value); mCb.onSetVolumeTo(packageName, pid, uid, caller, value);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Remote failure in setVolumeTo.", e); Slog.e(TAG, "Remote failure in setVolumeTo.", e);
} }
} }
private Intent createMediaButtonIntent(KeyEvent keyEvent) {
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
return mediaButtonIntent;
}
} }
class ControllerStub extends ISessionController.Stub { class ControllerStub extends ISessionController.Stub {
@Override @Override
public void sendCommand(String packageName, String command, Bundle args, public void sendCommand(String packageName, ISessionControllerCallback caller,
ResultReceiver cb) { String command, Bundle args, ResultReceiver cb) {
mSessionCb.sendCommand(packageName, Binder.getCallingPid(), Binder.getCallingUid(), mSessionCb.sendCommand(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
command, args, cb); caller, command, args, cb);
} }
@Override @Override
public boolean sendMediaButton(String packageName, boolean asSystemService, public boolean sendMediaButton(String packageName, ISessionControllerCallback cb,
KeyEvent mediaButtonIntent) { boolean asSystemService, KeyEvent keyEvent) {
return mSessionCb.sendMediaButton(packageName, Binder.getCallingPid(), return mSessionCb.sendMediaButton(packageName, Binder.getCallingPid(),
Binder.getCallingUid(), asSystemService, mediaButtonIntent, 0, null); Binder.getCallingUid(), cb, asSystemService, keyEvent);
} }
@Override @Override
public void registerCallbackListener(ISessionControllerCallback cb) { public void registerCallbackListener(String packageName, ISessionControllerCallback cb) {
synchronized (mLock) { synchronized (mLock) {
// If this session is already destroyed tell the caller and // If this session is already destroyed tell the caller and
// don't add them. // don't add them.
@@ -1141,24 +1170,24 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
} }
if (getControllerHolderIndexForCb(cb) < 0) { if (getControllerHolderIndexForCb(cb) < 0) {
mControllerCallbackHolders.add(new ISessionControllerCallbackHolder(cb, mControllerCallbackHolders.add(new ISessionControllerCallbackHolder(cb,
Binder.getCallingUid())); packageName, Binder.getCallingUid()));
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "registering controller callback " + cb); Log.d(TAG, "registering controller callback " + cb + " from controller"
+ packageName);
} }
} }
} }
} }
@Override @Override
public void unregisterCallbackListener(ISessionControllerCallback cb) public void unregisterCallbackListener(ISessionControllerCallback cb) {
throws RemoteException {
synchronized (mLock) { synchronized (mLock) {
int index = getControllerHolderIndexForCb(cb); int index = getControllerHolderIndexForCb(cb);
if (index != -1) { if (index != -1) {
mControllerCallbackHolders.remove(index); mControllerCallbackHolders.remove(index);
} }
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "unregistering callback " + cb + ". index=" + index); Log.d(TAG, "unregistering callback " + cb.asBinder());
} }
} }
} }
@@ -1204,13 +1233,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
} }
@Override @Override
public void adjustVolume(String packageName, boolean asSystemService, int direction, public void adjustVolume(String packageName, ISessionControllerCallback caller,
int flags) { boolean asSystemService, int direction, int flags) {
int pid = Binder.getCallingPid(); int pid = Binder.getCallingPid();
int uid = Binder.getCallingUid(); int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity();
try { try {
MediaSessionRecord.this.adjustVolume(packageName, pid, uid, asSystemService, MediaSessionRecord.this.adjustVolume(packageName, pid, uid, caller, asSystemService,
direction, flags, false /* useSuggested */); direction, flags, false /* useSuggested */);
} finally { } finally {
Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token);
@@ -1218,115 +1247,128 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
} }
@Override @Override
public void setVolumeTo(String packageName, int value, int flags) { public void setVolumeTo(String packageName, ISessionControllerCallback caller,
int value, int flags) {
int pid = Binder.getCallingPid(); int pid = Binder.getCallingPid();
int uid = Binder.getCallingUid(); int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity();
try { try {
MediaSessionRecord.this.setVolumeTo(packageName, pid, uid, value, flags); MediaSessionRecord.this.setVolumeTo(packageName, pid, uid, caller, value, flags);
} finally { } finally {
Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token);
} }
} }
@Override @Override
public void prepare(String packageName) { public void prepare(String packageName, ISessionControllerCallback caller) {
mSessionCb.prepare(packageName, Binder.getCallingPid(), Binder.getCallingUid()); mSessionCb.prepare(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
} }
@Override @Override
public void prepareFromMediaId(String packageName, String mediaId, Bundle extras) { public void prepareFromMediaId(String packageName, ISessionControllerCallback caller,
String mediaId, Bundle extras) {
mSessionCb.prepareFromMediaId(packageName, Binder.getCallingPid(), mSessionCb.prepareFromMediaId(packageName, Binder.getCallingPid(),
Binder.getCallingUid(), mediaId, extras); Binder.getCallingUid(), caller, mediaId, extras);
} }
@Override @Override
public void prepareFromSearch(String packageName, String query, Bundle extras) { public void prepareFromSearch(String packageName, ISessionControllerCallback caller,
String query, Bundle extras) {
mSessionCb.prepareFromSearch(packageName, Binder.getCallingPid(), mSessionCb.prepareFromSearch(packageName, Binder.getCallingPid(),
Binder.getCallingUid(), query, extras); Binder.getCallingUid(), caller, query, extras);
} }
@Override @Override
public void prepareFromUri(String packageName, Uri uri, Bundle extras) { public void prepareFromUri(String packageName, ISessionControllerCallback caller,
Uri uri, Bundle extras) {
mSessionCb.prepareFromUri(packageName, Binder.getCallingPid(), Binder.getCallingUid(), mSessionCb.prepareFromUri(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
uri, extras); caller, uri, extras);
} }
@Override @Override
public void play(String packageName) { public void play(String packageName, ISessionControllerCallback caller) {
mSessionCb.play(packageName, Binder.getCallingPid(), Binder.getCallingUid()); mSessionCb.play(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
} }
@Override @Override
public void playFromMediaId(String packageName, String mediaId, Bundle extras) { public void playFromMediaId(String packageName, ISessionControllerCallback caller,
String mediaId, Bundle extras) {
mSessionCb.playFromMediaId(packageName, Binder.getCallingPid(), Binder.getCallingUid(), mSessionCb.playFromMediaId(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
mediaId, extras); caller, mediaId, extras);
} }
@Override @Override
public void playFromSearch(String packageName, String query, Bundle extras) { public void playFromSearch(String packageName, ISessionControllerCallback caller,
String query, Bundle extras) {
mSessionCb.playFromSearch(packageName, Binder.getCallingPid(), Binder.getCallingUid(), mSessionCb.playFromSearch(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
query, extras); caller, query, extras);
} }
@Override @Override
public void playFromUri(String packageName, Uri uri, Bundle extras) { public void playFromUri(String packageName, ISessionControllerCallback caller,
Uri uri, Bundle extras) {
mSessionCb.playFromUri(packageName, Binder.getCallingPid(), Binder.getCallingUid(), mSessionCb.playFromUri(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
uri, extras); caller, uri, extras);
} }
@Override @Override
public void skipToQueueItem(String packageName, long id) { public void skipToQueueItem(String packageName, ISessionControllerCallback caller,
mSessionCb.skipToTrack(packageName, Binder.getCallingPid(), Binder.getCallingUid(), id); long id) {
mSessionCb.skipToTrack(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
caller, id);
} }
@Override @Override
public void pause(String packageName) { public void pause(String packageName, ISessionControllerCallback caller) {
mSessionCb.pause(packageName, Binder.getCallingPid(), Binder.getCallingUid()); mSessionCb.pause(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
} }
@Override @Override
public void stop(String packageName) { public void stop(String packageName, ISessionControllerCallback caller) {
mSessionCb.stop(packageName, Binder.getCallingPid(), Binder.getCallingUid()); mSessionCb.stop(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
} }
@Override @Override
public void next(String packageName) { public void next(String packageName, ISessionControllerCallback caller) {
mSessionCb.next(packageName, Binder.getCallingPid(), Binder.getCallingUid()); mSessionCb.next(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
} }
@Override @Override
public void previous(String packageName) { public void previous(String packageName, ISessionControllerCallback caller) {
mSessionCb.previous(packageName, Binder.getCallingPid(), Binder.getCallingUid()); mSessionCb.previous(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
caller);
} }
@Override @Override
public void fastForward(String packageName) { public void fastForward(String packageName, ISessionControllerCallback caller) {
mSessionCb.fastForward(packageName, Binder.getCallingPid(), Binder.getCallingUid()); mSessionCb.fastForward(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
caller);
} }
@Override @Override
public void rewind(String packageName) { public void rewind(String packageName, ISessionControllerCallback caller) {
mSessionCb.rewind(packageName, Binder.getCallingPid(), Binder.getCallingUid()); mSessionCb.rewind(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
} }
@Override @Override
public void seekTo(String packageName, long pos) { public void seekTo(String packageName, ISessionControllerCallback caller, long pos) {
mSessionCb.seekTo(packageName, Binder.getCallingPid(), Binder.getCallingUid(), pos); mSessionCb.seekTo(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller,
pos);
} }
@Override @Override
public void rate(String packageName, Rating rating) { public void rate(String packageName, ISessionControllerCallback caller, Rating rating) {
mSessionCb.rate(packageName, Binder.getCallingPid(), Binder.getCallingUid(), rating); mSessionCb.rate(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller,
rating);
} }
@Override @Override
public void sendCustomAction(String packageName, String action, Bundle args) { public void sendCustomAction(String packageName, ISessionControllerCallback caller,
String action, Bundle args) {
mSessionCb.sendCustomAction(packageName, Binder.getCallingPid(), Binder.getCallingUid(), mSessionCb.sendCustomAction(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
action, args); caller, action, args);
} }
@Override @Override
public MediaMetadata getMetadata() { public MediaMetadata getMetadata() {
synchronized (mLock) { synchronized (mLock) {
@@ -1372,10 +1414,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private class ISessionControllerCallbackHolder { private class ISessionControllerCallbackHolder {
private final ISessionControllerCallback mCallback; private final ISessionControllerCallback mCallback;
private final String mPackageName; private final String mPackageName;
private final int mUid;
ISessionControllerCallbackHolder(ISessionControllerCallback callback, int uid) { ISessionControllerCallbackHolder(ISessionControllerCallback callback, String packageName,
int uid) {
mCallback = callback; mCallback = callback;
mPackageName = getPackageName(uid); mPackageName = packageName;
mUid = uid;
} }
} }

View File

@@ -1851,7 +1851,7 @@ public class MediaSessionService extends SystemService implements Monitor {
} }
}); });
} else { } else {
session.adjustVolume(packageName, pid, uid, asSystemService, session.adjustVolume(packageName, pid, uid, null, asSystemService,
direction, flags, true); direction, flags, true);
} }
} }