| # Controlling Media Playback |
| |
| A media session is a single abstract representation of a single playing source |
| in the Chrome ecosystem. This could be something like an ARC++ app or a browser |
| tab. |
| |
| Sessions request audio focus from the media session service and the service |
| maintains a connection to each media session on the platform. This can be used |
| to receive metadata and control media playback in a unified way on Chrome. |
| |
| # Audio Focus |
| |
| When audio focus is enabled all the different media sessions will request audio |
| focus. A media session can request three different types of audio focus: |
| |
| * Gain - If a gain session acquires focus then all other sessions will stop |
| playing and will not be resumed even when the session is destroyed. In most |
| cases, this is the type that will be used. |
| * Gain Transient - If a transient session acquires focus then all other sessions |
| will stop playing, but will be resumed when that session is destroyed. This is |
| used for temporary playbacks. |
| * Gain Transient May Duck - If a ducking session acquires focus then all other |
| sessions will continue playing but at a reduced volume. When that session is |
| destroyed it will continue at the previous volume. This is used for short |
| sounds e.g. notifications. |
| |
| Each WebContents (tab) in Chrome has it's own media session and will request |
| Gain audio focus in most cases. If the media is only a few seconds then it will |
| request the ducking focus type. |
| |
| In ARC++ each app can make audio focus requests using the Android Audio Manager |
| API. Each of these requests is a media session in Chrome and can be any one of |
| the three above audio focus types. |
| |
| To reduce the impact of single session audio focus we currently have grouping |
| enabled. By default, all media sessions will have a unique "group id". All |
| browser media session have the same group id. When a session acquires focus it |
| will not pause any other session with the same group id. Likewise, if playback |
| is resumed automatically all sessions with the same group id will be resumed. |
| This allows all the browser tabs to share audio focus and play concurrently, but |
| still behave as individual media sessions. Ducking is unaffected by group ids. |
| |
| # Active Media Session |
| |
| The active media session is the session that would be controlled if there is a |
| user action (e.g. pressing the play/pause key on a keyboard). Part of the state |
| that the media session exposes is `is_controllable`. If this boolean is true |
| then the media session can be controlled by the user. The active media session |
| will be the top most controllable media session. |
| |
| # Audio Focus Observer |
| |
| The media session service can be accessed via Mojo and currently lives in the |
| browser process. Clients can implement [AudioFocusObserver](https://cs.chromium.org/chromium/src/services/media_session/public/mojom/media_session.mojom) |
| and add themselves as an observer using the [AudioFocusManager](https://cs.chromium.org/chromium/src/services/media_session/public/mojom/media_session.mojom) |
| mojo API. The observer will then receive notifications when the active media |
| session changes. This can be used to determine whether there is any current |
| media playback. |
| |
| # Media Controller Manager |
| |
| The media session service also exposes a [MediaControllerManager](https://cs.chromium.org/chromium/src/services/media_session/public/mojom/media_controller.mojom) |
| mojo API. This can be used to create a [MediaController](https://cs.chromium.org/chromium/src/services/media_session/public/mojom/media_controller.mojom) |
| instance. These can be used to control and observe a media session. This can |
| be an individual media session or the active media session. |
| |
| If the controller is created using `CreateActiveMediaController` then it will |
| follow the active media session. This means you do not need to create a new |
| media controller if the active media session changes. |
| |
| **There is also a MediaSession mojo API. This is used for session / service |
| communication and should not be used for control.**. |
| |
| # Media Session Observer |
| |
| There is also a [MediaSessionObserver](https://cs.chromium.org/chromium/src/services/media_session/public/mojom/media_session.mojom) |
| mojo API that clients can implement. They can then add themselves as an observer |
| using the `AddObserver` call on the `MediaController` api. When an observer is |
| added it will be flushed with all the latest information from the currently |
| active media session. |
| |
| Again, this will automatically route to the active media session. If that |
| changes then we will flush all methods on the observer with the information from |
| the new active media session. |
| |
| # Testing |
| |
| There is a [MockMediaSession](https://cs.chromium.org/chromium/src/services/media_session/public/cpp/test/mock_media_session.h) |
| C++ class that can be used for simulating a media session in unit tests. The |
| [//services/media_session/public/cpp/test](https://cs.chromium.org/chromium/src/services/media_session/public/cpp/test/) |
| directory also contains a number of other useful test utilities. |
| |
| # Current Media Session service integrations |
| |
| The following clients are integrated with the media session service and expose |
| a media session and request audio focus: |
| |
| * content::WebContents |
| * ARC++ apps (requires Android Pie) |
| * Assistant |
| |
| Questions? - Feel free to reach out to beccahughes@chromium.org. |