Chromium Code Reviews| Index: content/browser/media/android/media_session.h |
| diff --git a/content/browser/media/android/media_session.h b/content/browser/media/android/media_session.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..33e73cad8ce7f29fc0aad4aaea7e19af14fc255e |
| --- /dev/null |
| +++ b/content/browser/media/android/media_session.h |
| @@ -0,0 +1,124 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_H_ |
| +#define CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_H_ |
| + |
| +#include <jni.h> |
| + |
| +#include "base/android/scoped_java_ref.h" |
| +#include "base/id_map.h" |
| +#include "content/common/content_export.h" |
| +#include "content/public/browser/web_contents_observer.h" |
| +#include "content/public/browser/web_contents_user_data.h" |
| + |
| +namespace content { |
| + |
| +class MediaSessionBrowserTest; |
| +class MediaSessionObserver; |
| + |
| +// MediaSession manages the Android AudioFocus for a given WebContents. It is |
| +// requesting the audio focus, pausing when requested by the system and dropping |
| +// it on demand. |
| +// The audio focus can be of two types: Transient or Content. A Transient audio |
| +// focus will allow other players to duck instead of pausing and will be |
| +// declared as temporary to the system. A Content audio focus will not be |
| +// declared as temporary and will not allow other players to duck. If a given |
| +// WebContents can only have one audio focus at a time, it will be Content in |
| +// case of Transient and Content audio focus are both requested. |
| +// It is communicating to the Android system trough MediaSession.java via JNI. |
| +class CONTENT_EXPORT MediaSession |
| + : public content::WebContentsObserver, |
| + protected content::WebContentsUserData<MediaSession> { |
| + public: |
| + enum class Type { |
| + Content, |
| + Transient |
| + }; |
| + |
| + static bool RegisterMediaSession(JNIEnv* env); |
| + |
| + // Returns the MediaSession associated to this WebContents. Create one if none |
|
qinmin
2015/05/23 18:16:06
nit:s/Create/Creates/
mlamouri (slow - plz ping)
2015/05/23 20:05:27
Done.
|
| + // is currently available. |
| + static MediaSession* Get(WebContents* web_contents); |
| + |
| + ~MediaSession() override; |
| + |
| + // Adds the given player to the current media session. Returns whether the |
| + // player was successfully added. If it returns false, AddPlayer() should be |
| + // called again later. |
| + bool AddPlayer(MediaSessionObserver* observer, int player_id, Type type); |
| + |
| + // Removes the given player from the current media session. Abandon audio |
|
qinmin
2015/05/23 18:16:06
s/Abandon/Abandons/
mlamouri (slow - plz ping)
2015/05/23 20:05:27
Done.
|
| + // focus if that was the last player in the session. |
| + void RemovePlayer(MediaSessionObserver* observer, int player_id); |
| + |
| + // Removes all the players associated with |observer|. Abandon audio focus if |
|
qinmin
2015/05/23 18:16:06
ditto
mlamouri (slow - plz ping)
2015/05/23 20:05:27
Done.
|
| + // these were the last players in the session. |
| + void RemovePlayers(MediaSessionObserver* observer); |
| + |
| + // Called by Java trough JNI. |
| + void OnSuspend(JNIEnv* env, jobject obj); |
| + void OnResume(JNIEnv* env, jobject obj); |
| + |
| + protected: |
| + friend class content::MediaSessionBrowserTest; |
| + |
| + // Resets the |j_media_session_| ref to prevent calling the Java backend |
| + // during content_browsertests. |
| + void ResetJavaRefForTest(); |
| + |
| + bool has_audio_focus_for_test() const; |
| + Type audio_focus_type_for_test() const; |
| + |
| + void OnSuspend(); |
| + void OnResume(); |
| + |
| + private: |
| + friend class content::WebContentsUserData<MediaSession>; |
| + |
| + // Representation of a player for the MediaSession. |
| + struct PlayerIdentifier { |
| + PlayerIdentifier(MediaSessionObserver* observer, int player_id); |
| + PlayerIdentifier(const PlayerIdentifier&) = default; |
| + |
| + void operator=(const PlayerIdentifier&) = delete; |
| + bool operator==(const PlayerIdentifier& player_identifier) const; |
| + |
| + // Hash operator for base::hash_map<>. |
| + struct Hash { |
| + size_t operator()(const PlayerIdentifier& player_identifier) const; |
| + }; |
| + |
| + MediaSessionObserver* observer; |
| + int player_id; |
| + }; |
| + using PlayersMap = base::hash_set<PlayerIdentifier, PlayerIdentifier::Hash>; |
| + |
| + explicit MediaSession(WebContents* web_contents); |
| + |
| + // Setup the JNI. |
| + void Initialize(); |
| + |
| + // Requests audio focus to Android using |j_media_session_|. |
| + // Returns whether the request was granted. If |j_media_session_| is null, it |
| + // will always return true. |
| + bool RequestSystemAudioFocus(Type type); |
| + |
| + // To be called after a call to AbandonAudioFocus() in order to call the Java |
| + // MediaSession if the audio focus really need to be abandoned. |
| + void AbandonSystemAudioFocusIfNeeded(); |
| + |
| + base::android::ScopedJavaGlobalRef<jobject> j_media_session_; |
| + PlayersMap players_; |
| + |
| + bool has_audio_focus_; |
| + Type audio_focus_type_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(MediaSession); |
| +}; |
| + |
| +} // namespace content |
| + |
| +#endif // CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_H_ |