From 6042bec18a4b30449a20d1e858bac799cc6d18c3 Mon Sep 17 00:00:00 2001 From: bachinger Date: Thu, 2 Mar 2023 12:36:33 +0000 Subject: [PATCH] Fix some JavaDoc in the Media3 session module #minor-release PiperOrigin-RevId: 513501046 --- .../androidx/media3/session/MediaSession.java | 83 +++++++++++-------- .../media3/session/MediaSessionImpl.java | 2 +- .../media3/session/MediaSessionService.java | 32 +++---- 3 files changed, 65 insertions(+), 52 deletions(-) diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java index 7fea6a0c81..d13592099b 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java @@ -68,14 +68,16 @@ import java.util.List; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** - * A session that allows a media app to expose its transport controls and playback information in a - * process to other processes including the Android framework and other apps. The common use cases - * are as follows: + * A session that allows a media app to expose its player functionality, information of the playlist + * and the media item currently being played to other processes including the Android framework and + * other apps. The common use cases are as follows: * * * *

A session should be created when an app wants to publish media playback information or handle @@ -83,9 +85,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * sessions can be created to provide finer grain controls of media. See Supporting Multiple Sessions for details. * - *

If you want to support background playback, {@link MediaSessionService} is preferred. With the - * service, your playback can be revived even after playback is finished. See {@link - * MediaSessionService} for details. + *

If an app wants to support playback when in the background, using a {@link + * MediaSessionService} is the preferred approach. See {@link MediaSessionService} for details. * *

Topics covered here: * @@ -104,7 +105,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * #getToken() session token} to other processes to allow them to create a {@link MediaController} * to interact with the session. * - *

When a session receives transport control commands, the session sends the commands directly to + *

When a session receives playback commands, the session calls corresponding methods directly on * the underlying player set by {@link Builder#Builder(Context, Player)} or {@link * #setPlayer(Player)}. * @@ -114,15 +115,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * *

Threading Model

* - *

The instances are thread safe, but should be used on the thread with a looper. + *

The instances are thread safe, but must be used on a thread with a looper. * - *

{@link Callback} methods will be called from the application thread associated with the {@link + *

{@link Callback} methods will be called on the application thread associated with the {@link * Player#getApplicationLooper() application looper} of the underlying player. When a new player is - * set by {@link #setPlayer}, the player should use the same application looper as the previous one. + * set by {@link #setPlayer}, the player must use the same application looper as the previous one. * - *

The session listens to events from the underlying player via {@link Player.Listener} and - * expects the callback methods to be called from the application thread. If the player violates the - * threading contract, {@link IllegalStateException} will be thrown. + *

The session listens to player events via {@link Player.Listener} and expects the callback + * methods to be called on the application thread. If the player violates the threading contract, an + * {@link IllegalStateException} will be thrown. * *

Media Key Events Mapping

* @@ -161,7 +162,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * *
  • {@link Player#play()} otherwise
  • * - *
  • For a double tap, {@link Player#seekToNext()}
  • + *
  • In case the media key events are coming from another package ID than the package ID of + * the media app (events coming for instance from Bluetooth), a double tap generating two + * key events within a brief amount of time, is converted to {@link Player#seekToNext()} + *
  • * * * @@ -194,16 +198,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * media or remote playback, since the audio focus policy * recommends not playing multiple audio content at the same time. Also, keep in mind that multiple - * media sessions would make Android Auto and Bluetooth device with display to show your apps + * media sessions would make Android Auto and Bluetooth devices with display to show your app * multiple times, because they list up media sessions, not media apps. * *

    Backward Compatibility with Legacy Session APIs

    * - *

    An active {@link MediaSessionCompat} is internally created with the session for the backward - * compatibility. It's used to handle incoming connection and commands from {@link - * MediaControllerCompat}, and helps to utilize existing APIs that are built with legacy media - * session APIs. Use {@link #getSessionCompatToken} to get the legacy token of {@link - * MediaSessionCompat}. + *

    An active {@link MediaSessionCompat} is internally created with the session for backwards + * compatibility. It's used to handle incoming connections and commands from {@link + * MediaControllerCompat} instances, and helps to utilize existing APIs that are built with legacy + * media session APIs. * *

    Backward Compatibility with Legacy Controller APIs

    * @@ -212,10 +215,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * {@linkplain MediaControllerCompat AndroidX controller compat}. However, {@link ControllerInfo} * may not be precise for legacy controllers. See {@link ControllerInfo} for the details. * - *

    Unknown package name nor UID doesn't mean that you should disallow connection nor commands. - * For SDK levels where such issues happen, session tokens could only be obtained by trusted - * controllers (e.g. Bluetooth, Auto, ...), so it may be better for you to allow them as you did - * with legacy sessions. + *

    Neither an unknown package name nor an unknown UID mean that you should disallow a connection + * or commands per se. For SDK levels where such issues happen, session tokens can only be obtained + * by trusted controllers (e.g. Bluetooth, Auto, ...). This means only trusted controllers can + * connect and an app can accept such controllers in the same way as with legacy sessions. */ public class MediaSession { @@ -243,7 +246,7 @@ public class MediaSession { * Creates a builder for {@link MediaSession}. * * @param context The context. - * @param player The underlying player to perform playback and handle transport controls. + * @param player The underlying player to perform playback and handle player commands. * @throws IllegalArgumentException if {@link Player#canAdvertiseSession()} returns false. */ public Builder(Context context, Player player) { @@ -254,13 +257,13 @@ public class MediaSession { * Sets a {@link PendingIntent} to launch an {@link android.app.Activity} for the {@link * MediaSession}. This can be used as a quick link to an ongoing media screen. * - *

    A client can use this pending intent to start an activity belonging to this session. When - * this pending intent is for instance included in the notification {@linkplain - * NotificationCompat.Builder#setContentIntent(PendingIntent) as the content intent}, tapping - * the notification will open this activity. - * - *

    See 'Start an - * Activity from a Notification' also. + *

    A client can use this pending intent to start an activity belonging to this session. On + * API levels below 33 the pending intent can be used {@linkplain + * NotificationCompat.Builder#setContentIntent(PendingIntent) as the content intent}. Tapping + * the notification will then send that pending intent and open the activity (see 'Start an Activity from + * a Notification'). For API levels starting with 33, the media notification reads the + * pending intent directly from the session. * * @param pendingIntent The pending intent. * @return The builder to allow chaining. @@ -291,6 +294,13 @@ public class MediaSession { * Sets a callback for the {@link MediaSession} to handle incoming requests from {link * MediaController}. * + *

    Apps that want to allow controllers to {@linkplain MediaController#setMediaItems(List) + * set} or {@linkplain MediaController#addMediaItems(List) add} media items to the playlist, + * must use a callback and override its {@link + * MediaSession.Callback#onSetMediaItems(MediaSession, ControllerInfo, List, int, long)} or + * {@link MediaSession.Callback#onSetMediaItems(MediaSession, ControllerInfo, List, int, long)} + * methods. + * * @param callback The callback. * @return The builder to allow chaining. */ @@ -372,7 +382,8 @@ public class MediaSession { * @param remoteUserInfo The remote user info. * @param trusted {@code true} if trusted, {@code false} otherwise. * @param cb ControllerCb. Can be {@code null} only when a MediaBrowserCompat connects to - * MediaSessionService and ControllerInfo is needed for {@code SessionCallback#onConnect()}. + * MediaSessionService and ControllerInfo is needed for {@link + * MediaSession.Callback#onConnect(MediaSession, ControllerInfo)}. * @param connectionHints A session-specific argument sent from the controller for the * connection. The contents of this bundle may affect the connection result. */ diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java index 064e5239a2..ba76484f43 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java @@ -448,7 +448,7 @@ import org.checkerframework.checker.initialization.qual.Initialized; public MediaSession.ConnectionResult onConnectOnHandler(ControllerInfo controller) { return checkNotNull( - callback.onConnect(instance, controller), "onConntext must return non-null future"); + callback.onConnect(instance, controller), "onConnect must return non-null future"); } public void onPostConnectOnHandler(ControllerInfo controller) { diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java index a93a6cf8a7..30b76997f5 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java @@ -57,26 +57,27 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * Superclass to be extended by services hosting {@link MediaSession media sessions}. * - *

    It's highly recommended for an app to use this class if they want to keep media playback in - * the background. The service allows other apps to know that your app supports {@link MediaSession} - * even when your app isn't running. For example, a user voice command may start your app to play - * media. + *

    It's highly recommended for an app to use this class if media playback should continue while + * in the background. The service allows other apps to know that your app supports {@link + * MediaSession} even when your app isn't running. This way, a user voice command may be able start + * your app to play media. * *

    To extend this class, declare the intent filter in your {@code AndroidManifest.xml}: * *

    {@code
      * 
    + *   android:foregroundServiceType="mediaPlayback"
    + *   android:exported="true">
      *   
      *     
      *   
      * 
      * }
    * - *

    You may also declare {@code android.media.browse.MediaBrowserService} for compatibility with - * {@link android.support.v4.media.MediaBrowserCompat}. This service can handle the case - * automatically. + *

    You may also declare the action {@code android.media.browse.MediaBrowserService} for + * compatibility with {@link android.support.v4.media.MediaBrowserCompat}. This service can handle + * the case automatically. * *

    It's recommended for an app to have a single service declared in the manifest. Otherwise, your * app might be shown twice in the list of the controller apps, or another app might fail to pick @@ -93,10 +94,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; *

    Service Lifecycle

    * *

    A media session service is a bound service and its foreground - * service type must include mediaPlayback. When a {@link MediaController} is created - * for the service, the controller binds to the service. {@link #onGetSession(ControllerInfo)} will - * be called from {@link #onBind(Intent)}. + * href="https://developer.android.com/guide/topics/manifest/service-element#foregroundservicetype"> + * foreground service type must include mediaPlayback. When a {@link MediaController} + * is created for the service, the controller binds to the service. {@link + * #onGetSession(ControllerInfo)} will be called from {@link #onBind(Intent)}. * *

    After binding, the session's {@link MediaSession.Callback#onConnect(MediaSession, * MediaSession.ControllerInfo)} will be called to accept or reject the connection request from the @@ -115,8 +116,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; * #onUpdateNotification(MediaSession)}. In this case, you must also start or stop the service from * the foreground, when playback starts or stops respectively. * - *

    The service will be destroyed when all sessions are closed, or no controller is binding to the - * service while the service is in the background. + *

    The service will be destroyed when all sessions are {@linkplain MediaController#release() + * released}, or no controller is binding to the service while the service is in the background. * *

    Supporting Multiple Sessions

    * @@ -247,7 +248,8 @@ public abstract class MediaSessionService extends Service { * Adds a {@link MediaSession} to this service. This is not necessary for most media apps. See Supporting Multiple Sessions for details. * - *

    The added session will be removed automatically when it's closed. + *

    The added session will be removed automatically {@linkplain MediaSession#release() when the + * session is released}. * * @param session A session to be added. * @see #removeSession(MediaSession)