From 7553b35ea1a519cc9d15b0b3da572c3061675c40 Mon Sep 17 00:00:00 2001 From: Sungsoo Lim Date: Fri, 11 Jan 2019 17:06:40 +0900 Subject: [PATCH] Unhide MediaSession2 and MediaController2 Also unhide the relevant class: Session2Token. Bug: 122055262 Test: pass MediaSession2Test and MediaController2Test Change-Id: I7fb94b24082d683ff6367961e300f9ce5f6f8821 --- api/current.txt | 60 +++++++++++++++++++ api/system-current.txt | 2 +- media/java/android/media/MediaConstants.java | 2 +- .../java/android/media/MediaController2.java | 13 ++-- media/java/android/media/MediaSession2.java | 20 ++++--- .../android/media/Session2CommandGroup.java | 1 + media/java/android/media/Session2Token.java | 19 ++---- 7 files changed, 88 insertions(+), 29 deletions(-) diff --git a/api/current.txt b/api/current.txt index 39ee0ede83a19..afff3d28cd427 100644 --- a/api/current.txt +++ b/api/current.txt @@ -24518,6 +24518,22 @@ package android.media { field public static final int REGULAR_CODECS = 0; // 0x0 } + public class MediaController2 implements java.lang.AutoCloseable { + ctor public MediaController2(android.content.Context, android.media.Session2Token); + ctor public MediaController2(android.content.Context, android.media.Session2Token, java.util.concurrent.Executor, android.media.MediaController2.ControllerCallback); + method public void cancelSessionCommand(java.lang.Object); + method public void close(); + method public java.lang.Object sendSessionCommand(android.media.Session2Command, android.os.Bundle); + } + + public static abstract class MediaController2.ControllerCallback { + ctor public MediaController2.ControllerCallback(); + method public void onCommandResult(android.media.MediaController2, java.lang.Object, android.media.Session2Command, android.media.Session2Command.Result); + method public void onConnected(android.media.MediaController2, android.media.Session2CommandGroup); + method public void onDisconnected(android.media.MediaController2); + method public android.media.Session2Command.Result onSessionCommand(android.media.MediaController2, android.media.Session2Command, android.os.Bundle); + } + public final class MediaCrypto { ctor public MediaCrypto(java.util.UUID, byte[]) throws android.media.MediaCryptoException; method protected void finalize(); @@ -25806,6 +25822,37 @@ package android.media { method public abstract void onScanCompleted(java.lang.String, android.net.Uri); } + public class MediaSession2 implements java.lang.AutoCloseable { + method public void broadcastSessionCommand(android.media.Session2Command, android.os.Bundle); + method public void cancelSessionCommand(android.media.MediaSession2.ControllerInfo, java.lang.Object); + method public void close(); + method public java.lang.String getSessionId(); + method public android.media.Session2Token getSessionToken(); + method public java.lang.Object sendSessionCommand(android.media.MediaSession2.ControllerInfo, android.media.Session2Command, android.os.Bundle); + } + + public static final class MediaSession2.Builder { + ctor public MediaSession2.Builder(android.content.Context); + method public android.media.MediaSession2 build(); + method public android.media.MediaSession2.Builder setId(java.lang.String); + method public android.media.MediaSession2.Builder setSessionActivity(android.app.PendingIntent); + method public android.media.MediaSession2.Builder setSessionCallback(java.util.concurrent.Executor, android.media.MediaSession2.SessionCallback); + } + + public static final class MediaSession2.ControllerInfo { + method public java.lang.String getPackageName(); + method public android.media.session.MediaSessionManager.RemoteUserInfo getRemoteUserInfo(); + method public int getUid(); + } + + public static abstract class MediaSession2.SessionCallback { + ctor public MediaSession2.SessionCallback(); + method public void onCommandResult(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, java.lang.Object, android.media.Session2Command, android.media.Session2Command.Result); + method public android.media.Session2CommandGroup onConnect(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo); + method public void onDisconnected(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo); + method public android.media.Session2Command.Result onSessionCommand(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, android.media.Session2Command, android.os.Bundle); + } + public final class MediaSync { ctor public MediaSync(); method public android.view.Surface createInputSurface(); @@ -26119,6 +26166,19 @@ package android.media { method public android.media.Session2CommandGroup.Builder removeCommand(int); } + public final class Session2Token implements android.os.Parcelable { + ctor public Session2Token(android.content.Context, android.content.ComponentName); + method public int describeContents(); + method public java.lang.String getPackageName(); + method public java.lang.String getServiceName(); + method public int getType(); + method public int getUid(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int TYPE_SESSION = 0; // 0x0 + field public static final int TYPE_SESSION_SERVICE = 1; // 0x1 + } + public class SoundPool { ctor public deprecated SoundPool(int, int, int); method public final void autoPause(); diff --git a/api/system-current.txt b/api/system-current.txt index e5b65b1ce3f0b..78f3471c3e868 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1284,8 +1284,8 @@ package android.content { field public static final java.lang.String EXTRA_LONG_VERSION_CODE = "android.intent.extra.LONG_VERSION_CODE"; field public static final java.lang.String EXTRA_ORIGINATING_UID = "android.intent.extra.ORIGINATING_UID"; field public static final java.lang.String EXTRA_PACKAGES = "android.intent.extra.PACKAGES"; - field public static final java.lang.String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME"; field public static final java.lang.String EXTRA_PERMISSION_GROUP_NAME = "android.intent.extra.PERMISSION_GROUP_NAME"; + field public static final java.lang.String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME"; field public static final java.lang.String EXTRA_REASON = "android.intent.extra.REASON"; field public static final java.lang.String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK"; field public static final java.lang.String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED"; diff --git a/media/java/android/media/MediaConstants.java b/media/java/android/media/MediaConstants.java index 275b0acd8ad6b..5a5747ae4bab4 100644 --- a/media/java/android/media/MediaConstants.java +++ b/media/java/android/media/MediaConstants.java @@ -24,7 +24,7 @@ class MediaConstants { static final String KEY_PACKAGE_NAME = "android.media.key.PACKAGE_NAME"; // Bundle key for Parcelable - static final String KEY_SESSION2_STUB = "android.media.key.SESSION2_STUB"; + static final String KEY_SESSION2LINK = "android.media.key.SESSION2LINK"; static final String KEY_ALLOWED_COMMANDS = "android.media.key.ALLOWED_COMMANDS"; private MediaConstants() { diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java index b8381a7249bea..774ea185f57cf 100644 --- a/media/java/android/media/MediaController2.java +++ b/media/java/android/media/MediaController2.java @@ -19,7 +19,7 @@ package android.media; import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS; import static android.media.MediaConstants.KEY_PACKAGE_NAME; import static android.media.MediaConstants.KEY_PID; -import static android.media.MediaConstants.KEY_SESSION2_STUB; +import static android.media.MediaConstants.KEY_SESSION2LINK; import static android.media.Session2Command.RESULT_ERROR_UNKNOWN_ERROR; import static android.media.Session2Command.RESULT_INFO_SKIPPED; import static android.media.Session2Token.TYPE_SESSION; @@ -41,15 +41,15 @@ import java.util.concurrent.Executor; /** * Allows an app to interact with an active {@link MediaSession2} or a - * {@link MediaSession2Service} which would provide {@link MediaSession2}. Media buttons and other + * MediaSession2Service which would provide {@link MediaSession2}. Media buttons and other * commands can be sent to the session. *

* This API is not generally intended for third party application developers. * Use the AndroidX * Media2 Library * for consistent behavior across all devices. - * @hide */ +// TODO: use @link for MediaSession2Service public class MediaController2 implements AutoCloseable { static final String TAG = "MediaController2"; static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -130,8 +130,8 @@ public class MediaController2 implements AutoCloseable { synchronized (mLock) { if (mSessionBinder != null) { try { - mSessionBinder.unlinkToDeath(mDeathRecipient, 0); mSessionBinder.disconnect(mControllerStub, getNextSeqNumber()); + mSessionBinder.unlinkToDeath(mDeathRecipient, 0); } catch (RuntimeException e) { // No-op } @@ -153,6 +153,7 @@ public class MediaController2 implements AutoCloseable { * @return a token which will be sent together in {@link ControllerCallback#onCommandResult} * when its result is received. */ + @NonNull public Object sendSessionCommand(@NonNull Session2Command command, @Nullable Bundle args) { if (command == null) { throw new IllegalArgumentException("command shouldn't be null"); @@ -208,7 +209,7 @@ public class MediaController2 implements AutoCloseable { void onConnected(int seq, Bundle connectionResult) { final long token = Binder.clearCallingIdentity(); try { - Session2Link sessionBinder = connectionResult.getParcelable(KEY_SESSION2_STUB); + Session2Link sessionBinder = connectionResult.getParcelable(KEY_SESSION2LINK); Session2CommandGroup allowedCommands = connectionResult.getParcelable(KEY_ALLOWED_COMMANDS); if (DEBUG) { @@ -349,7 +350,7 @@ public class MediaController2 implements AutoCloseable { * @return the result for the session command. A runtime exception will be thrown if null * is returned. */ - @NonNull + @Nullable public Session2Command.Result onSessionCommand(@NonNull MediaController2 controller, @NonNull Session2Command command, @Nullable Bundle args) { return null; diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java index 7b20f7ae5954e..e008adf120abe 100644 --- a/media/java/android/media/MediaSession2.java +++ b/media/java/android/media/MediaSession2.java @@ -19,7 +19,7 @@ package android.media; import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS; import static android.media.MediaConstants.KEY_PACKAGE_NAME; import static android.media.MediaConstants.KEY_PID; -import static android.media.MediaConstants.KEY_SESSION2_STUB; +import static android.media.MediaConstants.KEY_SESSION2LINK; import static android.media.Session2Command.RESULT_ERROR_UNKNOWN_ERROR; import static android.media.Session2Command.RESULT_INFO_SKIPPED; import static android.media.Session2Token.TYPE_SESSION; @@ -56,10 +56,9 @@ import java.util.concurrent.Executor; * Use the AndroidX * Media2 Library * for consistent behavior across all devices. - * @hide */ public class MediaSession2 implements AutoCloseable { - static final String TAG = "MediaSession"; + static final String TAG = "MediaSession2"; static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); // Note: This checks the uniqueness of a session ID only in a single process. @@ -89,7 +88,6 @@ public class MediaSession2 implements AutoCloseable { private final Handler mResultHandler; //@GuardedBy("mLock") - @SuppressWarnings("WeakerAccess") /* synthetic access */ private boolean mClosed; MediaSession2(@NonNull Context context, @NonNull String id, PendingIntent sessionActivity, @@ -113,6 +111,7 @@ public class MediaSession2 implements AutoCloseable { Context.MEDIA_SESSION_SERVICE); // NOTE: mResultHandler uses main looper, so this MUST NOT be blocked. mResultHandler = new Handler(context.getMainLooper()); + mClosed = false; } @Override @@ -179,6 +178,7 @@ public class MediaSession2 implements AutoCloseable { * @return a token which will be sent together in {@link SessionCallback#onCommandResult} * when its result is received. */ + @NonNull public Object sendSessionCommand(@NonNull ControllerInfo controller, @NonNull Session2Command command, @Nullable Bundle args) { if (controller == null) { @@ -206,7 +206,10 @@ public class MediaSession2 implements AutoCloseable { * @param controller the controller to get the session command * @param token the token which is returned from {@link #sendSessionCommand}. */ - public void cancelSessionCommand(ControllerInfo controller, Object token) { + public void cancelSessionCommand(@NonNull ControllerInfo controller, @NonNull Object token) { + if (controller == null) { + throw new IllegalArgumentException("controller shouldn't be null"); + } if (token == null) { throw new IllegalArgumentException("token shouldn't be null"); } @@ -267,7 +270,7 @@ public class MediaSession2 implements AutoCloseable { // It's needed because we cannot call synchronous calls between // session/controller. Bundle connectionResult = new Bundle(); - connectionResult.putParcelable(KEY_SESSION2_STUB, mSessionStub); + connectionResult.putParcelable(KEY_SESSION2LINK, mSessionStub); connectionResult.putParcelable(KEY_ALLOWED_COMMANDS, controllerInfo.mAllowedCommands); @@ -558,7 +561,7 @@ public class MediaSession2 implements AutoCloseable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (!(obj instanceof ControllerInfo)) return false; if (this == obj) return true; @@ -570,6 +573,7 @@ public class MediaSession2 implements AutoCloseable { } @Override + @NonNull public String toString() { return "ControllerInfo {pkg=" + mRemoteUserInfo.getPackageName() + ", uid=" + mRemoteUserInfo.getUid() + ", allowedCommands=" + mAllowedCommands + "})"; @@ -693,7 +697,7 @@ public class MediaSession2 implements AutoCloseable { * @return the result for the session command. A runtime exception will be thrown if null * is returned. */ - @NonNull + @Nullable public Session2Command.Result onSessionCommand(@NonNull MediaSession2 session, @NonNull ControllerInfo controller, @NonNull Session2Command command, @Nullable Bundle args) { diff --git a/media/java/android/media/Session2CommandGroup.java b/media/java/android/media/Session2CommandGroup.java index 519888e864625..a189c264b0296 100644 --- a/media/java/android/media/Session2CommandGroup.java +++ b/media/java/android/media/Session2CommandGroup.java @@ -59,6 +59,7 @@ public final class Session2CommandGroup implements Parcelable { * * @param commands The collection of commands to copy. */ + @SuppressWarnings("WeakerAccess") /* synthetic access */ Session2CommandGroup(@Nullable Collection commands) { if (commands != null) { mCommands.addAll(commands); diff --git a/media/java/android/media/Session2Token.java b/media/java/android/media/Session2Token.java index e1fff38c6a798..95ee4c039f4bc 100644 --- a/media/java/android/media/Session2Token.java +++ b/media/java/android/media/Session2Token.java @@ -34,7 +34,7 @@ import java.util.List; import java.util.Objects; /** - * Represents an ongoing {@link MediaSession2} or a {@link MediaSession2Service}. + * Represents an ongoing {@link MediaSession2} or a MediaSession2Service. * If it's representing a session service, it may not be ongoing. *

* This API is not generally intended for third party application developers. @@ -45,9 +45,8 @@ import java.util.Objects; * This may be passed to apps by the session owner to allow them to create a * {@link MediaController2} to communicate with the session. *

- * It can be also obtained by {@link MediaSessionManager}. + * It can be also obtained by {@link android.media.session.MediaSessionManager}. * - * @hide */ // New version of MediaSession2.Token for following reasons // - Stop implementing Parcelable for updatable support @@ -56,6 +55,7 @@ import java.util.Objects; // This helps controller apps to keep target of dispatching media key events in uniform way. // For details about the reason, see following. (Android O+) // android.media.session.MediaSessionManager.Callback#onAddressedPlayerChanged +// TODO: use @link for MediaSession2Service public final class Session2Token implements Parcelable { private static final String TAG = "Session2Token"; @@ -75,7 +75,7 @@ public final class Session2Token implements Parcelable { * @hide */ @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = "TYPE_", value = {TYPE_SESSION, TYPE_SESSION_SERVICE, TYPE_LIBRARY_SERVICE}) + @IntDef(prefix = "TYPE_", value = {TYPE_SESSION, TYPE_SESSION_SERVICE}) public @interface TokenType { } @@ -85,15 +85,10 @@ public final class Session2Token implements Parcelable { public static final int TYPE_SESSION = 0; /** - * Type for {@link MediaSession2Service}. + * Type for MediaSession2Service. */ public static final int TYPE_SESSION_SERVICE = 1; - /** - * Type for {@link MediaLibrary2Service}. - */ - public static final int TYPE_LIBRARY_SERVICE = 2; - private final int mUid; private final @TokenType int mType; private final String mPackageName; @@ -102,8 +97,7 @@ public final class Session2Token implements Parcelable { private final ComponentName mComponentName; /** - * Constructor for the token with type {@link #TYPE_SESSION_SERVICE} or - * {@link #TYPE_LIBRARY_SERVICE}. + * Constructor for the token with type {@link #TYPE_SESSION_SERVICE}. * * @param context The context. * @param serviceComponent The component name of the service. @@ -239,7 +233,6 @@ public final class Session2Token implements Parcelable { * @return type of the token * @see #TYPE_SESSION * @see #TYPE_SESSION_SERVICE - * @see #TYPE_LIBRARY_SERVICE */ public @TokenType int getType() { return mType;