Loading media/java/android/media/Controller2Link.java +16 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import java.util.Objects; /** * Handles incoming commands from {@link MediaSession2} and {@link MediaLibrarySession} * to both {@link MediaController2} and {@link MediaBrowser2}. Loading Loading @@ -68,6 +70,20 @@ public final class Controller2Link implements Parcelable { dest.writeStrongBinder(mIController.asBinder()); } @Override public int hashCode() { return mIController.asBinder().hashCode(); } @Override public boolean equals(Object obj) { if (!(obj instanceof Controller2Link)) { return false; } Controller2Link other = (Controller2Link) obj; return Objects.equals(mIController.asBinder(), other.mIController.asBinder()); } /** Interface method for IMediaController2.notifyConnected */ public void notifyConnected(int seq, Bundle connectionResult) { try { Loading media/java/android/media/MediaController2.java +11 −2 Original line number Diff line number Diff line Loading @@ -98,7 +98,6 @@ public class MediaController2 implements AutoCloseable { mNextSeqNumber = 0; Session2Link sessionBinder = token.getSessionLink(); if (token.getType() == TYPE_SESSION) { connectToSession(); } else { Loading @@ -120,9 +119,11 @@ public class MediaController2 implements AutoCloseable { mCallbackExecutor.execute(() -> { mCallback.onDisconnected(MediaController2.this); }); mSessionBinder = null; } } // Called by Controller2Link.onConnected void onConnected(int seq, Bundle connectionResult) { final long token = Binder.clearCallingIdentity(); try { Loading Loading @@ -155,10 +156,18 @@ public class MediaController2 implements AutoCloseable { } } // Called by Controller2Link.onDisconnected void onDisconnected(int seq) { // TODO: Implement this final long token = Binder.clearCallingIdentity(); try { // close() will call mCallback.onDisconnected close(); } finally { Binder.restoreCallingIdentity(token); } } // Called by Controller2Link.onSessionCommand void onSessionCommand(int seq, Session2Command command, Bundle args) { // TODO: Implement this } Loading media/java/android/media/MediaSession2.java +59 −22 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.Process; import android.util.Log; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; Loading Loading @@ -107,7 +108,13 @@ public class MediaSession2 implements AutoCloseable { synchronized (MediaSession2.class) { SESSION_ID_LIST.remove(mSessionId); } // TODO: Implement this Collection<ControllerInfo> controllerInfos; synchronized (mLock) { controllerInfos = mConnectedControllers.values(); } for (ControllerInfo info : controllerInfos) { info.notifyDisconnected(); } } catch (Exception e) { // Should not be here. } Loading @@ -118,6 +125,7 @@ public class MediaSession2 implements AutoCloseable { return true; } // Called by Session2Link.onConnect void onConnect(final Controller2Link controller, int seq, Bundle connectionRequest) { if (controller == null || connectionRequest == null) { return; Loading Loading @@ -173,21 +181,12 @@ public class MediaSession2 implements AutoCloseable { if (isClosed()) { return; } try { controller.notifyConnected( controllerInfo.mNextSeqNumber++, connectionResult); } catch (RuntimeException e) { // Controller may be died prematurely. } controllerInfo.notifyConnected(connectionResult); } else { if (DEBUG) { Log.d(TAG, "Rejecting connection, controllerInfo=" + controllerInfo); } try { controller.notifyDisconnected(controllerInfo.mNextSeqNumber++); } catch (RuntimeException e) { // Controller may be died prematurely. } controllerInfo.notifyDisconnected(); } }); } finally { Loading @@ -195,20 +194,24 @@ public class MediaSession2 implements AutoCloseable { } } // Called by Session2Link.onDisconnect void onDisconnect(final Controller2Link controller, int seq) { if (controller == null) { return; } final ControllerInfo controllerInfo; synchronized (mLock) { controllerInfo = mConnectedControllers.get(controller); } if (controllerInfo == null) { return; } final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { final ControllerInfo controllerInfo = mConnectedControllers.get(controller); mCallbackExecutor.execute(() -> { try { controller.notifyDisconnected(controllerInfo.mNextSeqNumber++); } catch (RuntimeException e) { // Controller may be died prematurely. } mCallback.onDisconnected(MediaSession2.this, controllerInfo); }); mConnectedControllers.remove(controller); } Loading @@ -217,6 +220,7 @@ public class MediaSession2 implements AutoCloseable { } } // Called by Session2Link.onSessionCommand void onSessionCommand(final Controller2Link controller, final int seq, final Session2Command command, final Bundle args) { // TODO: Implement this Loading Loading @@ -323,13 +327,12 @@ public class MediaSession2 implements AutoCloseable { * <p> * This API is not generally intended for third party application developers. */ public static final class ControllerInfo { static final class ControllerInfo { private final RemoteUserInfo mRemoteUserInfo; private final boolean mIsTrusted; private final Controller2Link mControllerBinder; private int mNextSeqNumber; @SuppressWarnings("WeakerAccess") /* synthetic access */ int mNextSeqNumber; @SuppressWarnings("WeakerAccess") /* synthetic access */ Session2CommandGroup mAllowedCommands; Loading @@ -348,7 +351,7 @@ public class MediaSession2 implements AutoCloseable { } /** * @hide * @return remote user info of the controller. */ @NonNull public RemoteUserInfo getRemoteUserInfo() { Loading @@ -370,6 +373,36 @@ public class MediaSession2 implements AutoCloseable { return mRemoteUserInfo.getUid(); } public void notifyConnected(Bundle connectionResult) { if (mControllerBinder != null) { try { mControllerBinder.notifyConnected(getNextSeqNumber(), connectionResult); } catch (RuntimeException e) { // Controller may be died prematurely. } } } public void notifyDisconnected() { if (mControllerBinder != null) { try { mControllerBinder.notifyDisconnected(getNextSeqNumber()); } catch (RuntimeException e) { // Controller may be died prematurely. } } } public void sendSessionCommand(Session2Command command, Bundle args) { if (mControllerBinder != null) { try { mControllerBinder.sendSessionCommand(getNextSeqNumber(), command, args); } catch (RuntimeException e) { // Controller may be died prematurely. } } } /** * Return if the controller has granted {@code android.permission.MEDIA_CONTENT_CONTROL} or * has a enabled notification listener so can be trusted to accept connection and incoming Loading Loading @@ -407,6 +440,10 @@ public class MediaSession2 implements AutoCloseable { return "ControllerInfo {pkg=" + mRemoteUserInfo.getPackageName() + ", uid=" + mRemoteUserInfo.getUid() + ", allowedCommands=" + mAllowedCommands + "})"; } private synchronized int getNextSeqNumber() { return mNextSeqNumber++; } } /** Loading Loading
media/java/android/media/Controller2Link.java +16 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import java.util.Objects; /** * Handles incoming commands from {@link MediaSession2} and {@link MediaLibrarySession} * to both {@link MediaController2} and {@link MediaBrowser2}. Loading Loading @@ -68,6 +70,20 @@ public final class Controller2Link implements Parcelable { dest.writeStrongBinder(mIController.asBinder()); } @Override public int hashCode() { return mIController.asBinder().hashCode(); } @Override public boolean equals(Object obj) { if (!(obj instanceof Controller2Link)) { return false; } Controller2Link other = (Controller2Link) obj; return Objects.equals(mIController.asBinder(), other.mIController.asBinder()); } /** Interface method for IMediaController2.notifyConnected */ public void notifyConnected(int seq, Bundle connectionResult) { try { Loading
media/java/android/media/MediaController2.java +11 −2 Original line number Diff line number Diff line Loading @@ -98,7 +98,6 @@ public class MediaController2 implements AutoCloseable { mNextSeqNumber = 0; Session2Link sessionBinder = token.getSessionLink(); if (token.getType() == TYPE_SESSION) { connectToSession(); } else { Loading @@ -120,9 +119,11 @@ public class MediaController2 implements AutoCloseable { mCallbackExecutor.execute(() -> { mCallback.onDisconnected(MediaController2.this); }); mSessionBinder = null; } } // Called by Controller2Link.onConnected void onConnected(int seq, Bundle connectionResult) { final long token = Binder.clearCallingIdentity(); try { Loading Loading @@ -155,10 +156,18 @@ public class MediaController2 implements AutoCloseable { } } // Called by Controller2Link.onDisconnected void onDisconnected(int seq) { // TODO: Implement this final long token = Binder.clearCallingIdentity(); try { // close() will call mCallback.onDisconnected close(); } finally { Binder.restoreCallingIdentity(token); } } // Called by Controller2Link.onSessionCommand void onSessionCommand(int seq, Session2Command command, Bundle args) { // TODO: Implement this } Loading
media/java/android/media/MediaSession2.java +59 −22 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.Process; import android.util.Log; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; Loading Loading @@ -107,7 +108,13 @@ public class MediaSession2 implements AutoCloseable { synchronized (MediaSession2.class) { SESSION_ID_LIST.remove(mSessionId); } // TODO: Implement this Collection<ControllerInfo> controllerInfos; synchronized (mLock) { controllerInfos = mConnectedControllers.values(); } for (ControllerInfo info : controllerInfos) { info.notifyDisconnected(); } } catch (Exception e) { // Should not be here. } Loading @@ -118,6 +125,7 @@ public class MediaSession2 implements AutoCloseable { return true; } // Called by Session2Link.onConnect void onConnect(final Controller2Link controller, int seq, Bundle connectionRequest) { if (controller == null || connectionRequest == null) { return; Loading Loading @@ -173,21 +181,12 @@ public class MediaSession2 implements AutoCloseable { if (isClosed()) { return; } try { controller.notifyConnected( controllerInfo.mNextSeqNumber++, connectionResult); } catch (RuntimeException e) { // Controller may be died prematurely. } controllerInfo.notifyConnected(connectionResult); } else { if (DEBUG) { Log.d(TAG, "Rejecting connection, controllerInfo=" + controllerInfo); } try { controller.notifyDisconnected(controllerInfo.mNextSeqNumber++); } catch (RuntimeException e) { // Controller may be died prematurely. } controllerInfo.notifyDisconnected(); } }); } finally { Loading @@ -195,20 +194,24 @@ public class MediaSession2 implements AutoCloseable { } } // Called by Session2Link.onDisconnect void onDisconnect(final Controller2Link controller, int seq) { if (controller == null) { return; } final ControllerInfo controllerInfo; synchronized (mLock) { controllerInfo = mConnectedControllers.get(controller); } if (controllerInfo == null) { return; } final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { final ControllerInfo controllerInfo = mConnectedControllers.get(controller); mCallbackExecutor.execute(() -> { try { controller.notifyDisconnected(controllerInfo.mNextSeqNumber++); } catch (RuntimeException e) { // Controller may be died prematurely. } mCallback.onDisconnected(MediaSession2.this, controllerInfo); }); mConnectedControllers.remove(controller); } Loading @@ -217,6 +220,7 @@ public class MediaSession2 implements AutoCloseable { } } // Called by Session2Link.onSessionCommand void onSessionCommand(final Controller2Link controller, final int seq, final Session2Command command, final Bundle args) { // TODO: Implement this Loading Loading @@ -323,13 +327,12 @@ public class MediaSession2 implements AutoCloseable { * <p> * This API is not generally intended for third party application developers. */ public static final class ControllerInfo { static final class ControllerInfo { private final RemoteUserInfo mRemoteUserInfo; private final boolean mIsTrusted; private final Controller2Link mControllerBinder; private int mNextSeqNumber; @SuppressWarnings("WeakerAccess") /* synthetic access */ int mNextSeqNumber; @SuppressWarnings("WeakerAccess") /* synthetic access */ Session2CommandGroup mAllowedCommands; Loading @@ -348,7 +351,7 @@ public class MediaSession2 implements AutoCloseable { } /** * @hide * @return remote user info of the controller. */ @NonNull public RemoteUserInfo getRemoteUserInfo() { Loading @@ -370,6 +373,36 @@ public class MediaSession2 implements AutoCloseable { return mRemoteUserInfo.getUid(); } public void notifyConnected(Bundle connectionResult) { if (mControllerBinder != null) { try { mControllerBinder.notifyConnected(getNextSeqNumber(), connectionResult); } catch (RuntimeException e) { // Controller may be died prematurely. } } } public void notifyDisconnected() { if (mControllerBinder != null) { try { mControllerBinder.notifyDisconnected(getNextSeqNumber()); } catch (RuntimeException e) { // Controller may be died prematurely. } } } public void sendSessionCommand(Session2Command command, Bundle args) { if (mControllerBinder != null) { try { mControllerBinder.sendSessionCommand(getNextSeqNumber(), command, args); } catch (RuntimeException e) { // Controller may be died prematurely. } } } /** * Return if the controller has granted {@code android.permission.MEDIA_CONTENT_CONTROL} or * has a enabled notification listener so can be trusted to accept connection and incoming Loading Loading @@ -407,6 +440,10 @@ public class MediaSession2 implements AutoCloseable { return "ControllerInfo {pkg=" + mRemoteUserInfo.getPackageName() + ", uid=" + mRemoteUserInfo.getUid() + ", allowedCommands=" + mAllowedCommands + "})"; } private synchronized int getNextSeqNumber() { return mNextSeqNumber++; } } /** Loading