Convert MediaWebContentsObsever to be the client of WakeLock mojo interface.
Convert MediaWebContentsObsever to be the client of WakeLock mojo interface
instead of direct client of PowerSaveBlocker.
TEST = Play audio or video and check the OS level wake locks.
On macOS: pmset -g assertions
On Windows: powercfg /requests.
BUG=689413
TBR=<jam@chromium.org>
Review-Url: https://codereview.chromium.org/2846813002
Cr-Commit-Position: refs/heads/master@{#470889}
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc
index 2098fac..96d29bd81 100644
--- a/content/browser/media/media_web_contents_observer.cc
+++ b/content/browser/media/media_web_contents_observer.cc
@@ -13,8 +13,9 @@
#include "content/common/media/media_player_delegate_messages.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
-#include "device/power_save_blocker/power_save_blocker.h"
+#include "device/wake_lock/public/interfaces/wake_lock_context.mojom.h"
#include "ipc/ipc_message_macros.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
namespace content {
@@ -29,6 +30,8 @@
MediaWebContentsObserver::MediaWebContentsObserver(WebContents* web_contents)
: WebContentsObserver(web_contents),
+ has_audio_wake_lock_for_testing_(false),
+ has_video_wake_lock_for_testing_(false),
session_controllers_manager_(this) {}
MediaWebContentsObserver::~MediaWebContentsObserver() = default;
@@ -39,7 +42,7 @@
void MediaWebContentsObserver::RenderFrameDeleted(
RenderFrameHost* render_frame_host) {
- ClearPowerSaveBlockers(render_frame_host);
+ ClearWakeLocks(render_frame_host);
session_controllers_manager_.RenderFrameDeleted(render_frame_host);
if (fullscreen_player_ && fullscreen_player_->first == render_frame_host)
@@ -50,12 +53,10 @@
AudioStreamMonitor* audio_stream_monitor =
static_cast<WebContentsImpl*>(web_contents())->audio_stream_monitor();
- if (audio_stream_monitor->WasRecentlyAudible()) {
- if (!audio_power_save_blocker_)
- CreateAudioPowerSaveBlocker();
- } else {
- audio_power_save_blocker_.reset();
- }
+ if (audio_stream_monitor->WasRecentlyAudible())
+ LockAudio();
+ else
+ CancelAudioLock();
GetAudibleMetrics()->UpdateAudibleWebContentsState(
web_contents(), audio_stream_monitor->IsCurrentlyAudible());
@@ -95,16 +96,18 @@
}
void MediaWebContentsObserver::WasShown() {
- // Restore power save blocker if there are active video players running.
- if (!active_video_players_.empty() && !video_power_save_blocker_)
- CreateVideoPowerSaveBlocker();
+ // Restore wake lock if there are active video players running.
+ if (!active_video_players_.empty())
+ LockVideo();
}
void MediaWebContentsObserver::WasHidden() {
// If there are entities capturing screenshots or video (e.g., mirroring),
- // don't release the power save blocker.
- if (!web_contents()->GetCapturerCount())
- video_power_save_blocker_.reset();
+ // don't release the wake lock.
+ if (!web_contents()->GetCapturerCount()) {
+ GetVideoWakeLock()->CancelWakeLock();
+ has_video_wake_lock_for_testing_ = false;
+ }
}
void MediaWebContentsObserver::RequestPersistentVideo(bool value) {
@@ -132,7 +135,7 @@
RemoveMediaPlayerEntry(player_id, &active_audio_players_);
const bool removed_video =
RemoveMediaPlayerEntry(player_id, &active_video_players_);
- MaybeReleasePowerSaveBlockers();
+ MaybeCancelVideoLock();
if (removed_audio || removed_video) {
// Notify observers the player has been "paused".
@@ -167,11 +170,9 @@
if (has_video) {
AddMediaPlayerEntry(id, &active_video_players_);
- // If we're not hidden and have just created a player, create a blocker.
- if (!video_power_save_blocker_ &&
- !static_cast<WebContentsImpl*>(web_contents())->IsHidden()) {
- CreateVideoPowerSaveBlocker();
- }
+ // If we're not hidden and have just created a player, create a wakelock.
+ if (!static_cast<WebContentsImpl*>(web_contents())->IsHidden())
+ LockVideo();
}
if (!session_controllers_manager_.RequestPlay(
@@ -201,7 +202,7 @@
fullscreen_player_ = id;
}
-void MediaWebContentsObserver::ClearPowerSaveBlockers(
+void MediaWebContentsObserver::ClearWakeLocks(
RenderFrameHost* render_frame_host) {
std::set<MediaPlayerId> removed_players;
RemoveAllMediaPlayerEntries(render_frame_host, &active_video_players_,
@@ -209,7 +210,7 @@
std::set<MediaPlayerId> video_players(removed_players);
RemoveAllMediaPlayerEntries(render_frame_host, &active_audio_players_,
&removed_players);
- MaybeReleasePowerSaveBlockers();
+ MaybeCancelVideoLock();
// Notify all observers the player has been "paused".
WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents());
@@ -221,35 +222,65 @@
}
}
-void MediaWebContentsObserver::CreateAudioPowerSaveBlocker() {
- DCHECK(!audio_power_save_blocker_);
- audio_power_save_blocker_.reset(new device::PowerSaveBlocker(
- device::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
- device::PowerSaveBlocker::kReasonAudioPlayback, "Playing audio",
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)));
-}
-
-void MediaWebContentsObserver::CreateVideoPowerSaveBlocker() {
- DCHECK(!video_power_save_blocker_);
- DCHECK(!active_video_players_.empty());
- video_power_save_blocker_.reset(new device::PowerSaveBlocker(
- device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
- device::PowerSaveBlocker::kReasonVideoPlayback, "Playing video",
- BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
- BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)));
-#if defined(OS_ANDROID)
- if (web_contents()->GetNativeView()) {
- video_power_save_blocker_.get()->InitDisplaySleepBlocker(
- web_contents()->GetNativeView());
+device::mojom::WakeLockService* MediaWebContentsObserver::GetAudioWakeLock() {
+ // Here is a lazy binding, and will not reconnect after connection error.
+ if (!audio_wake_lock_) {
+ device::mojom::WakeLockServiceRequest request =
+ mojo::MakeRequest(&audio_wake_lock_);
+ device::mojom::WakeLockContext* wake_lock_context =
+ web_contents()->GetWakeLockContext();
+ if (wake_lock_context) {
+ wake_lock_context->GetWakeLock(
+ device::mojom::WakeLockType::PreventAppSuspension,
+ device::mojom::WakeLockReason::ReasonAudioPlayback, "Playing audio",
+ std::move(request));
+ }
}
-#endif
+ return audio_wake_lock_.get();
}
-void MediaWebContentsObserver::MaybeReleasePowerSaveBlockers() {
- // If there are no more video players, clear the video power save blocker.
+device::mojom::WakeLockService* MediaWebContentsObserver::GetVideoWakeLock() {
+ // Here is a lazy binding, and will not reconnect after connection error.
+ if (!video_wake_lock_) {
+ device::mojom::WakeLockServiceRequest request =
+ mojo::MakeRequest(&video_wake_lock_);
+ device::mojom::WakeLockContext* wake_lock_context =
+ web_contents()->GetWakeLockContext();
+ if (wake_lock_context) {
+ wake_lock_context->GetWakeLock(
+ device::mojom::WakeLockType::PreventDisplaySleep,
+ device::mojom::WakeLockReason::ReasonVideoPlayback, "Playing video",
+ std::move(request));
+ }
+ }
+ return video_wake_lock_.get();
+}
+
+void MediaWebContentsObserver::LockAudio() {
+ GetAudioWakeLock()->RequestWakeLock();
+ has_audio_wake_lock_for_testing_ = true;
+}
+
+void MediaWebContentsObserver::CancelAudioLock() {
+ GetAudioWakeLock()->CancelWakeLock();
+ has_audio_wake_lock_for_testing_ = false;
+}
+
+void MediaWebContentsObserver::LockVideo() {
+ DCHECK(!active_video_players_.empty());
+ GetVideoWakeLock()->RequestWakeLock();
+ has_video_wake_lock_for_testing_ = true;
+}
+
+void MediaWebContentsObserver::CancelVideoLock() {
+ GetVideoWakeLock()->CancelWakeLock();
+ has_video_wake_lock_for_testing_ = false;
+}
+
+void MediaWebContentsObserver::MaybeCancelVideoLock() {
+ // If there are no more video players, cancel the video wake lock.
if (active_video_players_.empty())
- video_power_save_blocker_.reset();
+ CancelVideoLock();
}
void MediaWebContentsObserver::AddMediaPlayerEntry(
diff --git a/content/browser/media/media_web_contents_observer.h b/content/browser/media/media_web_contents_observer.h
index 3a2a0d3a..0e61ecff 100644
--- a/content/browser/media/media_web_contents_observer.h
+++ b/content/browser/media/media_web_contents_observer.h
@@ -15,15 +15,12 @@
#include "content/browser/media/session/media_session_controllers_manager.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
+#include "device/wake_lock/public/interfaces/wake_lock_service.mojom.h"
#if defined(OS_ANDROID)
#include "ui/android/view_android.h"
#endif // OS_ANDROID
-namespace device {
-class PowerSaveBlocker;
-} // namespace device
-
namespace media {
enum class MediaContentType;
} // namespace media
@@ -63,12 +60,12 @@
// fullscreening video element to the same place.
void RequestPersistentVideo(bool value);
- bool has_audio_power_save_blocker_for_testing() const {
- return !!audio_power_save_blocker_;
+ bool has_audio_wake_lock_for_testing() const {
+ return has_audio_wake_lock_for_testing_;
}
- bool has_video_power_save_blocker_for_testing() const {
- return !!video_power_save_blocker_;
+ bool has_video_wake_lock_for_testing() const {
+ return has_video_wake_lock_for_testing_;
}
protected:
@@ -91,17 +88,18 @@
int delegate_id,
bool is_fullscreen);
- // Clear |render_frame_host|'s tracking entry for its power save blockers.
- void ClearPowerSaveBlockers(RenderFrameHost* render_frame_host);
+ // Clear |render_frame_host|'s tracking entry for its WakeLocks.
+ void ClearWakeLocks(RenderFrameHost* render_frame_host);
- // Creates an audio or video power save blocker respectively.
- void CreateAudioPowerSaveBlocker();
- void CreateVideoPowerSaveBlocker();
+ device::mojom::WakeLockService* GetAudioWakeLock();
+ device::mojom::WakeLockService* GetVideoWakeLock();
- // Releases the audio power save blockers if |active_audio_players_| is empty.
- // Likewise, releases the video power save blockers if |active_video_players_|
- // is empty.
- void MaybeReleasePowerSaveBlockers();
+ void LockAudio();
+ void LockVideo();
+
+ void CancelAudioLock();
+ void CancelVideoLock();
+ void MaybeCancelVideoLock();
// Helper methods for adding or removing player entries in |player_map|.
using PlayerSet = std::set<int>;
@@ -117,12 +115,14 @@
ActiveMediaPlayerMap* player_map,
std::set<MediaPlayerId>* removed_players);
- // Tracking variables and associated power save blockers for media playback.
+ // Tracking variables and associated wake locks for media playback.
ActiveMediaPlayerMap active_audio_players_;
ActiveMediaPlayerMap active_video_players_;
- std::unique_ptr<device::PowerSaveBlocker> audio_power_save_blocker_;
- std::unique_ptr<device::PowerSaveBlocker> video_power_save_blocker_;
+ device::mojom::WakeLockServicePtr audio_wake_lock_;
+ device::mojom::WakeLockServicePtr video_wake_lock_;
base::Optional<MediaPlayerId> fullscreen_player_;
+ bool has_audio_wake_lock_for_testing_;
+ bool has_video_wake_lock_for_testing_;
MediaSessionControllersManager session_controllers_manager_;
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 36ce192..1eda2756 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -257,16 +257,16 @@
RenderViewHostImplTestHarness::TearDown();
}
- bool has_audio_power_save_blocker() {
+ bool has_audio_wake_lock() {
return contents()
->media_web_contents_observer()
- ->has_audio_power_save_blocker_for_testing();
+ ->has_audio_wake_lock_for_testing();
}
- bool has_video_power_save_blocker() {
+ bool has_video_wake_lock() {
return contents()
->media_web_contents_observer()
- ->has_video_power_save_blocker_for_testing();
+ ->has_video_wake_lock_for_testing();
}
};
@@ -3214,15 +3214,15 @@
EXPECT_FALSE(contents()->IsLoading());
}
-TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
+TEST_F(WebContentsImplTest, MediaWakeLock) {
// Verify that both negative and positive player ids don't blow up.
const int kPlayerAudioVideoId = 15;
const int kPlayerAudioOnlyId = -15;
const int kPlayerVideoOnlyId = 30;
const int kPlayerRemoteId = -30;
- EXPECT_FALSE(has_audio_power_save_blocker());
- EXPECT_FALSE(has_video_power_save_blocker());
+ EXPECT_FALSE(has_audio_wake_lock());
+ EXPECT_FALSE(has_video_wake_lock());
TestRenderFrameHost* rfh = main_test_rfh();
AudioStreamMonitor* monitor = contents()->audio_stream_monitor();
@@ -3230,100 +3230,100 @@
// Ensure RenderFrame is initialized before simulating events coming from it.
main_test_rfh()->InitializeRenderFrameIfNeeded();
- // Send a fake audio stream monitor notification. The audio power save
- // blocker should be created.
+ // Send a fake audio stream monitor notification. The audio wake lock
+ // should be created.
monitor->set_was_recently_audible_for_testing(true);
contents()->NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
- EXPECT_TRUE(has_audio_power_save_blocker());
+ EXPECT_TRUE(has_audio_wake_lock());
// Send another fake notification, this time when WasRecentlyAudible() will
- // be false. The power save blocker should be released.
+ // be false. The wake lock should be released.
monitor->set_was_recently_audible_for_testing(false);
contents()->NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
- EXPECT_FALSE(has_audio_power_save_blocker());
+ EXPECT_FALSE(has_audio_wake_lock());
- // Start a player with both audio and video. A video power save blocker
+ // Start a player with both audio and video. A video wake lock
// should be created. If audio stream monitoring is available, an audio power
// save blocker should be created too.
rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnMediaPlaying(
0, kPlayerAudioVideoId, true, true, false,
media::MediaContentType::Persistent));
- EXPECT_TRUE(has_video_power_save_blocker());
- EXPECT_FALSE(has_audio_power_save_blocker());
+ EXPECT_TRUE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
- // Upon hiding the video power save blocker should be released.
+ // Upon hiding the video wake lock should be released.
contents()->WasHidden();
- EXPECT_FALSE(has_video_power_save_blocker());
+ EXPECT_FALSE(has_video_wake_lock());
// Start another player that only has video. There should be no change in
- // the power save blockers. The notification should take into account the
+ // the wake locks. The notification should take into account the
// visibility state of the WebContents.
rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnMediaPlaying(
0, kPlayerVideoOnlyId, true, false, false,
media::MediaContentType::Persistent));
- EXPECT_FALSE(has_video_power_save_blocker());
- EXPECT_FALSE(has_audio_power_save_blocker());
+ EXPECT_FALSE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
// Showing the WebContents should result in the creation of the blocker.
contents()->WasShown();
- EXPECT_TRUE(has_video_power_save_blocker());
+ EXPECT_TRUE(has_video_wake_lock());
// Start another player that only has audio. There should be no change in
- // the power save blockers.
+ // the wake locks.
rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnMediaPlaying(
0, kPlayerAudioOnlyId, false, true, false,
media::MediaContentType::Persistent));
- EXPECT_TRUE(has_video_power_save_blocker());
- EXPECT_FALSE(has_audio_power_save_blocker());
+ EXPECT_TRUE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
// Start a remote player. There should be no change in the power save
// blockers.
rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnMediaPlaying(
0, kPlayerRemoteId, true, true, true,
media::MediaContentType::Persistent));
- EXPECT_TRUE(has_video_power_save_blocker());
- EXPECT_FALSE(has_audio_power_save_blocker());
+ EXPECT_TRUE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
- // Destroy the original audio video player. Both power save blockers should
+ // Destroy the original audio video player. Both wake locks should
// remain.
rfh->OnMessageReceived(
MediaPlayerDelegateHostMsg_OnMediaPaused(0, kPlayerAudioVideoId, false));
- EXPECT_TRUE(has_video_power_save_blocker());
- EXPECT_FALSE(has_audio_power_save_blocker());
+ EXPECT_TRUE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
- // Destroy the audio only player. The video power save blocker should remain.
+ // Destroy the audio only player. The video wake lock should remain.
rfh->OnMessageReceived(
MediaPlayerDelegateHostMsg_OnMediaPaused(0, kPlayerAudioOnlyId, false));
- EXPECT_TRUE(has_video_power_save_blocker());
- EXPECT_FALSE(has_audio_power_save_blocker());
+ EXPECT_TRUE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
- // Destroy the video only player. No power save blockers should remain.
+ // Destroy the video only player. No wake locks should remain.
rfh->OnMessageReceived(
MediaPlayerDelegateHostMsg_OnMediaPaused(0, kPlayerVideoOnlyId, false));
- EXPECT_FALSE(has_video_power_save_blocker());
- EXPECT_FALSE(has_audio_power_save_blocker());
+ EXPECT_FALSE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
- // Destroy the remote player. No power save blockers should remain.
+ // Destroy the remote player. No wake locks should remain.
rfh->OnMessageReceived(
MediaPlayerDelegateHostMsg_OnMediaPaused(0, kPlayerRemoteId, false));
- EXPECT_FALSE(has_video_power_save_blocker());
- EXPECT_FALSE(has_audio_power_save_blocker());
+ EXPECT_FALSE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
- // Start a player with both audio and video. A video power save blocker
+ // Start a player with both audio and video. A video wake lock
// should be created. If audio stream monitoring is available, an audio power
// save blocker should be created too.
rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnMediaPlaying(
0, kPlayerAudioVideoId, true, true, false,
media::MediaContentType::Persistent));
- EXPECT_TRUE(has_video_power_save_blocker());
- EXPECT_FALSE(has_audio_power_save_blocker());
+ EXPECT_TRUE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
// Crash the renderer.
main_test_rfh()->GetProcess()->SimulateCrash();
- // Verify that all the power save blockers have been released.
- EXPECT_FALSE(has_video_power_save_blocker());
- EXPECT_FALSE(has_audio_power_save_blocker());
+ // Verify that all the wake locks have been released.
+ EXPECT_FALSE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
}
TEST_F(WebContentsImplTest, ThemeColorChangeDependingOnFirstVisiblePaint) {