use of androidx.media3.session.MediaSession.ControllerInfo in project media by androidx.
the class MediaLibraryServiceLegacyStub method onCustomAction.
@Override
public void onCustomAction(String action, Bundle extras, Result<Bundle> result) {
@Nullable ControllerInfo controller = getCurrentController();
if (controller == null) {
result.sendError(/* extras= */
null);
return;
}
result.detach();
postOrRun(librarySessionImpl.getApplicationHandler(), () -> {
SessionCommand command = new SessionCommand(action, /* extras= */
Bundle.EMPTY);
if (!getConnectedControllersManager().isSessionCommandAvailable(controller, command)) {
result.sendError(/* extras= */
null);
return;
}
ListenableFuture<SessionResult> future = librarySessionImpl.onCustomCommandOnHandler(controller, command, extras);
sendCustomActionResultWhenReady(result, future);
});
}
use of androidx.media3.session.MediaSession.ControllerInfo in project media by androidx.
the class MediaLibraryServiceLegacyStub method onLoadChildren.
@Override
public void onLoadChildren(String parentId, Result<List<MediaBrowserCompat.MediaItem>> result, @Nullable Bundle options) {
@Nullable ControllerInfo controller = getCurrentController();
if (controller == null) {
result.sendError(/* extras= */
null);
return;
}
if (TextUtils.isEmpty(parentId)) {
Log.w(TAG, "onLoadChildren(): Ignoring empty parentId from " + controller);
result.sendError(/* extras= */
null);
return;
}
result.detach();
postOrRun(librarySessionImpl.getApplicationHandler(), () -> {
if (!getConnectedControllersManager().isSessionCommandAvailable(controller, SessionCommand.COMMAND_CODE_LIBRARY_GET_CHILDREN)) {
result.sendError(/* extras= */
null);
return;
}
if (options != null) {
options.setClassLoader(librarySessionImpl.getContext().getClassLoader());
try {
int page = options.getInt(EXTRA_PAGE);
int pageSize = options.getInt(EXTRA_PAGE_SIZE);
if (page >= 0 && pageSize > 0) {
// Requesting the list of children through pagination.
@Nullable LibraryParams params = MediaUtils.convertToLibraryParams(librarySessionImpl.getContext(), options);
ListenableFuture<LibraryResult<ImmutableList<MediaItem>>> future = librarySessionImpl.onGetChildrenOnHandler(controller, parentId, page, pageSize, params);
sendLibraryResultWithMediaItemsWhenReady(result, future);
return;
}
// Cannot distinguish onLoadChildren() why it's called either by
// {@link MediaBrowserCompat#subscribe()} or
// {@link MediaBrowserServiceCompat#notifyChildrenChanged}.
} catch (BadParcelableException e) {
// pass-through.
}
}
// A MediaBrowserCompat called loadChildren with no pagination option.
ListenableFuture<LibraryResult<ImmutableList<MediaItem>>> future = librarySessionImpl.onGetChildrenOnHandler(controller, parentId, /* page= */
0, /* pageSize= */
Integer.MAX_VALUE, /* params= */
null);
sendLibraryResultWithMediaItemsWhenReady(result, future);
});
}
use of androidx.media3.session.MediaSession.ControllerInfo in project media by androidx.
the class MediaSessionService method onStartCommand.
/**
* Called when a component calls {@link android.content.Context#startService(Intent)}.
*
* <p>The default implementation handles the incoming media button events. In this case, the
* intent will have the action {@link Intent#ACTION_MEDIA_BUTTON}. Override this method if this
* service also needs to handle actions other than {@link Intent#ACTION_MEDIA_BUTTON}.
*/
@CallSuper
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
if (intent == null) {
return START_STICKY;
}
DefaultActionFactory actionFactory;
synchronized (lock) {
actionFactory = checkStateNotNull(this.actionFactory);
}
@Nullable Uri uri = intent.getData();
@Nullable MediaSession session = uri != null ? MediaSession.getSession(uri) : null;
if (actionFactory.isMediaAction(intent)) {
if (session == null) {
ControllerInfo controllerInfo = ControllerInfo.createLegacyControllerInfo();
session = onGetSession(controllerInfo);
if (session == null) {
return START_STICKY;
}
addSession(session);
}
@Nullable KeyEvent keyEvent = actionFactory.getKeyEvent(intent);
if (keyEvent != null) {
session.getSessionCompat().getController().dispatchMediaButtonEvent(keyEvent);
}
} else if (actionFactory.isCustomAction(intent)) {
@Nullable String customAction = actionFactory.getCustomAction(intent);
if (session != null && customAction != null) {
Bundle customExtras = actionFactory.getCustomActionExtras(intent);
getMediaNotificationManager().onCustomAction(session, customAction, customExtras);
}
}
return START_STICKY;
}
use of androidx.media3.session.MediaSession.ControllerInfo in project media by androidx.
the class MediaSessionStub method dispatchSessionTaskWithSessionCommandInternal.
private <T, K extends MediaSessionImpl> void dispatchSessionTaskWithSessionCommandInternal(IMediaController caller, int seq, @Nullable SessionCommand sessionCommand, @CommandCode int commandCode, SessionTask<T, K> task, PostSessionTask<T> postTask) {
long token = Binder.clearCallingIdentity();
try {
@SuppressWarnings({ "unchecked", "cast.unsafe" }) @Nullable K sessionImpl = (K) this.sessionImpl.get();
if (sessionImpl == null || sessionImpl.isReleased()) {
return;
}
@Nullable ControllerInfo controller = connectedControllersManager.getController(caller.asBinder());
if (controller == null) {
return;
}
postOrRun(sessionImpl.getApplicationHandler(), () -> {
if (!connectedControllersManager.isConnected(controller)) {
return;
}
if (sessionCommand != null) {
if (!connectedControllersManager.isSessionCommandAvailable(controller, sessionCommand)) {
sendSessionResult(controller, seq, new SessionResult(SessionResult.RESULT_ERROR_PERMISSION_DENIED));
return;
}
} else {
if (!connectedControllersManager.isSessionCommandAvailable(controller, commandCode)) {
sendSessionResult(controller, seq, new SessionResult(SessionResult.RESULT_ERROR_PERMISSION_DENIED));
return;
}
}
T result = task.run(sessionImpl, controller);
postTask.run(controller, seq, result);
});
} finally {
Binder.restoreCallingIdentity(token);
}
}
use of androidx.media3.session.MediaSession.ControllerInfo in project media by androidx.
the class MediaSessionStub method connect.
public void connect(IMediaController caller, int controllerVersion, String callingPackage, int pid, int uid, Bundle connectionHints) {
MediaSessionManager.RemoteUserInfo remoteUserInfo = new MediaSessionManager.RemoteUserInfo(callingPackage, pid, uid);
ControllerInfo controllerInfo = new ControllerInfo(remoteUserInfo, controllerVersion, sessionManager.isTrustedForMediaControl(remoteUserInfo), new Controller2Cb(caller), connectionHints);
@Nullable MediaSessionImpl sessionImpl = this.sessionImpl.get();
if (sessionImpl == null || sessionImpl.isReleased()) {
try {
caller.onDisconnected(/* seq= */
0);
} catch (RemoteException e) {
// Controller may be died prematurely.
// Not an issue because we'll ignore it anyway.
}
return;
}
pendingControllers.add(controllerInfo);
postOrRun(sessionImpl.getApplicationHandler(), () -> {
boolean connected = false;
try {
pendingControllers.remove(controllerInfo);
if (sessionImpl.isReleased()) {
return;
}
IBinder callbackBinder = checkStateNotNull((Controller2Cb) controllerInfo.getControllerCb()).getCallbackBinder();
MediaSession.ConnectionResult connectionResult = sessionImpl.onConnectOnHandler(controllerInfo);
// media keys to.
if (!connectionResult.isAccepted && !controllerInfo.isTrusted()) {
return;
}
if (!connectionResult.isAccepted) {
// For the accepted controller, send non-null allowed commands to keep connection.
connectionResult = MediaSession.ConnectionResult.accept(SessionCommands.EMPTY, Player.Commands.EMPTY);
}
SequencedFutureManager sequencedFutureManager;
if (connectedControllersManager.isConnected(controllerInfo)) {
Log.w(TAG, "Controller " + controllerInfo + " has sent connection" + " request multiple times");
}
connectedControllersManager.addController(callbackBinder, controllerInfo, connectionResult.availableSessionCommands, connectionResult.availablePlayerCommands);
sequencedFutureManager = checkStateNotNull(connectedControllersManager.getSequencedFutureManager(controllerInfo));
// If connection is accepted, notify the current state to the controller.
// It's needed because we cannot call synchronous calls between
// session/controller.
PlayerWrapper playerWrapper = sessionImpl.getPlayerWrapper();
PlayerInfo playerInfo = playerWrapper.createPlayerInfoForBundling();
ConnectionState state = new ConnectionState(MediaLibraryInfo.VERSION_INT, MediaSessionStub.this, sessionImpl.getSessionActivity(), connectionResult.availableSessionCommands, connectionResult.availablePlayerCommands, playerWrapper.getAvailableCommands(), sessionImpl.getToken().getExtras(), playerInfo);
// another thread.
if (sessionImpl.isReleased()) {
return;
}
try {
caller.onConnected(sequencedFutureManager.obtainNextSequenceNumber(), state.toBundle());
connected = true;
} catch (RemoteException e) {
// Controller may be died prematurely.
}
sessionImpl.onPostConnectOnHandler(controllerInfo);
} finally {
if (!connected) {
try {
caller.onDisconnected(/* seq= */
0);
} catch (RemoteException e) {
// Controller may be died prematurely.
// Not an issue because we'll ignore it anyway.
}
}
}
});
}
Aggregations