Search in sources :

Example 11 with ControllerInfo

use of androidx.media3.session.MediaSession.ControllerInfo in project media by androidx.

the class MediaLibrarySessionImpl method onSubscribeOnHandler.

public ListenableFuture<LibraryResult<Void>> onSubscribeOnHandler(ControllerInfo browser, String parentId, @Nullable LibraryParams params) {
    ControllerCb controller = checkStateNotNull(browser.getControllerCb());
    synchronized (lock) {
        @Nullable Set<String> subscription = subscriptions.get(controller);
        if (subscription == null) {
            subscription = new HashSet<>();
            subscriptions.put(controller, subscription);
        }
        subscription.add(parentId);
    }
    // Call callbacks after adding it to the subscription list because library session may want
    // to call notifyChildrenChanged() in the callback.
    // 
    // onSubscribe is defined to return a non-null result but it's implemented by applications,
    // so we explicitly null-check the result to fail early if an app accidentally returns null.
    ListenableFuture<LibraryResult<Void>> future = checkNotNull(callback.onSubscribe(instance, browser, parentId, params), "onSubscribe must return non-null future");
    // When error happens, remove from the subscription list.
    future.addListener(() -> {
        @Nullable LibraryResult<Void> result = tryGetFutureResult(future);
        if (result == null || result.resultCode != RESULT_SUCCESS) {
            removeSubscription(controller, parentId);
        }
    }, MoreExecutors.directExecutor());
    return future;
}
Also used : ControllerCb(androidx.media3.session.MediaSession.ControllerCb) Nullable(androidx.annotation.Nullable)

Example 12 with ControllerInfo

use of androidx.media3.session.MediaSession.ControllerInfo in project media by androidx.

the class MediaSessionImpl method dispatchRemoteControllerTask.

private ListenableFuture<SessionResult> dispatchRemoteControllerTask(ControllerInfo controller, RemoteControllerTask task) {
    try {
        ListenableFuture<SessionResult> future;
        int seq;
        @Nullable SequencedFutureManager manager = sessionStub.getConnectedControllersManager().getSequencedFutureManager(controller);
        if (manager != null) {
            future = manager.createSequencedFuture(RESULT_WHEN_CLOSED);
            seq = ((SequencedFuture<SessionResult>) future).getSequenceNumber();
        } else {
            if (!isConnected(controller)) {
                return Futures.immediateFuture(new SessionResult(RESULT_ERROR_SESSION_DISCONNECTED));
            }
            // 0 is OK for legacy controllers, because they didn't have sequence numbers.
            seq = 0;
            // Tell that operation is successful, although we don't know the actual result.
            future = Futures.immediateFuture(new SessionResult(SessionResult.RESULT_SUCCESS));
        }
        ControllerCb cb = controller.getControllerCb();
        if (cb != null) {
            task.run(cb, seq);
        }
        return future;
    } catch (DeadObjectException e) {
        onDeadObjectException(controller, e);
        return Futures.immediateFuture(new SessionResult(RESULT_ERROR_SESSION_DISCONNECTED));
    } catch (RemoteException e) {
        // Currently it's TransactionTooLargeException or DeadSystemException.
        // We'd better to leave log for those cases because
        // - TransactionTooLargeException means that we may need to fix our code.
        // (e.g. add pagination or special way to deliver Bitmap)
        // - DeadSystemException means that errors around it can be ignored.
        Log.w(TAG, "Exception in " + controller.toString(), e);
    }
    return Futures.immediateFuture(new SessionResult(RESULT_ERROR_UNKNOWN));
}
Also used : ControllerCb(androidx.media3.session.MediaSession.ControllerCb) DeadObjectException(android.os.DeadObjectException) RemoteException(android.os.RemoteException) Nullable(androidx.annotation.Nullable)

Example 13 with ControllerInfo

use of androidx.media3.session.MediaSession.ControllerInfo in project media by androidx.

the class MediaSessionLegacyStub method tryGetController.

@Nullable
private ControllerInfo tryGetController(RemoteUserInfo remoteUserInfo) {
    @Nullable ControllerInfo controller = connectedControllersManager.getController(remoteUserInfo);
    if (controller == null) {
        // Try connect.
        ControllerCb controllerCb = new ControllerLegacyCb(remoteUserInfo);
        controller = new ControllerInfo(remoteUserInfo, /* controllerVersion= */
        0, sessionManager.isTrustedForMediaControl(remoteUserInfo), controllerCb, /* connectionHints= */
        Bundle.EMPTY);
        MediaSession.ConnectionResult connectionResult = sessionImpl.onConnectOnHandler(controller);
        if (!connectionResult.isAccepted) {
            try {
                controllerCb.onDisconnected(/* seq= */
                0);
            } catch (RemoteException e) {
            // Controller may have died prematurely.
            }
            return null;
        }
        connectedControllersManager.addController(controller.getRemoteUserInfo(), controller, connectionResult.availableSessionCommands, connectionResult.availablePlayerCommands);
    }
    // Reset disconnect timeout.
    connectionTimeoutHandler.disconnectControllerAfterTimeout(controller, connectionTimeoutMs);
    return controller;
}
Also used : ControllerCb(androidx.media3.session.MediaSession.ControllerCb) RemoteException(android.os.RemoteException) Nullable(androidx.annotation.Nullable) ControllerInfo(androidx.media3.session.MediaSession.ControllerInfo) Nullable(androidx.annotation.Nullable)

Example 14 with ControllerInfo

use of androidx.media3.session.MediaSession.ControllerInfo in project media by androidx.

the class MediaSessionLegacyStub method dispatchSessionTaskWithPlayerCommand.

private void dispatchSessionTaskWithPlayerCommand(@Player.Command int command, SessionTask task, @Nullable RemoteUserInfo remoteUserInfo) {
    if (sessionImpl.isReleased()) {
        return;
    }
    if (remoteUserInfo == null) {
        Log.d(TAG, "RemoteUserInfo is null, ignoring command=" + command);
        return;
    }
    postOrRun(sessionImpl.getApplicationHandler(), () -> {
        if (sessionImpl.isReleased()) {
            return;
        }
        if (!sessionCompat.isActive()) {
            Log.w(TAG, "Ignore incoming player command before initialization. command=" + command + ", pid=" + remoteUserInfo.getPid());
            return;
        }
        @Nullable ControllerInfo controller = tryGetController(remoteUserInfo);
        if (controller == null) {
            // Failed to get controller since connection was rejected.
            return;
        }
        if (!connectedControllersManager.isPlayerCommandAvailable(controller, command)) {
            return;
        }
        int resultCode = sessionImpl.onPlayerCommandRequestOnHandler(controller, command);
        if (resultCode != RESULT_SUCCESS) {
            // Don't run rejected command.
            return;
        }
        try {
            task.run(controller);
        } catch (RemoteException e) {
            // Currently it's TransactionTooLargeException or DeadSystemException.
            // We'd better to leave log for those cases because
            // - TransactionTooLargeException means that we may need to fix our code.
            // (e.g. add pagination or special way to deliver Bitmap)
            // - DeadSystemException means that errors around it can be ignored.
            Log.w(TAG, "Exception in " + controller, e);
        }
    });
}
Also used : RemoteException(android.os.RemoteException) Nullable(androidx.annotation.Nullable) ControllerInfo(androidx.media3.session.MediaSession.ControllerInfo)

Example 15 with ControllerInfo

use of androidx.media3.session.MediaSession.ControllerInfo in project media by androidx.

the class ConnectedControllersManager method getSequencedFutureManager.

/**
 * Gets the sequenced future manager.
 *
 * @param controllerKey key
 * @return sequenced future manager. Can be {@code null} if the controller was null or
 *     disconnected.
 */
@Nullable
public SequencedFutureManager getSequencedFutureManager(T controllerKey) {
    @Nullable ConnectedControllerRecord<T> info;
    synchronized (lock) {
        @Nullable ControllerInfo controllerInfo = getController(controllerKey);
        info = controllerInfo != null ? controllerRecords.get(controllerInfo) : null;
    }
    return info != null ? info.sequencedFutureManager : null;
}
Also used : Nullable(androidx.annotation.Nullable) ControllerInfo(androidx.media3.session.MediaSession.ControllerInfo) Nullable(androidx.annotation.Nullable)

Aggregations

ControllerInfo (androidx.media3.session.MediaSession.ControllerInfo)44 Test (org.junit.Test)27 CountDownLatch (java.util.concurrent.CountDownLatch)26 Nullable (androidx.annotation.Nullable)22 LargeTest (androidx.test.filters.LargeTest)22 Bundle (android.os.Bundle)13 SessionCallback (androidx.media3.session.MediaSession.SessionCallback)12 Uri (android.net.Uri)8 RemoteException (android.os.RemoteException)7 LibraryParams (androidx.media3.session.MediaLibraryService.LibraryParams)7 AtomicReference (java.util.concurrent.atomic.AtomicReference)7 MediaItem (androidx.media3.common.MediaItem)6 ControllerCb (androidx.media3.session.MediaSession.ControllerCb)4 MediumTest (androidx.test.filters.MediumTest)4 DeadObjectException (android.os.DeadObjectException)3 PlaybackParameters (androidx.media3.common.PlaybackParameters)3 Rating (androidx.media3.common.Rating)3 DeviceInfo (androidx.media3.common.DeviceInfo)2 PlaybackException (androidx.media3.common.PlaybackException)2 COMMAND_SEEK_BACK (androidx.media3.common.Player.COMMAND_SEEK_BACK)2