Introduce link classes for media mainline module
Bug: 121239200
Test: make update-api -j / make -j
atest CtsMediaTestCases:android.media.cts.MediaSessionTest
atest CtsMediaTestCases:android.media.cts.MediaControllerTest
Change-Id: I93662e83a82f111bfdf25e22525c1466dd66079f
diff --git a/api/current.txt b/api/current.txt
index 6122e52..d378416 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27286,21 +27286,6 @@
package android.media.session {
- public final class ControllerCallbackLink implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.os.IBinder getBinder();
- method public void notifyEvent(@NonNull String, @Nullable android.os.Bundle);
- method public void notifyExtrasChanged(@Nullable android.os.Bundle);
- method public void notifyMetadataChanged(@Nullable android.media.MediaMetadata);
- method public void notifyPlaybackStateChanged(@Nullable android.media.session.PlaybackState);
- method public void notifyQueueChanged(@Nullable java.util.List<android.media.session.MediaSession.QueueItem>);
- method public void notifyQueueTitleChanged(@Nullable CharSequence);
- method public void notifySessionDestroyed();
- method public void notifyVolumeInfoChanged(@NonNull android.media.session.MediaController.PlaybackInfo);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.media.session.ControllerCallbackLink> CREATOR;
- }
-
public final class MediaController {
ctor public MediaController(@NonNull android.content.Context, @NonNull android.media.session.MediaSession.Token);
method public void adjustVolume(int, int);
@@ -27535,36 +27520,6 @@
method public android.media.session.PlaybackState.CustomAction.Builder setExtras(android.os.Bundle);
}
- public final class SessionCallbackLink implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.os.IBinder getBinder();
- method public void notifyAdjustVolume(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, int);
- method public void notifyCommand(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle, @Nullable android.os.ResultReceiver);
- method public void notifyCustomAction(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
- method public void notifyFastForward(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
- method public void notifyMediaButton(@NonNull String, int, int, @NonNull android.content.Intent, int, @Nullable android.os.ResultReceiver);
- method public void notifyMediaButtonFromController(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull android.content.Intent);
- method public void notifyNext(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
- method public void notifyPause(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
- method public void notifyPlay(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
- method public void notifyPlayFromMediaId(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
- method public void notifyPlayFromSearch(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
- method public void notifyPlayFromUri(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull android.net.Uri, @Nullable android.os.Bundle);
- method public void notifyPrepare(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
- method public void notifyPrepareFromMediaId(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
- method public void notifyPrepareFromSearch(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
- method public void notifyPrepareFromUri(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull android.net.Uri, @Nullable android.os.Bundle);
- method public void notifyPrevious(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
- method public void notifyRate(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull android.media.Rating);
- method public void notifyRewind(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
- method public void notifySeekTo(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, long);
- method public void notifySetVolumeTo(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, int);
- method public void notifySkipToTrack(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, long);
- method public void notifyStop(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.media.session.SessionCallbackLink> CREATOR;
- }
-
}
package android.media.tv {
diff --git a/api/system-current.txt b/api/system-current.txt
index ce0ef38..810b237 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3448,7 +3448,20 @@
package android.media.session {
public final class ControllerCallbackLink implements android.os.Parcelable {
- ctor public ControllerCallbackLink(@NonNull android.media.session.ControllerCallbackLink.CallbackStub);
+ ctor public ControllerCallbackLink(@NonNull android.content.Context, @NonNull android.media.session.ControllerCallbackLink.CallbackStub);
+ ctor public ControllerCallbackLink(android.os.IBinder);
+ method public int describeContents();
+ method @NonNull public android.os.IBinder getBinder();
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyEvent(@NonNull String, @Nullable android.os.Bundle);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyExtrasChanged(@Nullable android.os.Bundle);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyMetadataChanged(@Nullable android.media.MediaMetadata);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyPlaybackStateChanged(@Nullable android.media.session.PlaybackState);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyQueueChanged(@Nullable java.util.List<android.media.session.MediaSession.QueueItem>);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyQueueTitleChanged(@Nullable CharSequence);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifySessionDestroyed();
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyVolumeInfoChanged(@NonNull android.media.session.MediaController.PlaybackInfo);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.media.session.ControllerCallbackLink> CREATOR;
}
public abstract static class ControllerCallbackLink.CallbackStub {
@@ -3463,6 +3476,60 @@
method public void onVolumeInfoChanged(@NonNull android.media.session.MediaController.PlaybackInfo);
}
+ public final class ControllerLink implements android.os.Parcelable {
+ ctor public ControllerLink(@NonNull android.media.session.ControllerLink.ControllerStub);
+ ctor public ControllerLink(android.os.IBinder);
+ method public int describeContents();
+ method @NonNull public android.os.IBinder getBinder();
+ method @Nullable public android.os.Bundle getExtras();
+ method @Nullable public android.media.MediaMetadata getMetadata();
+ method @Nullable public android.media.session.PlaybackState getPlaybackState();
+ method @Nullable public java.util.List<android.media.session.MediaSession.QueueItem> getQueue();
+ method @Nullable public CharSequence getQueueTitle();
+ method public int getRatingType();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.media.session.ControllerLink> CREATOR;
+ }
+
+ public abstract static class ControllerLink.ControllerStub {
+ ctor public ControllerLink.ControllerStub();
+ method public void adjustVolume(@NonNull String, @NonNull String, @NonNull android.media.session.ControllerCallbackLink, boolean, int, int);
+ method public void fastForward(@NonNull String, @NonNull android.media.session.ControllerCallbackLink);
+ method @Nullable public android.os.Bundle getExtras();
+ method public long getFlags();
+ method @Nullable public android.app.PendingIntent getLaunchPendingIntent();
+ method @Nullable public android.media.MediaMetadata getMetadata();
+ method @NonNull public String getPackageName();
+ method @Nullable public android.media.session.PlaybackState getPlaybackState();
+ method @Nullable public java.util.List<android.media.session.MediaSession.QueueItem> getQueue();
+ method @Nullable public CharSequence getQueueTitle();
+ method public int getRatingType();
+ method @NonNull public String getTag();
+ method @NonNull public android.media.session.MediaController.PlaybackInfo getVolumeAttributes();
+ method public void next(@NonNull String, @NonNull android.media.session.ControllerCallbackLink);
+ method public void pause(@NonNull String, @NonNull android.media.session.ControllerCallbackLink);
+ method public void play(@NonNull String, @NonNull android.media.session.ControllerCallbackLink);
+ method public void playFromMediaId(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
+ method public void playFromSearch(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
+ method public void playFromUri(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, @NonNull android.net.Uri, @Nullable android.os.Bundle);
+ method public void prepare(@NonNull String, @NonNull android.media.session.ControllerCallbackLink);
+ method public void prepareFromMediaId(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
+ method public void prepareFromSearch(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
+ method public void prepareFromUri(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, @NonNull android.net.Uri, @Nullable android.os.Bundle);
+ method public void previous(@NonNull String, @NonNull android.media.session.ControllerCallbackLink);
+ method public void rate(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, @NonNull android.media.Rating);
+ method public void registerCallback(@NonNull String, @NonNull android.media.session.ControllerCallbackLink);
+ method public void rewind(@NonNull String, @NonNull android.media.session.ControllerCallbackLink);
+ method public void seekTo(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, long);
+ method public void sendCommand(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle, @Nullable android.os.ResultReceiver);
+ method public void sendCustomAction(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
+ method public boolean sendMediaButton(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, boolean, @NonNull android.view.KeyEvent);
+ method public void setVolumeTo(@NonNull String, @NonNull String, @NonNull android.media.session.ControllerCallbackLink, int, int);
+ method public void skipToQueueItem(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, long);
+ method public void stop(@NonNull String, @NonNull android.media.session.ControllerCallbackLink);
+ method public void unregisterCallback(@NonNull android.media.session.ControllerCallbackLink);
+ }
+
public final class MediaSessionManager {
method @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER) public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, @Nullable android.os.Handler);
method @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER) public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, @Nullable android.os.Handler);
@@ -3476,6 +3543,66 @@
method public void onVolumeKeyLongPress(android.view.KeyEvent);
}
+ public final class SessionCallbackLink implements android.os.Parcelable {
+ ctor public SessionCallbackLink(android.os.IBinder);
+ method public int describeContents();
+ method @NonNull public android.os.IBinder getBinder();
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyAdjustVolume(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, int);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyCommand(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle, @Nullable android.os.ResultReceiver);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyCustomAction(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyFastForward(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyMediaButton(@NonNull String, int, int, @NonNull android.content.Intent, int, @Nullable android.os.ResultReceiver);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyMediaButtonFromController(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull android.content.Intent);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyNext(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyPause(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyPlay(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyPlayFromMediaId(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyPlayFromSearch(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyPlayFromUri(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull android.net.Uri, @Nullable android.os.Bundle);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyPrepare(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyPrepareFromMediaId(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyPrepareFromSearch(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyPrepareFromUri(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull android.net.Uri, @Nullable android.os.Bundle);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyPrevious(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyRate(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, @NonNull android.media.Rating);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyRewind(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifySeekTo(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, long);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifySetVolumeTo(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, int);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifySkipToTrack(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink, long);
+ method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void notifyStop(@NonNull String, int, int, @NonNull android.media.session.ControllerCallbackLink);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.media.session.SessionCallbackLink> CREATOR;
+ }
+
+ public final class SessionLink implements android.os.Parcelable {
+ ctor public SessionLink(@NonNull android.media.session.SessionLink.SessionStub);
+ ctor public SessionLink(android.os.IBinder);
+ method public int describeContents();
+ method @NonNull public android.os.IBinder getBinder();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.media.session.SessionLink> CREATOR;
+ }
+
+ public abstract static class SessionLink.SessionStub {
+ ctor public SessionLink.SessionStub();
+ method public void destroySession();
+ method @NonNull public android.media.session.ControllerLink getController();
+ method public void sendEvent(@NonNull String, @Nullable android.os.Bundle);
+ method public void setActive(boolean);
+ method public void setCurrentVolume(int);
+ method public void setExtras(@Nullable android.os.Bundle);
+ method public void setFlags(int);
+ method public void setLaunchPendingIntent(@Nullable android.app.PendingIntent);
+ method public void setMediaButtonReceiver(@Nullable android.app.PendingIntent);
+ method public void setMetadata(@Nullable android.media.MediaMetadata, long, @Nullable String);
+ method public void setPlaybackState(@Nullable android.media.session.PlaybackState);
+ method public void setPlaybackToLocal(@NonNull android.media.AudioAttributes);
+ method public void setPlaybackToRemote(int, int);
+ method public void setQueue(@Nullable java.util.List<android.media.session.MediaSession.QueueItem>);
+ method public void setQueueTitle(@Nullable CharSequence);
+ method public void setRatingType(int);
+ }
+
}
package android.media.soundtrigger {
diff --git a/media/java/android/media/IRemoteVolumeController.aidl b/media/java/android/media/IRemoteVolumeController.aidl
index e4a4a42..a591c11 100644
--- a/media/java/android/media/IRemoteVolumeController.aidl
+++ b/media/java/android/media/IRemoteVolumeController.aidl
@@ -25,8 +25,8 @@
* @hide
*/
oneway interface IRemoteVolumeController {
- void remoteVolumeChanged(ISessionController session, int flags);
+ void remoteVolumeChanged(in ISessionController session, int flags);
// sets the default session to use with the slider, replaces remoteSliderVisibility
// on IVolumeController
- void updateRemoteController(ISessionController session);
+ void updateRemoteController(in ISessionController session);
}
diff --git a/media/java/android/media/session/ControllerCallbackLink.java b/media/java/android/media/session/ControllerCallbackLink.java
index a143c9b..95e19d2 100644
--- a/media/java/android/media/session/ControllerCallbackLink.java
+++ b/media/java/android/media/session/ControllerCallbackLink.java
@@ -16,35 +16,41 @@
package android.media.session;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.media.MediaMetadata;
import android.media.session.MediaController.PlaybackInfo;
import android.media.session.MediaSession.QueueItem;
+import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Process;
import android.os.RemoteException;
import java.util.List;
/**
* Handles incoming commands to {@link MediaController.Callback}.
- * <p>
- * This API is not generally intended for third party application developers.
+ * @hide
*/
+@SystemApi
public final class ControllerCallbackLink implements Parcelable {
+ final Context mContext;
final CallbackStub mCallbackStub;
final ISessionControllerCallback mIControllerCallback;
/**
* Constructor for stub (Callee)
- * @hide
*/
- @SystemApi
- public ControllerCallbackLink(@NonNull CallbackStub callbackStub) {
+ public ControllerCallbackLink(@NonNull Context context, @NonNull CallbackStub callbackStub) {
+ mContext = context;
mCallbackStub = callbackStub;
mIControllerCallback = new CallbackStubProxy();
}
@@ -52,14 +58,16 @@
/**
* Constructor for interface (Caller)
*/
- ControllerCallbackLink(Parcel in) {
+ public ControllerCallbackLink(IBinder binder) {
+ mContext = null;
mCallbackStub = null;
- mIControllerCallback = ISessionControllerCallback.Stub.asInterface(in.readStrongBinder());
+ mIControllerCallback = ISessionControllerCallback.Stub.asInterface(binder);
}
/**
* Notify controller that the connected session is destroyed.
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifySessionDestroyed() {
try {
mIControllerCallback.notifySessionDestroyed();
@@ -74,6 +82,7 @@
* @param event the name of the event
* @param extras the extras included with the event
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyEvent(@NonNull String event, @Nullable Bundle extras) {
try {
mIControllerCallback.notifyEvent(event, extras);
@@ -87,6 +96,7 @@
*
* @param state the new playback state
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyPlaybackStateChanged(@Nullable PlaybackState state) {
try {
mIControllerCallback.notifyPlaybackStateChanged(state);
@@ -100,6 +110,7 @@
*
* @param metadata the new metadata
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyMetadataChanged(@Nullable MediaMetadata metadata) {
try {
mIControllerCallback.notifyMetadataChanged(metadata);
@@ -113,6 +124,7 @@
*
* @param queue the new queue
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyQueueChanged(@Nullable List<QueueItem> queue) {
try {
mIControllerCallback.notifyQueueChanged(queue);
@@ -126,6 +138,7 @@
*
* @param title the new queue title
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyQueueTitleChanged(@Nullable CharSequence title) {
try {
mIControllerCallback.notifyQueueTitleChanged(title);
@@ -139,6 +152,7 @@
*
* @param extras the new extras
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyExtrasChanged(@Nullable Bundle extras) {
try {
mIControllerCallback.notifyExtrasChanged(extras);
@@ -152,6 +166,7 @@
*
* @param info the new playback info
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyVolumeInfoChanged(@NonNull PlaybackInfo info) {
try {
mIControllerCallback.notifyVolumeInfoChanged(info);
@@ -180,7 +195,7 @@
new Parcelable.Creator<ControllerCallbackLink>() {
@Override
public ControllerCallbackLink createFromParcel(Parcel in) {
- return new ControllerCallbackLink(in);
+ return new ControllerCallbackLink(in.readStrongBinder());
}
@Override
@@ -191,9 +206,7 @@
/**
* Class for Stub implementation
- * @hide
*/
- @SystemApi
public abstract static class CallbackStub {
/** Stub method for ISessionControllerCallback.notifySessionDestroyed */
public void onSessionDestroyed() {
@@ -241,22 +254,46 @@
@Override
public void notifyPlaybackStateChanged(PlaybackState state) {
- mCallbackStub.onPlaybackStateChanged(state);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onPlaybackStateChanged(state);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyMetadataChanged(MediaMetadata metadata) {
- mCallbackStub.onMetadataChanged(metadata);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onMetadataChanged(metadata);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyQueueChanged(List<QueueItem> queue) {
- mCallbackStub.onQueueChanged(queue);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onQueueChanged(queue);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyQueueTitleChanged(CharSequence title) {
- mCallbackStub.onQueueTitleChanged(title);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onQueueTitleChanged(title);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
@@ -266,7 +303,31 @@
@Override
public void notifyVolumeInfoChanged(PlaybackInfo info) {
- mCallbackStub.onVolumeInfoChanged(info);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onVolumeInfoChanged(info);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void ensureMediasControlPermission() {
+ // Allow API calls from the System UI
+ if (mContext.checkCallingPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+
+ // Check if it's system server or has MEDIA_CONTENT_CONTROL.
+ // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
+ // check here.
+ if (getCallingUid() == Process.SYSTEM_UID || mContext.checkCallingPermission(
+ android.Manifest.permission.MEDIA_CONTENT_CONTROL)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ throw new SecurityException("Must hold the MEDIA_CONTENT_CONTROL permission.");
}
}
}
diff --git a/media/java/android/media/session/ControllerLink.aidl b/media/java/android/media/session/ControllerLink.aidl
new file mode 100644
index 0000000..532df59
--- /dev/null
+++ b/media/java/android/media/session/ControllerLink.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.session;
+
+parcelable ControllerLink;
diff --git a/media/java/android/media/session/ControllerLink.java b/media/java/android/media/session/ControllerLink.java
new file mode 100644
index 0000000..df1d649
--- /dev/null
+++ b/media/java/android/media/session/ControllerLink.java
@@ -0,0 +1,983 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.session;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.PendingIntent;
+import android.media.MediaMetadata;
+import android.media.Rating;
+import android.media.session.MediaController.PlaybackInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.view.KeyEvent;
+
+import java.util.List;
+
+/**
+ * Handles incoming commands from {@link MediaController}.
+ * @hide
+ */
+@SystemApi
+public final class ControllerLink implements Parcelable {
+ public static final Parcelable.Creator<ControllerLink> CREATOR =
+ new Parcelable.Creator<ControllerLink>() {
+ @Override
+ public ControllerLink createFromParcel(Parcel in) {
+ return new ControllerLink(in.readStrongBinder());
+ }
+
+ @Override
+ public ControllerLink[] newArray(int size) {
+ return new ControllerLink[size];
+ }
+ };
+
+ final ControllerStub mControllerStub;
+ final ISessionController mISessionController;
+
+ /**
+ * Constructor for stub (Callee)
+ */
+ public ControllerLink(@NonNull ControllerStub controllerStub) {
+ mControllerStub = controllerStub;
+ mISessionController = new StubProxy();
+ }
+
+ /**
+ * Constructor for interface (Caller)
+ */
+ public ControllerLink(IBinder binder) {
+ mControllerStub = null;
+ mISessionController = ISessionController.Stub.asInterface(binder);
+ }
+
+ /**
+ * Tell system that a controller sends a command.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param command the name of the command
+ * @param args the arguments included with the command
+ * @param cb the result receiver for getting the result of the command
+ */
+ void sendCommand(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ @NonNull String command, @Nullable Bundle args, @Nullable ResultReceiver cb) {
+ try {
+ mISessionController.sendCommand(packageName, caller, command, args, cb);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller sends a media button event.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param asSystemService whether this event should be considered as from system service
+ * @param mediaButton the media button key event
+ */
+ boolean sendMediaButton(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, boolean asSystemService,
+ @NonNull KeyEvent mediaButton) {
+ try {
+ return mISessionController.sendMediaButton(packageName, caller, asSystemService,
+ mediaButton);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Registers a controller callback link to the system.
+ *
+ * @param packageName the package name of the controller
+ * @param cb the controller callback link to register
+ */
+ void registerCallback(@NonNull String packageName, @NonNull ControllerCallbackLink cb) {
+ try {
+ mISessionController.registerCallback(packageName, cb);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Unregisters a controller callback link from the system.
+ *
+ * @param cb the controller callback link to register
+ */
+ void unregisterCallback(@NonNull ControllerCallbackLink cb) {
+ try {
+ mISessionController.unregisterCallback(cb);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the package name of the connected session.
+ */
+ @NonNull
+ String getPackageName() {
+ try {
+ return mISessionController.getPackageName();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the tag of the connected session.
+ */
+ @NonNull
+ String getTag() {
+ try {
+ return mISessionController.getTag();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the {@link PendingIntent} for launching UI of the connected session.
+ */
+ @Nullable
+ PendingIntent getLaunchPendingIntent() {
+ try {
+ return mISessionController.getLaunchPendingIntent();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the flags of the connected session.
+ */
+ long getFlags() {
+ try {
+ return mISessionController.getFlags();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the volume attributes of the connected session.
+ */
+ @NonNull
+ PlaybackInfo getVolumeAttributes() {
+ try {
+ return mISessionController.getVolumeAttributes();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests adjusting the volume.
+ *
+ * @param packageName the package name of the controller
+ * @param opPackageName the op package name of this request
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param asSystemService whether this event should be considered as from system service
+ * @param direction the direction to adjust the volume in
+ * @param flags the flags with this volume change request
+ */
+ void adjustVolume(@NonNull String packageName, @NonNull String opPackageName,
+ @NonNull ControllerCallbackLink caller, boolean asSystemService, int direction,
+ int flags) {
+ try {
+ mISessionController.adjustVolume(packageName, opPackageName, caller, asSystemService,
+ direction, flags);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests setting the volume.
+ *
+ * @param packageName the package name of the controller
+ * @param opPackageName the op package name of this request
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param flags the flags with this volume change request
+ */
+ void setVolumeTo(@NonNull String packageName, @NonNull String opPackageName,
+ @NonNull ControllerCallbackLink caller, int value, int flags) {
+ try {
+ mISessionController.setVolumeTo(packageName, opPackageName, caller, value, flags);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests preparing media.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ */
+ void prepare(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ try {
+ mISessionController.prepare(packageName, caller);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests preparing media from given media ID.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param mediaId the ID of the media
+ * @param extras the extras included with this request.
+ */
+ void prepareFromMediaId(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, @NonNull String mediaId,
+ @Nullable Bundle extras) {
+ try {
+ mISessionController.prepareFromMediaId(packageName, caller, mediaId, extras);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests preparing media from given search query.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param query the search query
+ * @param extras the extras included with this request.
+ */
+ void prepareFromSearch(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, @NonNull String query,
+ @Nullable Bundle extras) {
+ try {
+ mISessionController.prepareFromSearch(packageName, caller, query, extras);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests preparing media from given uri.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param uri the uri of the media
+ * @param extras the extras included with this request.
+ */
+ void prepareFromUri(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ @NonNull Uri uri, @Nullable Bundle extras) {
+ try {
+ mISessionController.prepareFromUri(packageName, caller, uri, extras);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests playing media.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ */
+ void play(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ try {
+ mISessionController.play(packageName, caller);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests playing media from given media ID.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param mediaId the ID of the media
+ * @param extras the extras included with this request.
+ */
+ void playFromMediaId(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ @NonNull String mediaId, @Nullable Bundle extras) {
+ try {
+ mISessionController.playFromMediaId(packageName, caller, mediaId, extras);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests playing media from given search query.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param query the search query
+ * @param extras the extras included with this request.
+ */
+ void playFromSearch(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ @NonNull String query, @Nullable Bundle extras) {
+ try {
+ mISessionController.playFromSearch(packageName, caller, query, extras);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests playing media from given uri.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param uri the uri of the media
+ * @param extras the extras included with this request.
+ */
+ void playFromUri(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ @NonNull Uri uri, @Nullable Bundle extras) {
+ try {
+ mISessionController.playFromUri(packageName, caller, uri, extras);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests skipping to the queue item with given ID.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param id the queue id of the item
+ */
+ void skipToQueueItem(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ long id) {
+ try {
+ mISessionController.skipToQueueItem(packageName, caller, id);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests pausing media.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ */
+ void pause(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ try {
+ mISessionController.pause(packageName, caller);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests stopping media.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ */
+ void stop(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ try {
+ mISessionController.stop(packageName, caller);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests skipping to the next queue item.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ */
+ void next(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ try {
+ mISessionController.next(packageName, caller);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests skipping to the previous queue item.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ */
+ void previous(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ try {
+ mISessionController.previous(packageName, caller);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests fast-forwarding.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ */
+ void fastForward(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ try {
+ mISessionController.fastForward(packageName, caller);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests rewinding.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ */
+ void rewind(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ try {
+ mISessionController.rewind(packageName, caller);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests seeking to the specific position.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param pos the position to move to, in milliseconds
+ */
+ void seekTo(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ long pos) {
+ try {
+ mISessionController.seekTo(packageName, caller, pos);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller requests rating of the current media.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param rating the rating of the current media
+ */
+ void rate(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ @NonNull Rating rating) {
+ try {
+ mISessionController.rate(packageName, caller, rating);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that a controller sends a custom action.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param action the name of the action
+ * @param args the arguments included with this action
+ */
+ void sendCustomAction(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, @NonNull String action, @Nullable Bundle args) {
+ try {
+ mISessionController.sendCustomAction(packageName, caller, action, args);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the current metadata of the connected session.
+ */
+ @Nullable
+ public MediaMetadata getMetadata() {
+ try {
+ return mISessionController.getMetadata();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the current playback state of the connected session.
+ */
+ @Nullable
+ public PlaybackState getPlaybackState() {
+ try {
+ return mISessionController.getPlaybackState();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the current queue of the connected session.
+ */
+ @Nullable
+ public List<MediaSession.QueueItem> getQueue() {
+ try {
+ return mISessionController.getQueue();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the current queue title of the connected session.
+ */
+ @Nullable
+ public CharSequence getQueueTitle() {
+ try {
+ return mISessionController.getQueueTitle();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the current extras of the connected session.
+ */
+ @Nullable
+ public Bundle getExtras() {
+ try {
+ return mISessionController.getExtras();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the current rating type of the connected session.
+ */
+ public int getRatingType() {
+ try {
+ return mISessionController.getRatingType();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Gets the binder */
+ @NonNull
+ public IBinder getBinder() {
+ return mISessionController.asBinder();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeStrongBinder(mISessionController.asBinder());
+ }
+
+ /**
+ * Class for Stub implementation
+ */
+ public abstract static class ControllerStub {
+ /** Stub method for ISessionController.sendCommand */
+ public void sendCommand(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ @NonNull String command, @Nullable Bundle args, @Nullable ResultReceiver cb) {
+ }
+
+ /** Stub method for ISessionController.sendMediaButton */
+ public boolean sendMediaButton(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, boolean asSystemService,
+ @NonNull KeyEvent mediaButton) {
+ return false;
+ }
+
+ /** Stub method for ISessionController.registerCallback */
+ public void registerCallback(@NonNull String packageName,
+ @NonNull ControllerCallbackLink cb) {
+ }
+
+ /** Stub method for ISessionController.unregisterCallback */
+ public void unregisterCallback(@NonNull ControllerCallbackLink cb) {
+ }
+
+ /** Stub method for ISessionController.getPackageName */
+ @NonNull
+ public String getPackageName() {
+ return null;
+ }
+
+ /** Stub method for ISessionController.getTag */
+ @NonNull
+ public String getTag() {
+ return null;
+ }
+
+ /** Stub method for ISessionController.getLaunchPendingIntent */
+ @Nullable
+ public PendingIntent getLaunchPendingIntent() {
+ return null;
+ }
+
+ /** Stub method for ISessionController.getFlags */
+ public long getFlags() {
+ return 0;
+ }
+
+ /** Stub method for ISessionController.getVolumeAttributes */
+ @NonNull
+ public PlaybackInfo getVolumeAttributes() {
+ return null;
+ }
+
+ /** Stub method for ISessionController.adjustVolume */
+ public void adjustVolume(@NonNull String packageName, @NonNull String opPackageName,
+ @NonNull ControllerCallbackLink caller, boolean asSystemService, int direction,
+ int flags) {
+ }
+
+ /** Stub method for ISessionController.setVolumeTo */
+ public void setVolumeTo(@NonNull String packageName, @NonNull String opPackageName,
+ @NonNull ControllerCallbackLink caller, int value, int flags) {
+ }
+
+ /** Stub method for ISessionController.prepare */
+ public void prepare(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ }
+
+ /** Stub method for ISessionController.prepareFromMediaId */
+ public void prepareFromMediaId(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, @NonNull String mediaId,
+ @Nullable Bundle extras) {
+ }
+
+ /** Stub method for ISessionController.prepareFromSearch */
+ public void prepareFromSearch(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, @NonNull String query,
+ @Nullable Bundle extras) {
+ }
+
+ /** Stub method for ISessionController.prepareFromUri */
+ public void prepareFromUri(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, @NonNull Uri uri, @Nullable Bundle extras) {
+ }
+
+ /** Stub method for ISessionController.play */
+ public void play(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ }
+
+ /** Stub method for ISessionController.playFromMediaId */
+ public void playFromMediaId(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, @NonNull String mediaId,
+ @Nullable Bundle extras) {
+ }
+
+ /** Stub method for ISessionController.playFromSearch */
+ public void playFromSearch(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, @NonNull String query,
+ @Nullable Bundle extras) {
+ }
+
+ /** Stub method for ISessionController.playFromUri */
+ public void playFromUri(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ @NonNull Uri uri, @Nullable Bundle extras) {
+ }
+
+ /** Stub method for ISessionController.skipToQueueItem */
+ public void skipToQueueItem(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, long id) {
+ }
+
+ /** Stub method for ISessionController.pause */
+ public void pause(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ }
+
+ /** Stub method for ISessionController.stop */
+ public void stop(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ }
+
+ /** Stub method for ISessionController.next */
+ public void next(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ }
+
+ /** Stub method for ISessionController.previous */
+ public void previous(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ }
+
+ /** Stub method for ISessionController.fastForward */
+ public void fastForward(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller) {
+ }
+
+ /** Stub method for ISessionController.rewind */
+ public void rewind(@NonNull String packageName, @NonNull ControllerCallbackLink caller) {
+ }
+
+ /** Stub method for ISessionController.seekTo */
+ public void seekTo(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ long pos) {
+ }
+
+ /** Stub method for ISessionController.rate */
+ public void rate(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ @NonNull Rating rating) {
+ }
+
+ /** Stub method for ISessionController.sendCustomAction */
+ public void sendCustomAction(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, @NonNull String action,
+ @Nullable Bundle args) {
+ }
+
+ /** Stub method for ISessionController.getMetadata */
+ @Nullable
+ public MediaMetadata getMetadata() {
+ return null;
+ }
+
+ /** Stub method for ISessionController.getPlaybackState */
+ @Nullable
+ public PlaybackState getPlaybackState() {
+ return null;
+ }
+
+ /** Stub method for ISessionController.getQueue */
+ @Nullable
+ public List<MediaSession.QueueItem> getQueue() {
+ return null;
+ }
+
+ /** Stub method for ISessionController.getQueueTitle */
+ @Nullable
+ public CharSequence getQueueTitle() {
+ return null;
+ }
+
+ /** Stub method for ISessionController.getExtras */
+ @Nullable
+ public Bundle getExtras() {
+ return null;
+ }
+
+ /** Stub method for ISessionController.getRatingType */
+ public int getRatingType() {
+ return Rating.RATING_NONE;
+ }
+ }
+
+ private class StubProxy extends ISessionController.Stub {
+ @Override
+ public void sendCommand(String packageName, ControllerCallbackLink caller,
+ String command, Bundle args, ResultReceiver cb) {
+ mControllerStub.sendCommand(packageName, caller, command, args, cb);
+ }
+
+ @Override
+ public boolean sendMediaButton(String packageName, ControllerCallbackLink caller,
+ boolean asSystemService, KeyEvent mediaButton) {
+ return mControllerStub.sendMediaButton(packageName, caller, asSystemService,
+ mediaButton);
+ }
+
+ @Override
+ public void registerCallback(String packageName, ControllerCallbackLink cb) {
+ mControllerStub.registerCallback(packageName, cb);
+ }
+
+ @Override
+ public void unregisterCallback(ControllerCallbackLink cb) {
+ mControllerStub.unregisterCallback(cb);
+ }
+
+ @Override
+ public String getPackageName() {
+ return mControllerStub.getPackageName();
+ }
+
+ @Override
+ public String getTag() {
+ return mControllerStub.getTag();
+ }
+
+ @Override
+ public PendingIntent getLaunchPendingIntent() {
+ return mControllerStub.getLaunchPendingIntent();
+ }
+
+ @Override
+ public long getFlags() {
+ return mControllerStub.getFlags();
+ }
+
+ @Override
+ public PlaybackInfo getVolumeAttributes() {
+ return mControllerStub.getVolumeAttributes();
+ }
+
+ @Override
+ public void adjustVolume(String packageName, String opPackageName,
+ ControllerCallbackLink caller, boolean asSystemService, int direction,
+ int flags) {
+ mControllerStub.adjustVolume(packageName, opPackageName, caller, asSystemService,
+ direction, flags);
+ }
+
+ @Override
+ public void setVolumeTo(String packageName, String opPackageName,
+ ControllerCallbackLink caller, int value, int flags) {
+ mControllerStub.setVolumeTo(packageName, opPackageName, caller, value, flags);
+ }
+
+ @Override
+ public void prepare(String packageName, ControllerCallbackLink caller) {
+ mControllerStub.prepare(packageName, caller);
+ }
+
+ @Override
+ public void prepareFromMediaId(String packageName, ControllerCallbackLink caller,
+ String mediaId, Bundle extras) {
+ mControllerStub.prepareFromMediaId(packageName, caller, mediaId, extras);
+ }
+
+ @Override
+ public void prepareFromSearch(String packageName, ControllerCallbackLink caller,
+ String query, Bundle extras) {
+ mControllerStub.prepareFromSearch(packageName, caller, query, extras);
+ }
+
+ @Override
+ public void prepareFromUri(String packageName, ControllerCallbackLink caller,
+ Uri uri, Bundle extras) {
+ mControllerStub.prepareFromUri(packageName, caller, uri, extras);
+ }
+
+ @Override
+ public void play(String packageName, ControllerCallbackLink caller) {
+ mControllerStub.play(packageName, caller);
+ }
+
+ @Override
+ public void playFromMediaId(String packageName, ControllerCallbackLink caller,
+ String mediaId, Bundle extras) {
+ mControllerStub.playFromMediaId(packageName, caller, mediaId, extras);
+ }
+
+ @Override
+ public void playFromSearch(String packageName, ControllerCallbackLink caller,
+ String query, Bundle extras) {
+ mControllerStub.playFromSearch(packageName, caller, query, extras);
+ }
+
+ @Override
+ public void playFromUri(String packageName, ControllerCallbackLink caller,
+ Uri uri, Bundle extras) {
+ mControllerStub.playFromUri(packageName, caller, uri, extras);
+ }
+
+ @Override
+ public void skipToQueueItem(String packageName, ControllerCallbackLink caller, long id) {
+ mControllerStub.skipToQueueItem(packageName, caller, id);
+ }
+
+ @Override
+ public void pause(String packageName, ControllerCallbackLink caller) {
+ mControllerStub.pause(packageName, caller);
+ }
+
+ @Override
+ public void stop(String packageName, ControllerCallbackLink caller) {
+ mControllerStub.stop(packageName, caller);
+ }
+
+ @Override
+ public void next(String packageName, ControllerCallbackLink caller) {
+ mControllerStub.next(packageName, caller);
+ }
+
+ @Override
+ public void previous(String packageName, ControllerCallbackLink caller) {
+ mControllerStub.previous(packageName, caller);
+ }
+
+ @Override
+ public void fastForward(String packageName, ControllerCallbackLink caller) {
+ mControllerStub.fastForward(packageName, caller);
+ }
+
+ @Override
+ public void rewind(String packageName, ControllerCallbackLink caller) {
+ mControllerStub.rewind(packageName, caller);
+ }
+
+ @Override
+ public void seekTo(String packageName, ControllerCallbackLink caller, long pos) {
+ mControllerStub.seekTo(packageName, caller, pos);
+ }
+
+ @Override
+ public void rate(String packageName, ControllerCallbackLink caller, Rating rating) {
+ mControllerStub.rate(packageName, caller, rating);
+ }
+
+ @Override
+ public void sendCustomAction(String packageName, ControllerCallbackLink caller,
+ String action, Bundle args) {
+ mControllerStub.sendCustomAction(packageName, caller, action, args);
+ }
+
+ @Override
+ public MediaMetadata getMetadata() {
+ return mControllerStub.getMetadata();
+ }
+
+ @Override
+ public PlaybackState getPlaybackState() {
+ return mControllerStub.getPlaybackState();
+ }
+
+ @Override
+ public List<MediaSession.QueueItem> getQueue() {
+ return mControllerStub.getQueue();
+ }
+
+ @Override
+ public CharSequence getQueueTitle() {
+ return mControllerStub.getQueueTitle();
+ }
+
+ @Override
+ public Bundle getExtras() {
+ return mControllerStub.getExtras();
+ }
+
+ @Override
+ public int getRatingType() {
+ return mControllerStub.getRatingType();
+ }
+ }
+}
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index 1524ad9..9b4e2bc 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -18,7 +18,7 @@
import android.app.PendingIntent;
import android.media.AudioAttributes;
import android.media.MediaMetadata;
-import android.media.session.ISessionController;
+import android.media.session.ControllerLink;
import android.media.session.PlaybackState;
import android.media.session.MediaSession;
import android.os.Bundle;
@@ -30,12 +30,12 @@
*/
interface ISession {
void sendEvent(String event, in Bundle data);
- ISessionController getController();
+ ControllerLink getController();
void setFlags(int flags);
void setActive(boolean active);
void setMediaButtonReceiver(in PendingIntent mbr);
void setLaunchPendingIntent(in PendingIntent pi);
- void destroy();
+ void destroySession();
// These commands are for the TransportPerformer
void setMetadata(in MediaMetadata metadata, long duration, String metadataDescription);
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index 2ba09fd..787cb77 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -39,9 +39,8 @@
String command, in Bundle args, in ResultReceiver cb);
boolean sendMediaButton(String packageName, in ControllerCallbackLink caller,
boolean asSystemService, in KeyEvent mediaButton);
- void registerCallbackListener(String packageName, in ControllerCallbackLink cb);
- void unregisterCallbackListener(in ControllerCallbackLink cb);
- boolean isTransportControlEnabled();
+ void registerCallback(String packageName, in ControllerCallbackLink cb);
+ void unregisterCallback(in ControllerCallbackLink cb);
String getPackageName();
String getTag();
PendingIntent getLaunchPendingIntent();
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 46516e0..ed16250 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -18,13 +18,14 @@
import android.content.ComponentName;
import android.media.IRemoteVolumeController;
import android.media.Session2Token;
+import android.media.session.ControllerLink;
import android.media.session.IActiveSessionsListener;
import android.media.session.ICallback;
import android.media.session.IOnMediaKeyListener;
import android.media.session.IOnVolumeKeyLongPressListener;
-import android.media.session.ISession;
import android.media.session.ISession2TokensListener;
import android.media.session.SessionCallbackLink;
+import android.media.session.SessionLink;
import android.os.Bundle;
import android.view.KeyEvent;
@@ -33,9 +34,10 @@
* @hide
*/
interface ISessionManager {
- ISession createSession(String packageName, in SessionCallbackLink cb, String tag, int userId);
+ SessionLink createSession(String packageName, in SessionCallbackLink sessionCb, String tag,
+ int userId);
void notifySession2Created(in Session2Token sessionToken);
- List<IBinder> getSessions(in ComponentName compName, int userId);
+ List<ControllerLink> getSessions(in ComponentName compName, int userId);
List<Session2Token> getSession2Tokens(int userId);
void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
boolean needWakeLock);
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index a1b8170..9d537c8 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -34,7 +34,6 @@
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.RemoteException;
import android.os.ResultReceiver;
import android.text.TextUtils;
import android.util.Log;
@@ -68,12 +67,11 @@
private static final int MSG_UPDATE_EXTRAS = 7;
private static final int MSG_DESTROYED = 8;
- private final ISessionController mSessionBinder;
+ private final ControllerLink mSessionBinder;
private final MediaSession.Token mToken;
private final Context mContext;
- private final ControllerCallbackLink mCbStub =
- new ControllerCallbackLink(new CallbackStub(this));
+ private final ControllerCallbackLink mCbStub;
private final ArrayList<MessageHandler> mCallbacks = new ArrayList<MessageHandler>();
private final Object mLock = new Object();
@@ -84,12 +82,11 @@
private final TransportControls mTransportControls;
/**
- * Call for creating a MediaController directly from a binder. Should only
+ * Call for creating a MediaController directly from a controller link. Should only
* be used by framework code.
- *
* @hide
*/
- public MediaController(Context context, ISessionController sessionBinder) {
+ public MediaController(Context context, ControllerLink sessionBinder) {
if (sessionBinder == null) {
throw new IllegalArgumentException("Session token cannot be null");
}
@@ -100,6 +97,17 @@
mTransportControls = new TransportControls();
mToken = new MediaSession.Token(sessionBinder);
mContext = context;
+ mCbStub = new ControllerCallbackLink(context, new CallbackStub(this));
+ }
+
+ /**
+ * Call for creating a MediaController directly from a binder. Should only
+ * be used by framework code.
+ * @hide
+ * TODO: remove this constructor
+ */
+ public MediaController(Context context, ISessionController sessionBinder) {
+ this(context, new ControllerLink(sessionBinder.asBinder()));
}
/**
@@ -158,7 +166,7 @@
try {
return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub,
asSystemService, keyEvent);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
// System is dead. =(
}
return false;
@@ -195,7 +203,7 @@
mSessionBinder.adjustVolume(mContext.getPackageName(),
mContext.getOpPackageName(), mCbStub, true, direction,
AudioManager.FLAG_SHOW_UI);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy", e);
}
}
@@ -209,7 +217,7 @@
// AppOpsManager usages.
mSessionBinder.adjustVolume(mContext.getPackageName(),
mContext.getOpPackageName(), mCbStub, true, 0, flags);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy", e);
}
}
@@ -224,7 +232,7 @@
public @Nullable PlaybackState getPlaybackState() {
try {
return mSessionBinder.getPlaybackState();
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling getPlaybackState.", e);
return null;
}
@@ -238,7 +246,7 @@
public @Nullable MediaMetadata getMetadata() {
try {
return mSessionBinder.getMetadata();
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling getMetadata.", e);
return null;
}
@@ -253,7 +261,7 @@
public @Nullable List<MediaSession.QueueItem> getQueue() {
try {
return mSessionBinder.getQueue();
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling getQueue.", e);
}
return null;
@@ -265,7 +273,7 @@
public @Nullable CharSequence getQueueTitle() {
try {
return mSessionBinder.getQueueTitle();
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling getQueueTitle", e);
}
return null;
@@ -277,7 +285,7 @@
public @Nullable Bundle getExtras() {
try {
return mSessionBinder.getExtras();
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling getExtras", e);
}
return null;
@@ -300,7 +308,7 @@
public int getRatingType() {
try {
return mSessionBinder.getRatingType();
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling getRatingType.", e);
return Rating.RATING_NONE;
}
@@ -314,7 +322,7 @@
public @MediaSession.SessionFlags long getFlags() {
try {
return mSessionBinder.getFlags();
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling getFlags.", e);
}
return 0;
@@ -328,7 +336,7 @@
public @Nullable PlaybackInfo getPlaybackInfo() {
try {
return mSessionBinder.getVolumeAttributes();
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling getAudioInfo.", e);
}
return null;
@@ -343,7 +351,7 @@
public @Nullable PendingIntent getSessionActivity() {
try {
return mSessionBinder.getLaunchPendingIntent();
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling getPendingIntent.", e);
}
return null;
@@ -376,7 +384,7 @@
// AppOpsManager usages.
mSessionBinder.setVolumeTo(mContext.getPackageName(), mContext.getOpPackageName(),
mCbStub, value, flags);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling setVolumeTo.", e);
}
}
@@ -401,7 +409,7 @@
// AppOpsManager usages.
mSessionBinder.adjustVolume(mContext.getPackageName(), mContext.getOpPackageName(),
mCbStub, false, direction, flags);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
}
}
@@ -467,7 +475,7 @@
}
try {
mSessionBinder.sendCommand(mContext.getPackageName(), mCbStub, command, args, cb);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.d(TAG, "Dead object in sendCommand.", e);
}
}
@@ -481,7 +489,7 @@
if (mPackageName == null) {
try {
mPackageName = mSessionBinder.getPackageName();
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.d(TAG, "Dead object in getPackageName.", e);
}
}
@@ -498,7 +506,7 @@
if (mTag == null) {
try {
mTag = mSessionBinder.getTag();
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.d(TAG, "Dead object in getTag.", e);
}
}
@@ -508,7 +516,7 @@
/*
* @hide
*/
- ISessionController getSessionBinder() {
+ ControllerLink getSessionBinder() {
return mSessionBinder;
}
@@ -518,7 +526,7 @@
@UnsupportedAppUsage
public boolean controlsSameSession(MediaController other) {
if (other == null) return false;
- return mSessionBinder.asBinder() == other.getSessionBinder().asBinder();
+ return mSessionBinder.getBinder() == other.getSessionBinder().getBinder();
}
private void addCallbackLocked(Callback cb, Handler handler) {
@@ -532,9 +540,9 @@
if (!mCbRegistered) {
try {
- mSessionBinder.registerCallbackListener(mContext.getPackageName(), mCbStub);
+ mSessionBinder.registerCallback(mContext.getPackageName(), mCbStub);
mCbRegistered = true;
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.e(TAG, "Dead object in registerCallback", e);
}
}
@@ -552,8 +560,8 @@
}
if (mCbRegistered && mCallbacks.size() == 0) {
try {
- mSessionBinder.unregisterCallbackListener(mCbStub);
- } catch (RemoteException e) {
+ mSessionBinder.unregisterCallback(mCbStub);
+ } catch (RuntimeException e) {
Log.e(TAG, "Dead object in removeCallbackLocked");
}
mCbRegistered = false;
@@ -680,7 +688,7 @@
public void prepare() {
try {
mSessionBinder.prepare(mContext.getPackageName(), mCbStub);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling prepare.", e);
}
}
@@ -705,7 +713,7 @@
try {
mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
extras);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
}
}
@@ -732,7 +740,7 @@
try {
mSessionBinder.prepareFromSearch(mContext.getPackageName(), mCbStub, query,
extras);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
}
}
@@ -756,7 +764,7 @@
}
try {
mSessionBinder.prepareFromUri(mContext.getPackageName(), mCbStub, uri, extras);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
}
}
@@ -767,7 +775,7 @@
public void play() {
try {
mSessionBinder.play(mContext.getPackageName(), mCbStub);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling play.", e);
}
}
@@ -787,7 +795,7 @@
try {
mSessionBinder.playFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
extras);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
}
}
@@ -809,7 +817,7 @@
}
try {
mSessionBinder.playFromSearch(mContext.getPackageName(), mCbStub, query, extras);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling play(" + query + ").", e);
}
}
@@ -828,7 +836,7 @@
}
try {
mSessionBinder.playFromUri(mContext.getPackageName(), mCbStub, uri, extras);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling play(" + uri + ").", e);
}
}
@@ -840,7 +848,7 @@
public void skipToQueueItem(long id) {
try {
mSessionBinder.skipToQueueItem(mContext.getPackageName(), mCbStub, id);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
}
}
@@ -852,7 +860,7 @@
public void pause() {
try {
mSessionBinder.pause(mContext.getPackageName(), mCbStub);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling pause.", e);
}
}
@@ -864,7 +872,7 @@
public void stop() {
try {
mSessionBinder.stop(mContext.getPackageName(), mCbStub);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling stop.", e);
}
}
@@ -877,7 +885,7 @@
public void seekTo(long pos) {
try {
mSessionBinder.seekTo(mContext.getPackageName(), mCbStub, pos);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling seekTo.", e);
}
}
@@ -889,7 +897,7 @@
public void fastForward() {
try {
mSessionBinder.fastForward(mContext.getPackageName(), mCbStub);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling fastForward.", e);
}
}
@@ -900,7 +908,7 @@
public void skipToNext() {
try {
mSessionBinder.next(mContext.getPackageName(), mCbStub);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling next.", e);
}
}
@@ -912,7 +920,7 @@
public void rewind() {
try {
mSessionBinder.rewind(mContext.getPackageName(), mCbStub);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling rewind.", e);
}
}
@@ -923,7 +931,7 @@
public void skipToPrevious() {
try {
mSessionBinder.previous(mContext.getPackageName(), mCbStub);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling previous.", e);
}
}
@@ -938,7 +946,7 @@
public void setRating(Rating rating) {
try {
mSessionBinder.rate(mContext.getPackageName(), mCbStub, rating);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error calling rate.", e);
}
}
@@ -973,7 +981,7 @@
}
try {
mSessionBinder.sendCustomAction(mContext.getPackageName(), mCbStub, action, args);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.d(TAG, "Dead object in sendCustomAction.", e);
}
}
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index e07cf15..881e6ee 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -37,9 +37,7 @@
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.RemoteException;
import android.os.ResultReceiver;
-import android.os.UserHandle;
import android.service.media.MediaBrowserService;
import android.text.TextUtils;
import android.util.Log;
@@ -128,7 +126,7 @@
private final MediaSession.Token mSessionToken;
private final MediaController mController;
- private final ISession mBinder;
+ private final SessionLink mSessionLink;
private final SessionCallbackLink mCbStub;
// Do not change the name of mCallback. Support lib accesses this by using reflection.
@@ -149,21 +147,6 @@
* @param tag A short name for debugging purposes.
*/
public MediaSession(@NonNull Context context, @NonNull String tag) {
- this(context, tag, UserHandle.myUserId());
- }
-
- /**
- * Creates a new session as the specified user. To create a session as a
- * user other than your own you must hold the
- * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
- * permission.
- *
- * @param context The context to use to create the session.
- * @param tag A short name for debugging purposes.
- * @param userId The user id to create the session as.
- * @hide
- */
- public MediaSession(@NonNull Context context, @NonNull String tag, int userId) {
if (context == null) {
throw new IllegalArgumentException("context cannot be null.");
}
@@ -172,14 +155,14 @@
}
mMaxBitmapSize = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.config_mediaMetadataBitmapMaxSize);
- mCbStub = new SessionCallbackLink(new CallbackStub(this));
+ mCbStub = new SessionCallbackLink(context, new CallbackStub(this));
MediaSessionManager manager = (MediaSessionManager) context
.getSystemService(Context.MEDIA_SESSION_SERVICE);
try {
- mBinder = manager.createSession(mCbStub, tag, userId);
- mSessionToken = new Token(mBinder.getController());
+ mSessionLink = manager.createSession(mCbStub, tag);
+ mSessionToken = new Token(mSessionLink.getController());
mController = new MediaController(context, mSessionToken);
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
throw new RuntimeException("Remote error creating session.", e);
}
}
@@ -236,8 +219,8 @@
*/
public void setSessionActivity(@Nullable PendingIntent pi) {
try {
- mBinder.setLaunchPendingIntent(pi);
- } catch (RemoteException e) {
+ mSessionLink.setLaunchPendingIntent(pi);
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Failure in setLaunchPendingIntent.", e);
}
}
@@ -252,8 +235,8 @@
*/
public void setMediaButtonReceiver(@Nullable PendingIntent mbr) {
try {
- mBinder.setMediaButtonReceiver(mbr);
- } catch (RemoteException e) {
+ mSessionLink.setMediaButtonReceiver(mbr);
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e);
}
}
@@ -265,8 +248,8 @@
*/
public void setFlags(@SessionFlags int flags) {
try {
- mBinder.setFlags(flags);
- } catch (RemoteException e) {
+ mSessionLink.setFlags(flags);
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Failure in setFlags.", e);
}
}
@@ -287,8 +270,8 @@
throw new IllegalArgumentException("Attributes cannot be null for local playback.");
}
try {
- mBinder.setPlaybackToLocal(attributes);
- } catch (RemoteException e) {
+ mSessionLink.setPlaybackToLocal(attributes);
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Failure in setPlaybackToLocal.", e);
}
}
@@ -319,10 +302,10 @@
});
try {
- mBinder.setPlaybackToRemote(volumeProvider.getVolumeControl(),
+ mSessionLink.setPlaybackToRemote(volumeProvider.getVolumeControl(),
volumeProvider.getMaxVolume());
- mBinder.setCurrentVolume(volumeProvider.getCurrentVolume());
- } catch (RemoteException e) {
+ mSessionLink.setCurrentVolume(volumeProvider.getCurrentVolume());
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Failure in setPlaybackToRemote.", e);
}
}
@@ -340,9 +323,9 @@
return;
}
try {
- mBinder.setActive(active);
+ mSessionLink.setActive(active);
mActive = active;
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Failure in setActive.", e);
}
}
@@ -369,8 +352,8 @@
throw new IllegalArgumentException("event cannot be null or empty");
}
try {
- mBinder.sendEvent(event, extras);
- } catch (RemoteException e) {
+ mSessionLink.sendEvent(event, extras);
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error sending event", e);
}
}
@@ -382,8 +365,8 @@
*/
public void release() {
try {
- mBinder.destroy();
- } catch (RemoteException e) {
+ mSessionLink.destroySession();
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Error releasing session: ", e);
}
}
@@ -418,8 +401,8 @@
public void setPlaybackState(@Nullable PlaybackState state) {
mPlaybackState = state;
try {
- mBinder.setPlaybackState(state);
- } catch (RemoteException e) {
+ mSessionLink.setPlaybackState(state);
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Dead object in setPlaybackState.", e);
}
}
@@ -447,8 +430,8 @@
String metadataDescription = "size=" + fields + ", description=" + description;
try {
- mBinder.setMetadata(metadata, duration, metadataDescription);
- } catch (RemoteException e) {
+ mSessionLink.setMetadata(metadata, duration, metadataDescription);
+ } catch (RuntimeException e) {
Log.wtf(TAG, "Dead object in setPlaybackState.", e);
}
}
@@ -466,8 +449,8 @@
*/
public void setQueue(@Nullable List<QueueItem> queue) {
try {
- mBinder.setQueue(queue);
- } catch (RemoteException e) {
+ mSessionLink.setQueue(queue);
+ } catch (RuntimeException e) {
Log.wtf("Dead object in setQueue.", e);
}
}
@@ -481,8 +464,8 @@
*/
public void setQueueTitle(@Nullable CharSequence title) {
try {
- mBinder.setQueueTitle(title);
- } catch (RemoteException e) {
+ mSessionLink.setQueueTitle(title);
+ } catch (RuntimeException e) {
Log.wtf("Dead object in setQueueTitle.", e);
}
}
@@ -502,8 +485,8 @@
*/
public void setRatingType(@Rating.Style int type) {
try {
- mBinder.setRatingType(type);
- } catch (RemoteException e) {
+ mSessionLink.setRatingType(type);
+ } catch (RuntimeException e) {
Log.e(TAG, "Error in setRatingType.", e);
}
}
@@ -517,8 +500,8 @@
*/
public void setExtras(@Nullable Bundle extras) {
try {
- mBinder.setExtras(extras);
- } catch (RemoteException e) {
+ mSessionLink.setExtras(extras);
+ } catch (RuntimeException e) {
Log.wtf("Dead object in setExtras.", e);
}
}
@@ -553,8 +536,8 @@
}
}
try {
- mBinder.setCurrentVolume(provider.getCurrentVolume());
- } catch (RemoteException e) {
+ mSessionLink.setCurrentVolume(provider.getCurrentVolume());
+ } catch (RuntimeException e) {
Log.e(TAG, "Error in notifyVolumeChanged", e);
}
}
@@ -709,12 +692,12 @@
*/
public static final class Token implements Parcelable {
- private ISessionController mBinder;
+ private ControllerLink mBinder;
/**
* @hide
*/
- public Token(ISessionController binder) {
+ public Token(ControllerLink binder) {
mBinder = binder;
}
@@ -725,14 +708,14 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeStrongBinder(mBinder.asBinder());
+ dest.writeParcelable(mBinder, flags);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((mBinder == null) ? 0 : mBinder.asBinder().hashCode());
+ result = prime * result + ((mBinder == null) ? 0 : mBinder.getBinder().hashCode());
return result;
}
@@ -748,20 +731,22 @@
if (mBinder == null) {
if (other.mBinder != null)
return false;
- } else if (!mBinder.asBinder().equals(other.mBinder.asBinder()))
+ } else if (!mBinder.getBinder().equals(other.mBinder.getBinder())) {
return false;
+ }
return true;
}
- ISessionController getBinder() {
+ ControllerLink getBinder() {
return mBinder;
}
- public static final Parcelable.Creator<Token> CREATOR
- = new Parcelable.Creator<Token>() {
+ public static final Parcelable.Creator<Token> CREATOR =
+ new Parcelable.Creator<Token>() {
@Override
public Token createFromParcel(Parcel in) {
- return new Token(ISessionController.Stub.asInterface(in.readStrongBinder()));
+ ControllerLink link = in.readParcelable(null);
+ return new Token(link);
}
@Override
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 4596c22..77e758fc 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -104,9 +104,14 @@
* @return The binder object from the system
* @hide
*/
- public @NonNull ISession createSession(@NonNull SessionCallbackLink cbStub,
- @NonNull String tag, int userId) throws RemoteException {
- return mService.createSession(mContext.getPackageName(), cbStub, tag, userId);
+ @NonNull
+ public SessionLink createSession(@NonNull SessionCallbackLink cbStub, @NonNull String tag) {
+ try {
+ return mService.createSession(mContext.getPackageName(), cbStub, tag,
+ UserHandle.myUserId());
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
}
/**
@@ -171,11 +176,10 @@
@Nullable ComponentName notificationListener, int userId) {
ArrayList<MediaController> controllers = new ArrayList<MediaController>();
try {
- List<IBinder> binders = mService.getSessions(notificationListener, userId);
+ List<ControllerLink> binders = mService.getSessions(notificationListener, userId);
int size = binders.size();
for (int i = 0; i < size; i++) {
- MediaController controller = new MediaController(mContext, ISessionController.Stub
- .asInterface(binders.get(i)));
+ MediaController controller = new MediaController(mContext, binders.get(i));
controllers.add(controller);
}
} catch (RemoteException e) {
diff --git a/media/java/android/media/session/SessionCallbackLink.java b/media/java/android/media/session/SessionCallbackLink.java
index 7547bff..0265687b 100644
--- a/media/java/android/media/session/SessionCallbackLink.java
+++ b/media/java/android/media/session/SessionCallbackLink.java
@@ -16,31 +16,40 @@
package android.media.session;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.media.Rating;
import android.net.Uri;
+import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
/**
* Handles incoming commands to {@link MediaSession.Callback}.
- * <p>
- * This API is not generally intended for third party application developers.
+ * @hide
*/
+@SystemApi
public final class SessionCallbackLink implements Parcelable {
+ final Context mContext;
final CallbackStub mCallbackStub;
final ISessionCallback mISessionCallback;
/**
* Constructor for stub (Callee)
*/
- SessionCallbackLink(@NonNull CallbackStub callbackStub) {
+ SessionCallbackLink(@NonNull Context context, @NonNull CallbackStub callbackStub) {
+ mContext = context;
mCallbackStub = callbackStub;
mISessionCallback = new CallbackStubProxy();
}
@@ -48,9 +57,10 @@
/**
* Constructor for interface (Caller)
*/
- SessionCallbackLink(Parcel in) {
+ public SessionCallbackLink(IBinder binder) {
+ mContext = null;
mCallbackStub = null;
- mISessionCallback = ISessionCallback.Stub.asInterface(in.readStrongBinder());
+ mISessionCallback = ISessionCallback.Stub.asInterface(binder);
}
/**
@@ -64,6 +74,7 @@
* @param args the arguments included with the command
* @param cb the result receiver for getting the result of the command
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyCommand(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, @NonNull String command,
@Nullable Bundle args, @Nullable ResultReceiver cb) {
@@ -84,6 +95,7 @@
* @param sequenceNumber the sequence number of this call
* @param cb the result receiver for getting the result of the command
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyMediaButton(@NonNull String packageName, int pid, int uid,
@NonNull Intent mediaButtonIntent, int sequenceNumber,
@Nullable ResultReceiver cb) {
@@ -104,6 +116,7 @@
* @param caller the {@link ControllerCallbackLink} of the controller
* @param mediaButtonIntent the media button intent
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyMediaButtonFromController(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, @NonNull Intent mediaButtonIntent) {
try {
@@ -122,6 +135,7 @@
* @param uid the uid of the controller
* @param caller the {@link ControllerCallbackLink} of the controller
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyPrepare(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller) {
try {
@@ -141,6 +155,7 @@
* @param mediaId the ID of the media
* @param extras the extras included with this request.
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyPrepareFromMediaId(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, @NonNull String mediaId,
@Nullable Bundle extras) {
@@ -162,6 +177,7 @@
* @param query the search query
* @param extras the extras included with this request.
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyPrepareFromSearch(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, @NonNull String query,
@Nullable Bundle extras) {
@@ -182,6 +198,7 @@
* @param uri the uri of the media
* @param extras the extras included with this request.
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyPrepareFromUri(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, @NonNull Uri uri, @Nullable Bundle extras) {
try {
@@ -199,6 +216,7 @@
* @param uid the uid of the controller
* @param caller the {@link ControllerCallbackLink} of the controller
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyPlay(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller) {
try {
@@ -218,6 +236,7 @@
* @param mediaId the ID of the media
* @param extras the extras included with this request.
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyPlayFromMediaId(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, @NonNull String mediaId,
@Nullable Bundle extras) {
@@ -238,6 +257,7 @@
* @param query the search query
* @param extras the extras included with this request.
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyPlayFromSearch(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, @NonNull String query,
@Nullable Bundle extras) {
@@ -258,6 +278,7 @@
* @param uri the uri of the media
* @param extras the extras included with this request.
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyPlayFromUri(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, @NonNull Uri uri, @Nullable Bundle extras) {
try {
@@ -276,6 +297,7 @@
* @param caller the {@link ControllerCallbackLink} of the controller
* @param id the queue id of the item
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifySkipToTrack(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, long id) {
try {
@@ -293,6 +315,7 @@
* @param uid the uid of the controller
* @param caller the {@link ControllerCallbackLink} of the controller
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyPause(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller) {
try {
@@ -310,6 +333,7 @@
* @param uid the uid of the controller
* @param caller the {@link ControllerCallbackLink} of the controller
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyStop(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller) {
try {
@@ -327,6 +351,7 @@
* @param uid the uid of the controller
* @param caller the {@link ControllerCallbackLink} of the controller
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyNext(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller) {
try {
@@ -344,6 +369,7 @@
* @param uid the uid of the controller
* @param caller the {@link ControllerCallbackLink} of the controller
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyPrevious(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller) {
try {
@@ -361,6 +387,7 @@
* @param uid the uid of the controller
* @param caller the {@link ControllerCallbackLink} of the controller
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyFastForward(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller) {
try {
@@ -378,6 +405,7 @@
* @param uid the uid of the controller
* @param caller the {@link ControllerCallbackLink} of the controller
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyRewind(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller) {
try {
@@ -396,6 +424,7 @@
* @param caller the {@link ControllerCallbackLink} of the controller
* @param pos the position to move to, in milliseconds
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifySeekTo(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, long pos) {
try {
@@ -414,6 +443,7 @@
* @param caller the {@link ControllerCallbackLink} of the controller
* @param rating the rating of the current media
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyRate(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, @NonNull Rating rating) {
try {
@@ -433,6 +463,7 @@
* @param action the name of the action
* @param args the arguments included with this action
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyCustomAction(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, @NonNull String action, @Nullable Bundle args) {
try {
@@ -451,6 +482,7 @@
* @param caller the {@link ControllerCallbackLink} of the controller
* @param direction the direction of the volume change.
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifyAdjustVolume(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, int direction) {
try {
@@ -469,6 +501,7 @@
* @param caller the {@link ControllerCallbackLink} of the controller
* @param value the volume value to set
*/
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
public void notifySetVolumeTo(@NonNull String packageName, int pid, int uid,
@NonNull ControllerCallbackLink caller, int value) {
try {
@@ -498,7 +531,7 @@
new Parcelable.Creator<SessionCallbackLink>() {
@Override
public SessionCallbackLink createFromParcel(Parcel in) {
- return new SessionCallbackLink(in);
+ return new SessionCallbackLink(in.readStrongBinder());
}
@Override
@@ -636,141 +669,296 @@
@Override
public void notifyCommand(String packageName, int pid, int uid,
ControllerCallbackLink caller, String command, Bundle args, ResultReceiver cb) {
- mCallbackStub.onCommand(packageName, pid, uid, caller, command, args, cb);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onCommand(packageName, pid, uid, caller, command, args, cb);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyMediaButton(String packageName, int pid, int uid,
Intent mediaButtonIntent, int sequenceNumber, ResultReceiver cb) {
- mCallbackStub.onMediaButton(packageName, pid, uid, mediaButtonIntent, sequenceNumber,
- cb);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onMediaButton(packageName, pid, uid, mediaButtonIntent,
+ sequenceNumber, cb);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyMediaButtonFromController(String packageName, int pid, int uid,
ControllerCallbackLink caller, Intent mediaButtonIntent) {
- mCallbackStub.onMediaButtonFromController(packageName, pid, uid, caller,
- mediaButtonIntent);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onMediaButtonFromController(packageName, pid, uid, caller,
+ mediaButtonIntent);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyPrepare(String packageName, int pid, int uid,
ControllerCallbackLink caller) {
- mCallbackStub.onPrepare(packageName, pid, uid, caller);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onPrepare(packageName, pid, uid, caller);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyPrepareFromMediaId(String packageName, int pid, int uid,
ControllerCallbackLink caller, String mediaId, Bundle extras) {
- mCallbackStub.onPrepareFromMediaId(packageName, pid, uid, caller, mediaId, extras);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onPrepareFromMediaId(packageName, pid, uid, caller, mediaId, extras);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyPrepareFromSearch(String packageName, int pid, int uid,
ControllerCallbackLink caller, String query, Bundle extras) {
- mCallbackStub.onPrepareFromSearch(packageName, pid, uid, caller, query, extras);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onPrepareFromSearch(packageName, pid, uid, caller, query, extras);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyPrepareFromUri(String packageName, int pid, int uid,
ControllerCallbackLink caller, Uri uri, Bundle extras) {
- mCallbackStub.onPrepareFromUri(packageName, pid, uid, caller, uri, extras);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onPrepareFromUri(packageName, pid, uid, caller, uri, extras);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyPlay(String packageName, int pid, int uid,
ControllerCallbackLink caller) {
- mCallbackStub.onPlay(packageName, pid, uid, caller);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onPlay(packageName, pid, uid, caller);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyPlayFromMediaId(String packageName, int pid, int uid,
ControllerCallbackLink caller, String mediaId, Bundle extras) {
- mCallbackStub.onPlayFromMediaId(packageName, pid, uid, caller, mediaId, extras);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onPlayFromMediaId(packageName, pid, uid, caller, mediaId, extras);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyPlayFromSearch(String packageName, int pid, int uid,
ControllerCallbackLink caller, String query, Bundle extras) {
- mCallbackStub.onPlayFromSearch(packageName, pid, uid, caller, query, extras);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onPlayFromSearch(packageName, pid, uid, caller, query, extras);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyPlayFromUri(String packageName, int pid, int uid,
ControllerCallbackLink caller, Uri uri, Bundle extras) {
- mCallbackStub.onPlayFromUri(packageName, pid, uid, caller, uri, extras);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onPlayFromUri(packageName, pid, uid, caller, uri, extras);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifySkipToTrack(String packageName, int pid, int uid,
ControllerCallbackLink caller, long id) {
- mCallbackStub.onSkipToTrack(packageName, pid, uid, caller, id);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onSkipToTrack(packageName, pid, uid, caller, id);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyPause(String packageName, int pid, int uid,
ControllerCallbackLink caller) {
- mCallbackStub.onPause(packageName, pid, uid, caller);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onPause(packageName, pid, uid, caller);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyStop(String packageName, int pid, int uid,
ControllerCallbackLink caller) {
- mCallbackStub.onStop(packageName, pid, uid, caller);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onStop(packageName, pid, uid, caller);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyNext(String packageName, int pid, int uid,
ControllerCallbackLink caller) {
- mCallbackStub.onNext(packageName, pid, uid, caller);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onNext(packageName, pid, uid, caller);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyPrevious(String packageName, int pid, int uid,
ControllerCallbackLink caller) {
- mCallbackStub.onPrevious(packageName, pid, uid, caller);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onPrevious(packageName, pid, uid, caller);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyFastForward(String packageName, int pid, int uid,
ControllerCallbackLink caller) {
- mCallbackStub.onFastForward(packageName, pid, uid, caller);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onFastForward(packageName, pid, uid, caller);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyRewind(String packageName, int pid, int uid,
ControllerCallbackLink caller) {
- mCallbackStub.onRewind(packageName, pid, uid, caller);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onRewind(packageName, pid, uid, caller);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifySeekTo(String packageName, int pid, int uid,
ControllerCallbackLink caller, long pos) {
- mCallbackStub.onSeekTo(packageName, pid, uid, caller, pos);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onSeekTo(packageName, pid, uid, caller, pos);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyRate(String packageName, int pid, int uid, ControllerCallbackLink caller,
Rating rating) {
- mCallbackStub.onRate(packageName, pid, uid, caller, rating);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onRate(packageName, pid, uid, caller, rating);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
- @Override
public void notifyCustomAction(String packageName, int pid, int uid,
ControllerCallbackLink caller, String action, Bundle args) {
- mCallbackStub.onCustomAction(packageName, pid, uid, caller, action, args);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onCustomAction(packageName, pid, uid, caller, action, args);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyAdjustVolume(String packageName, int pid, int uid,
ControllerCallbackLink caller, int direction) {
- mCallbackStub.onAdjustVolume(packageName, pid, uid, caller, direction);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onAdjustVolume(packageName, pid, uid, caller, direction);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifySetVolumeTo(String packageName, int pid, int uid,
ControllerCallbackLink caller, int value) {
- mCallbackStub.onSetVolumeTo(packageName, pid, uid, caller, value);
+ ensureMediasControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mCallbackStub.onSetVolumeTo(packageName, pid, uid, caller, value);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void ensureMediasControlPermission() {
+ // Allow API calls from the System UI
+ if (mContext.checkCallingPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+
+ // Check if it's system server or has MEDIA_CONTENT_CONTROL.
+ // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
+ // check here.
+ if (getCallingUid() == Process.SYSTEM_UID || mContext.checkCallingPermission(
+ android.Manifest.permission.MEDIA_CONTENT_CONTROL)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ throw new SecurityException("Must hold the MEDIA_CONTENT_CONTROL permission.");
}
}
}
diff --git a/media/java/android/media/session/SessionLink.aidl b/media/java/android/media/session/SessionLink.aidl
new file mode 100644
index 0000000..c3be23e
--- /dev/null
+++ b/media/java/android/media/session/SessionLink.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.session;
+
+parcelable SessionLink;
diff --git a/media/java/android/media/session/SessionLink.java b/media/java/android/media/session/SessionLink.java
new file mode 100644
index 0000000..466077e
--- /dev/null
+++ b/media/java/android/media/session/SessionLink.java
@@ -0,0 +1,453 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.session;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.PendingIntent;
+import android.media.AudioAttributes;
+import android.media.MediaMetadata;
+import android.media.Rating;
+import android.media.VolumeProvider;
+import android.media.session.MediaSession.QueueItem;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+
+import java.util.List;
+
+/**
+ * Handles incoming commands from {@link MediaSession}.
+ * @hide
+ */
+@SystemApi
+public final class SessionLink implements Parcelable {
+ public static final Parcelable.Creator<SessionLink> CREATOR =
+ new Parcelable.Creator<SessionLink>() {
+ @Override
+ public SessionLink createFromParcel(Parcel in) {
+ return new SessionLink(in.readStrongBinder());
+ }
+
+ @Override
+ public SessionLink[] newArray(int size) {
+ return new SessionLink[size];
+ }
+ };
+
+ final SessionStub mSessionStub;
+ final ISession mISession;
+
+ /**
+ * Constructor for stub (Callee)
+ */
+ public SessionLink(@NonNull SessionStub sessionStub) {
+ mSessionStub = sessionStub;
+ mISession = new StubProxy();
+ }
+
+ /**
+ * Constructor for interface (Caller)
+ */
+ public SessionLink(IBinder binder) {
+ mSessionStub = null;
+ mISession = ISession.Stub.asInterface(binder);
+ }
+
+ /**
+ * Tell system that the session sends an event to all the connected controllers.
+ *
+ * @param event the name of the event
+ * @param extras the extras included with the event
+ */
+ void sendEvent(@NonNull String event, @Nullable Bundle extras) {
+ try {
+ mISession.sendEvent(event, extras);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Gets the controller link from the system.
+ */
+ @NonNull
+ ControllerLink getController() {
+ try {
+ return mISession.getController();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session sets the flags.
+ *
+ * @param flags the new session flags
+ */
+ void setFlags(int flags) {
+ try {
+ mISession.setFlags(flags);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session is (in)active.
+ *
+ * @param active the new activeness state
+ */
+ void setActive(boolean active) {
+ try {
+ mISession.setActive(active);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session sets the media button receiver.
+ *
+ * @param mbr the pending intent for media button receiver
+ */
+ void setMediaButtonReceiver(@Nullable PendingIntent mbr) {
+ try {
+ mISession.setMediaButtonReceiver(mbr);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session sets the pending intent for launching UI.
+ *
+ * @param pi the pending intent for launching UI
+ */
+ void setLaunchPendingIntent(@Nullable PendingIntent pi) {
+ try {
+ mISession.setLaunchPendingIntent(pi);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session is destroyed.
+ */
+ void destroySession() {
+ try {
+ mISession.destroySession();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session sets the new metadata.
+ *
+ * @param metadata the new metadata
+ * @param duration the duration of the media in milliseconds
+ * @param metadataDescription the description of the metadata
+ */
+ void setMetadata(@Nullable MediaMetadata metadata, long duration,
+ @Nullable String metadataDescription) {
+ try {
+ mISession.setMetadata(metadata, duration, metadataDescription);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session sets the new playback state.
+ *
+ * @param state the new playback state
+ */
+ void setPlaybackState(@Nullable PlaybackState state) {
+ try {
+ mISession.setPlaybackState(state);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session sets the new queue.
+ *
+ * @param queue the new queue
+ */
+ void setQueue(@Nullable List<QueueItem> queue) {
+ try {
+ mISession.setQueue(queue);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session sets the new queue title.
+ *
+ * @param title the new queue title
+ */
+ void setQueueTitle(@Nullable CharSequence title) {
+ try {
+ mISession.setQueueTitle(title);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session sets the new extras.
+ *
+ * @param extras the new extras
+ */
+ void setExtras(@Nullable Bundle extras) {
+ try {
+ mISession.setExtras(extras);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session sets the new rating type of the current media.
+ *
+ * @param type the rating type.
+ */
+ void setRatingType(@Rating.Style int type) {
+ try {
+ mISession.setRatingType(type);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session represents a local playback.
+ *
+ * @param attributes the audio attributes of the local playback.
+ */
+ void setPlaybackToLocal(@NonNull AudioAttributes attributes) {
+ try {
+ mISession.setPlaybackToLocal(attributes);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session represents a remote playback.
+ *
+ * @param control the volume control type
+ * @param max the max volume
+ */
+ void setPlaybackToRemote(@VolumeProvider.ControlType int control, int max) {
+ try {
+ mISession.setPlaybackToRemote(control, max);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tell system that the session sets the new current volume.
+ *
+ * @param currentVolume the new current volume
+ */
+ void setCurrentVolume(int currentVolume) {
+ try {
+ mISession.setCurrentVolume(currentVolume);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Gets the binder */
+ @NonNull
+ public IBinder getBinder() {
+ return mISession.asBinder();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeStrongBinder(mISession.asBinder());
+ }
+
+ /**
+ * Class for Stub implementation
+ */
+ public abstract static class SessionStub {
+ /** Stub method for ISession.sendEvent */
+ public void sendEvent(@NonNull String event, @Nullable Bundle data) {
+ }
+
+ /** Stub method for ISession.getController */
+ @NonNull
+ public ControllerLink getController() {
+ return null;
+ }
+
+ /** Stub method for ISession.setFlags */
+ public void setFlags(int flags) {
+ }
+
+ /** Stub method for ISession.setActive */
+ public void setActive(boolean active) {
+ }
+
+ /** Stub method for ISession.setMediaButtonReceiver */
+ public void setMediaButtonReceiver(@Nullable PendingIntent mbr) {
+ }
+
+ /** Stub method for ISession.setLaunchPendingIntent */
+ public void setLaunchPendingIntent(@Nullable PendingIntent pi) {
+ }
+
+ /** Stub method for ISession.destroySession */
+ public void destroySession() {
+ }
+
+ /** Stub method for ISession.setMetadata */
+ public void setMetadata(@Nullable MediaMetadata metadata, long duration,
+ @Nullable String metadataDescription) {
+ }
+
+ /** Stub method for ISession.setPlaybackState */
+ public void setPlaybackState(@Nullable PlaybackState state) {
+ }
+
+ /** Stub method for ISession.setQueue */
+ public void setQueue(@Nullable List<QueueItem> queue) {
+ }
+
+ /** Stub method for ISession.setQueueTitle */
+ public void setQueueTitle(@Nullable CharSequence title) {
+ }
+
+ /** Stub method for ISession.setExtras */
+ public void setExtras(@Nullable Bundle extras) {
+ }
+
+ /** Stub method for ISession.setRatingType */
+ public void setRatingType(int type) {
+ }
+
+ /** Stub method for ISession.setPlaybackToLocal */
+ public void setPlaybackToLocal(@NonNull AudioAttributes attributes) {
+ }
+
+ /** Stub method for ISession.setPlaybackToRemote */
+ public void setPlaybackToRemote(int control, int max) {
+ }
+
+ /** Stub method for ISession.setCurrentVolume */
+ public void setCurrentVolume(int currentVolume) {
+ }
+ }
+
+ private class StubProxy extends ISession.Stub {
+ @Override
+ public void sendEvent(String event, Bundle data) {
+ mSessionStub.sendEvent(event, data);
+ }
+
+ @Override
+ public ControllerLink getController() {
+ return mSessionStub.getController();
+ }
+
+ @Override
+ public void setFlags(int flags) {
+ mSessionStub.setFlags(flags);
+ }
+
+ @Override
+ public void setActive(boolean active) {
+ mSessionStub.setActive(active);
+ }
+
+ @Override
+ public void setMediaButtonReceiver(PendingIntent mbr) {
+ mSessionStub.setMediaButtonReceiver(mbr);
+ }
+
+ @Override
+ public void setLaunchPendingIntent(PendingIntent pi) {
+ mSessionStub.setLaunchPendingIntent(pi);
+ }
+
+ @Override
+ public void destroySession() {
+ mSessionStub.destroySession();
+ }
+
+ @Override
+ public void setMetadata(MediaMetadata metadata, long duration, String metadataDescription) {
+ mSessionStub.setMetadata(metadata, duration, metadataDescription);
+ }
+
+ @Override
+ public void setPlaybackState(PlaybackState state) {
+ mSessionStub.setPlaybackState(state);
+ }
+
+ @Override
+ public void setQueue(List<QueueItem> queue) {
+ mSessionStub.setQueue(queue);
+ }
+
+ @Override
+ public void setQueueTitle(CharSequence title) {
+ mSessionStub.setQueueTitle(title);
+ }
+
+ @Override
+ public void setExtras(Bundle extras) {
+ mSessionStub.setExtras(extras);
+ }
+
+ @Override
+ public void setRatingType(int type) {
+ mSessionStub.setRatingType(type);
+ }
+
+ @Override
+ public void setPlaybackToLocal(AudioAttributes attributes) {
+ mSessionStub.setPlaybackToLocal(attributes);
+ }
+
+ @Override
+ public void setPlaybackToRemote(int control, int max) {
+ mSessionStub.setPlaybackToRemote(control, max);
+ }
+
+ @Override
+ public void setCurrentVolume(int currentVolume) {
+ mSessionStub.setCurrentVolume(currentVolume);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 7fffe8e..d8c2432 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -27,14 +27,14 @@
import android.media.Rating;
import android.media.VolumeProvider;
import android.media.session.ControllerCallbackLink;
-import android.media.session.ISession;
-import android.media.session.ISessionController;
+import android.media.session.ControllerLink;
import android.media.session.MediaController;
import android.media.session.MediaController.PlaybackInfo;
import android.media.session.MediaSession;
import android.media.session.MediaSession.QueueItem;
import android.media.session.PlaybackState;
import android.media.session.SessionCallbackLink;
+import android.media.session.SessionLink;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -77,8 +77,8 @@
private final int mUserId;
private final String mPackageName;
private final String mTag;
- private final ControllerStub mController;
- private final SessionStub mSession;
+ private final ControllerLink mController;
+ private final SessionLink mSession;
private final SessionCb mSessionCb;
private final MediaSessionService.ServiceImpl mService;
private final Context mContext;
@@ -127,8 +127,8 @@
mUserId = userId;
mPackageName = ownerPackageName;
mTag = tag;
- mController = new ControllerStub();
- mSession = new SessionStub();
+ mController = new ControllerLink(new ControllerStub());
+ mSession = new SessionLink(new SessionStub());
mSessionCb = new SessionCb(cb);
mService = service;
mContext = mService.getContext();
@@ -139,20 +139,20 @@
}
/**
- * Get the binder for the {@link MediaSession}.
+ * Get the session link for the {@link MediaSession}.
*
- * @return The session binder apps talk to.
+ * @return The session link apps talk to.
*/
- public ISession getSessionBinder() {
+ public SessionLink getSessionBinder() {
return mSession;
}
/**
- * Get the binder for the {@link MediaController}.
+ * Get the controller link for the {@link MediaController}.
*
- * @return The controller binder apps talk to.
+ * @return The controller link apps talk to.
*/
- public ISessionController getControllerBinder() {
+ public ControllerLink getControllerLink() {
return mController;
}
@@ -642,7 +642,7 @@
if (mDestroyed) {
return;
}
- PlaybackInfo info = mController.getVolumeAttributes();
+ PlaybackInfo info = getVolumeAttributes();
for (int i = mControllerCallbackHolders.size() - 1; i >= 0; i--) {
ControllerCallbackLinkHolder holder = mControllerCallbackHolders.get(i);
try {
@@ -750,6 +750,25 @@
return -1;
}
+ private PlaybackInfo getVolumeAttributes() {
+ int volumeType;
+ AudioAttributes attributes;
+ synchronized (mLock) {
+ if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_REMOTE) {
+ int current = mOptimisticVolume != -1 ? mOptimisticVolume : mCurrentVolume;
+ return new PlaybackInfo(mVolumeType, mVolumeControlType, mMaxVolume, current,
+ mAudioAttrs);
+ }
+ volumeType = mVolumeType;
+ attributes = mAudioAttrs;
+ }
+ int stream = AudioAttributes.toLegacyStreamType(attributes);
+ int max = mAudioManager.getStreamMaxVolume(stream);
+ int current = mAudioManager.getStreamVolume(stream);
+ return new PlaybackInfo(volumeType, VolumeProvider.VOLUME_CONTROL_ABSOLUTE, max,
+ current, attributes);
+ }
+
private final Runnable mClearOptimisticVolumeRunnable = new Runnable() {
@Override
public void run() {
@@ -761,9 +780,9 @@
}
};
- private final class SessionStub extends ISession.Stub {
+ private final class SessionStub extends SessionLink.SessionStub {
@Override
- public void destroy() {
+ public void destroySession() {
final long token = Binder.clearCallingIdentity();
try {
mService.destroySession(MediaSessionRecord.this);
@@ -779,7 +798,7 @@
}
@Override
- public ISessionController getController() {
+ public ControllerLink getController() {
return mController;
}
@@ -798,8 +817,8 @@
@Override
public void setFlags(int flags) {
if ((flags & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
- int pid = getCallingPid();
- int uid = getCallingUid();
+ int pid = Binder.getCallingPid();
+ int uid = Binder.getCallingUid();
mService.enforcePhoneStatePermission(pid, uid);
}
mFlags = flags;
@@ -1183,7 +1202,7 @@
}
}
- class ControllerStub extends ISessionController.Stub {
+ class ControllerStub extends ControllerLink.ControllerStub {
@Override
public void sendCommand(String packageName, ControllerCallbackLink caller,
String command, Bundle args, ResultReceiver cb) {
@@ -1199,7 +1218,7 @@
}
@Override
- public void registerCallbackListener(String packageName, ControllerCallbackLink cb) {
+ public void registerCallback(String packageName, ControllerCallbackLink cb) {
synchronized (mLock) {
// If this session is already destroyed tell the caller and
// don't add them.
@@ -1223,7 +1242,7 @@
}
@Override
- public void unregisterCallbackListener(ControllerCallbackLink cb) {
+ public void unregisterCallback(ControllerCallbackLink cb) {
synchronized (mLock) {
int index = getControllerHolderIndexForCb(cb);
if (index != -1) {
@@ -1257,22 +1276,7 @@
@Override
public PlaybackInfo getVolumeAttributes() {
- int volumeType;
- AudioAttributes attributes;
- synchronized (mLock) {
- if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_REMOTE) {
- int current = mOptimisticVolume != -1 ? mOptimisticVolume : mCurrentVolume;
- return new PlaybackInfo(mVolumeType, mVolumeControlType, mMaxVolume, current,
- mAudioAttrs);
- }
- volumeType = mVolumeType;
- attributes = mAudioAttrs;
- }
- int stream = AudioAttributes.toLegacyStreamType(attributes);
- int max = mAudioManager.getStreamMaxVolume(stream);
- int current = mAudioManager.getStreamVolume(stream);
- return new PlaybackInfo(volumeType, VolumeProvider.VOLUME_CONTROL_ABSOLUTE, max,
- current, attributes);
+ return MediaSessionRecord.this.getVolumeAttributes();
}
@Override
@@ -1449,11 +1453,6 @@
public int getRatingType() {
return mRatingType;
}
-
- @Override
- public boolean isTransportControlEnabled() {
- return MediaSessionRecord.this.isTransportControlEnabled();
- }
}
private class ControllerCallbackLinkHolder {
diff --git a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
index f374c6d..e3ae8a7 100644
--- a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
@@ -45,16 +45,18 @@
import android.media.MediaController2;
import android.media.Session2CommandGroup;
import android.media.Session2Token;
+import android.media.session.ControllerLink;
import android.media.session.IActiveSessionsListener;
import android.media.session.ICallback;
import android.media.session.IOnMediaKeyListener;
import android.media.session.IOnVolumeKeyLongPressListener;
-import android.media.session.ISession;
import android.media.session.ISession2TokensListener;
+import android.media.session.ISessionController;
import android.media.session.ISessionManager;
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.SessionCallbackLink;
+import android.media.session.SessionLink;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -288,7 +290,9 @@
return;
}
try {
- mRvc.remoteVolumeChanged(session.getControllerBinder(), flags);
+ mRvc.remoteVolumeChanged(
+ ISessionController.Stub.asInterface(session.getControllerLink().getBinder()),
+ flags);
} catch (Exception e) {
Log.wtf(TAG, "Error sending volume change to system UI.", e);
}
@@ -614,7 +618,7 @@
int size = records.size();
ArrayList<MediaSession.Token> tokens = new ArrayList<MediaSession.Token>();
for (int i = 0; i < size; i++) {
- tokens.add(new MediaSession.Token(records.get(i).getControllerBinder()));
+ tokens.add(new MediaSession.Token(records.get(i).getControllerLink()));
}
pushRemoteVolumeUpdateLocked(userId);
for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
@@ -641,7 +645,9 @@
return;
}
MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
- mRvc.updateRemoteController(record == null ? null : record.getControllerBinder());
+ mRvc.updateRemoteController(record == null ? null
+ : ISessionController.Stub.asInterface(
+ record.getControllerLink().getBinder()));
} catch (RemoteException e) {
Log.wtf(TAG, "Error sending default remote volume to sys ui.", e);
}
@@ -858,7 +864,7 @@
MediaSessionRecord mediaButtonSession = getMediaButtonSessionLocked();
if (mediaButtonSession != null) {
mCallback.onAddressedPlayerChangedToMediaSession(
- new MediaSession.Token(mediaButtonSession.getControllerBinder()));
+ new MediaSession.Token(mediaButtonSession.getControllerLink()));
} else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
mCurrentFullUserRecord.mLastMediaButtonReceiver
@@ -978,7 +984,7 @@
private boolean mVoiceButtonHandled = false;
@Override
- public ISession createSession(String packageName, SessionCallbackLink cb, String tag,
+ public SessionLink createSession(String packageName, SessionCallbackLink cb, String tag,
int userId) throws RemoteException {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
@@ -1023,18 +1029,18 @@
}
@Override
- public List<IBinder> getSessions(ComponentName componentName, int userId) {
+ public List<ControllerLink> getSessions(ComponentName componentName, int userId) {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
int resolvedUserId = verifySessionsRequest(componentName, userId, pid, uid);
- ArrayList<IBinder> binders = new ArrayList<IBinder>();
+ ArrayList<ControllerLink> binders = new ArrayList<>();
synchronized (mLock) {
List<MediaSessionRecord> records = getActiveSessionsLocked(resolvedUserId);
for (MediaSessionRecord record : records) {
- binders.add(record.getControllerBinder().asBinder());
+ binders.add(record.getControllerLink());
}
}
return binders;
@@ -1798,7 +1804,7 @@
if (mCurrentFullUserRecord.mCallback != null) {
try {
mCurrentFullUserRecord.mCallback.onMediaKeyEventDispatchedToMediaSession(
- keyEvent, new MediaSession.Token(session.getControllerBinder()));
+ keyEvent, new MediaSession.Token(session.getControllerLink()));
} catch (RemoteException e) {
Log.w(TAG, "Failed to send callback", e);
}