Commit f3c302a3 authored by derat's avatar derat Committed by Commit bot

Use PowerSaveBlocker for audio and video on Chrome OS.

PowerSaveBlocker objects are constructed in response to web
audio and video to keep the system from suspending or
turning its display off. Historically, this was not used on
Chrome OS, as Chrome OS has alternate mechanisms for
detecting audio and video activity and using
PowerSaveBlocker would interfere with enterprise
power-management-policy prefs to ignore audio and video
activity.

However, low-framerate video, such as that used by WebRTC
for Hangouts screen-sharing, can fail to trigger Chrome OS's
video detection code, resulting in the screen being turned
off while in use. This change renames PowerSaveBlocker's
human-readable "reason" field to "description" and adds a
new Reason enum that Chrome OS uses to identify and ignore
audio- or video-triggered PowerSaveBlockers if needed.

BUG=354723,176405
TEST=watch /var/log/power_manager/powerd.LATEST on chrome os
     while on the receiving end of a screen-sharing hangout
     and observe that a policy is sent forcing the screen on

Review URL: https://codereview.chromium.org/946643002

Cr-Commit-Position: refs/heads/master@{#317612}
parent a58ec6a8
......@@ -160,7 +160,8 @@ class PowerSaveBlockerStub : public content::PowerSaveBlocker {
static scoped_ptr<PowerSaveBlocker> Create(PowerSettingsMock* power_settings,
PowerSaveBlockerType type,
const std::string& reason) {
Reason reason,
const std::string& description) {
return scoped_ptr<PowerSaveBlocker>(
new PowerSaveBlockerStub(power_settings));
}
......
......@@ -59,10 +59,10 @@ struct DriveUploader::UploadFileInfo {
next_start_position(-1),
power_save_blocker(content::PowerSaveBlocker::Create(
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
content::PowerSaveBlocker::kReasonOther,
"Upload in progress")),
cancelled(false),
weak_ptr_factory_(this) {
}
weak_ptr_factory_(this) {}
~UploadFileInfo() {
}
......
......@@ -90,9 +90,11 @@ void CastTransportHostFilter::OnNew(
if (!power_save_blocker_) {
DVLOG(1) << ("Preventing the application from being suspended while one or "
"more transports are active for Cast Streaming.");
power_save_blocker_ = content::PowerSaveBlocker::Create(
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
"Cast is streaming content to a remote receiver.").Pass();
power_save_blocker_ =
content::PowerSaveBlocker::Create(
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
content::PowerSaveBlocker::kReasonOther,
"Cast is streaming content to a remote receiver").Pass();
}
if (id_map_.Lookup(channel_id)) {
......
......@@ -4,6 +4,8 @@
#include "chromeos/dbus/power_policy_controller.h"
#include <utility>
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
......@@ -57,9 +59,24 @@ power_manager::PowerManagementPolicy_Action GetProtoAction(
}
}
// Returns false if |use_audio_activity| and |use_audio_activity| prevent wake
// locks created for |reason| from being honored or true otherwise.
bool IsWakeLockReasonHonored(PowerPolicyController::WakeLockReason reason,
bool use_audio_activity,
bool use_video_activity) {
if (reason == PowerPolicyController::REASON_AUDIO_PLAYBACK &&
!use_audio_activity)
return false;
if (reason == PowerPolicyController::REASON_VIDEO_PLAYBACK &&
!use_video_activity)
return false;
return true;
}
} // namespace
const int PowerPolicyController::kScreenLockAfterOffDelayMs = 10000; // 10 sec.
const char PowerPolicyController::kPrefsReason[] = "Prefs";
// -1 is interpreted as "unset" by powerd, resulting in powerd's default
// delays being used instead. There are no similarly-interpreted values
......@@ -224,22 +241,18 @@ void PowerPolicyController::ApplyPrefs(const PrefValues& values) {
SendCurrentPolicy();
}
int PowerPolicyController::AddScreenWakeLock(const std::string& reason) {
int id = next_wake_lock_id_++;
screen_wake_locks_[id] = reason;
SendCurrentPolicy();
return id;
int PowerPolicyController::AddScreenWakeLock(WakeLockReason reason,
const std::string& description) {
return AddWakeLockInternal(WakeLock::TYPE_SCREEN, reason, description);
}
int PowerPolicyController::AddSystemWakeLock(const std::string& reason) {
int id = next_wake_lock_id_++;
system_wake_locks_[id] = reason;
SendCurrentPolicy();
return id;
int PowerPolicyController::AddSystemWakeLock(WakeLockReason reason,
const std::string& description) {
return AddWakeLockInternal(WakeLock::TYPE_SYSTEM, reason, description);
}
void PowerPolicyController::RemoveWakeLock(int id) {
if (!screen_wake_locks_.erase(id) && !system_wake_locks_.erase(id))
if (!wake_locks_.erase(id))
LOG(WARNING) << "Ignoring request to remove nonexistent wake lock " << id;
else
SendCurrentPolicy();
......@@ -262,14 +275,51 @@ PowerPolicyController::~PowerPolicyController() {
client_->RemoveObserver(this);
}
PowerPolicyController::WakeLock::WakeLock(Type type,
WakeLockReason reason,
const std::string& description)
: type(type), reason(reason), description(description) {
}
PowerPolicyController::WakeLock::~WakeLock() {
}
int PowerPolicyController::AddWakeLockInternal(WakeLock::Type type,
WakeLockReason reason,
const std::string& description) {
const int id = next_wake_lock_id_++;
wake_locks_.insert(std::make_pair(id, WakeLock(type, reason, description)));
SendCurrentPolicy();
return id;
}
void PowerPolicyController::SendCurrentPolicy() {
std::string reason;
std::string causes;
power_manager::PowerManagementPolicy policy = prefs_policy_;
if (prefs_were_set_)
reason = "Prefs";
causes = kPrefsReason;
bool have_screen_wake_locks = false;
bool have_system_wake_locks = false;
for (const auto& it : wake_locks_) {
// Skip audio and video locks that should be ignored due to policy.
if (!IsWakeLockReasonHonored(it.second.reason, policy.use_audio_activity(),
policy.use_video_activity()))
continue;
switch (it.second.type) {
case WakeLock::TYPE_SCREEN:
have_screen_wake_locks = true;
break;
case WakeLock::TYPE_SYSTEM:
have_system_wake_locks = true;
break;
}
causes += (causes.empty() ? "" : ", ") + it.second.description;
}
if (honor_screen_wake_locks_ && !screen_wake_locks_.empty()) {
if (honor_screen_wake_locks_ && have_screen_wake_locks) {
policy.mutable_ac_delays()->set_screen_dim_ms(0);
policy.mutable_ac_delays()->set_screen_off_ms(0);
policy.mutable_ac_delays()->set_screen_lock_ms(0);
......@@ -278,7 +328,7 @@ void PowerPolicyController::SendCurrentPolicy() {
policy.mutable_battery_delays()->set_screen_lock_ms(0);
}
if (!screen_wake_locks_.empty() || !system_wake_locks_.empty()) {
if (have_screen_wake_locks || have_system_wake_locks) {
if (!policy.has_ac_idle_action() || policy.ac_idle_action() ==
power_manager::PowerManagementPolicy_Action_SUSPEND) {
policy.set_ac_idle_action(
......@@ -291,17 +341,8 @@ void PowerPolicyController::SendCurrentPolicy() {
}
}
for (WakeLockMap::const_iterator it = screen_wake_locks_.begin();
it != screen_wake_locks_.end(); ++it) {
reason += (reason.empty() ? "" : ", ") + it->second;
}
for (WakeLockMap::const_iterator it = system_wake_locks_.begin();
it != system_wake_locks_.end(); ++it) {
reason += (reason.empty() ? "" : ", ") + it->second;
}
if (!reason.empty())
policy.set_reason(reason);
if (!causes.empty())
policy.set_reason(causes);
client_->SetPolicy(policy);
}
......
......@@ -32,6 +32,13 @@ class CHROMEOS_EXPORT PowerPolicyController
// Returns the global instance. Initialize() must be called first.
static PowerPolicyController* Get();
// Reasons why a wake lock may be added.
enum WakeLockReason {
REASON_AUDIO_PLAYBACK,
REASON_VIDEO_PLAYBACK,
REASON_OTHER,
};
// Note: Do not change these values; they are used by preferences.
enum Action {
ACTION_SUSPEND = 0,
......@@ -79,16 +86,20 @@ class CHROMEOS_EXPORT PowerPolicyController
// constant would imply.
static const int kScreenLockAfterOffDelayMs;
// String added to a PowerManagementPolicy |reason| field if the policy has
// been modified by preferences.
static const char kPrefsReason[];
// Updates |prefs_policy_| with |values| and sends an updated policy.
void ApplyPrefs(const PrefValues& values);
// Registers a request to temporarily prevent the screen from getting
// dimmed or turned off or the system from suspending in response to user
// inactivity and sends an updated policy. |reason| is a human-readable
// description of the reason the lock was created. Returns a unique ID
// that can be passed to RemoveWakeLock() later.
int AddScreenWakeLock(const std::string& reason);
int AddSystemWakeLock(const std::string& reason);
// Registers a request to temporarily prevent the screen from getting dimmed
// or turned off or the system from suspending in response to user inactivity
// and sends an updated policy. |description| is a human-readable description
// of the reason the lock was created. Returns a unique ID that can be passed
// to RemoveWakeLock() later.
int AddScreenWakeLock(WakeLockReason reason, const std::string& description);
int AddSystemWakeLock(WakeLockReason reason, const std::string& description);
// Unregisters a request previously created via AddScreenWakeLock() or
// AddSystemWakeLock() and sends an updated policy.
......@@ -103,7 +114,28 @@ class CHROMEOS_EXPORT PowerPolicyController
friend class PowerPrefsTest;
typedef std::map<int, std::string> WakeLockMap;
// Details about a wake lock added via AddScreenWakeLock() or
// AddSystemWakeLock().
struct WakeLock {
enum Type {
TYPE_SCREEN,
TYPE_SYSTEM,
};
WakeLock(Type type, WakeLockReason reason, const std::string& description);
~WakeLock();
const Type type;
const WakeLockReason reason;
const std::string description;
};
using WakeLockMap = std::map<int, WakeLock>;
// Helper method for AddScreenWakeLock() and AddSystemWakeLock().
int AddWakeLockInternal(WakeLock::Type type,
WakeLockReason reason,
const std::string& description);
// Sends a policy based on |prefs_policy_| to the power manager.
void SendCurrentPolicy();
......@@ -118,12 +150,11 @@ class CHROMEOS_EXPORT PowerPolicyController
// Maps from an ID representing a request to prevent the screen from
// getting dimmed or turned off or to prevent the system from suspending
// to the reason for the request.
WakeLockMap screen_wake_locks_;
WakeLockMap system_wake_locks_;
// to details about the request.
WakeLockMap wake_locks_;
// Should entries in |screen_wake_locks_| be honored? If false, screen
// wake locks are just treated as system wake locks instead.
// Should TYPE_SCREEN entries in |wake_locks_| be honored? If false, screen
// wake locks are just treated as TYPE_SYSTEM instead.
bool honor_screen_wake_locks_;
// Next ID to be used by AddScreenWakeLock() or AddSystemWakeLock().
......
......@@ -82,7 +82,7 @@ TEST_F(PowerPolicyControllerTest, Prefs) {
expected_policy.set_user_activity_screen_dim_delay_factor(2.0);
expected_policy.set_wait_for_initial_user_activity(true);
expected_policy.set_force_nonzero_brightness_for_user_activity(false);
expected_policy.set_reason("Prefs");
expected_policy.set_reason(PowerPolicyController::kPrefsReason);
EXPECT_EQ(PowerPolicyController::GetPolicyDebugString(expected_policy),
PowerPolicyController::GetPolicyDebugString(
fake_power_client_->policy()));
......@@ -151,10 +151,12 @@ TEST_F(PowerPolicyControllerTest, Prefs) {
// pref-supplied screen-related delays should be left untouched.
prefs.allow_screen_wake_locks = false;
policy_controller_->ApplyPrefs(prefs);
policy_controller_->AddScreenWakeLock("Screen");
policy_controller_->AddScreenWakeLock(PowerPolicyController::REASON_OTHER,
"Screen");
expected_policy.set_ac_idle_action(
power_manager::PowerManagementPolicy_Action_DO_NOTHING);
expected_policy.set_reason("Prefs, Screen");
expected_policy.set_reason(std::string(PowerPolicyController::kPrefsReason) +
", Screen");
EXPECT_EQ(PowerPolicyController::GetPolicyDebugString(expected_policy),
PowerPolicyController::GetPolicyDebugString(
fake_power_client_->policy()));
......@@ -162,8 +164,8 @@ TEST_F(PowerPolicyControllerTest, Prefs) {
TEST_F(PowerPolicyControllerTest, WakeLocks) {
const char kSystemWakeLockReason[] = "system";
const int system_id =
policy_controller_->AddSystemWakeLock(kSystemWakeLockReason);
const int system_id = policy_controller_->AddSystemWakeLock(
PowerPolicyController::REASON_OTHER, kSystemWakeLockReason);
power_manager::PowerManagementPolicy expected_policy;
expected_policy.set_ac_idle_action(
power_manager::PowerManagementPolicy_Action_DO_NOTHING);
......@@ -176,15 +178,15 @@ TEST_F(PowerPolicyControllerTest, WakeLocks) {
const char kScreenWakeLockReason[] = "screen";
const int screen_id = policy_controller_->AddScreenWakeLock(
kScreenWakeLockReason);
PowerPolicyController::REASON_OTHER, kScreenWakeLockReason);
expected_policy.mutable_ac_delays()->set_screen_dim_ms(0);
expected_policy.mutable_ac_delays()->set_screen_off_ms(0);
expected_policy.mutable_ac_delays()->set_screen_lock_ms(0);
expected_policy.mutable_battery_delays()->set_screen_dim_ms(0);
expected_policy.mutable_battery_delays()->set_screen_off_ms(0);
expected_policy.mutable_battery_delays()->set_screen_lock_ms(0);
expected_policy.set_reason(
std::string(kScreenWakeLockReason) + ", " + kSystemWakeLockReason);
expected_policy.set_reason(std::string(kSystemWakeLockReason) + ", " +
kScreenWakeLockReason);
EXPECT_EQ(PowerPolicyController::GetPolicyDebugString(expected_policy),
PowerPolicyController::GetPolicyDebugString(
fake_power_client_->policy()));
......@@ -202,6 +204,72 @@ TEST_F(PowerPolicyControllerTest, WakeLocks) {
fake_power_client_->policy()));
}
TEST_F(PowerPolicyControllerTest, IgnoreMediaWakeLocksWhenRequested) {
PowerPolicyController::PrefValues prefs;
policy_controller_->ApplyPrefs(prefs);
const power_manager::PowerManagementPolicy kDefaultPolicy =
fake_power_client_->policy();
// Wake locks created for audio or video playback should be ignored when the
// |use_audio_activity| or |use_video_activity| prefs are unset.
prefs.use_audio_activity = false;
prefs.use_video_activity = false;
policy_controller_->ApplyPrefs(prefs);
const int audio_id = policy_controller_->AddSystemWakeLock(
PowerPolicyController::REASON_AUDIO_PLAYBACK, "audio");
const int video_id = policy_controller_->AddScreenWakeLock(
PowerPolicyController::REASON_VIDEO_PLAYBACK, "video");
power_manager::PowerManagementPolicy expected_policy = kDefaultPolicy;
expected_policy.set_use_audio_activity(false);
expected_policy.set_use_video_activity(false);
expected_policy.set_reason(PowerPolicyController::kPrefsReason);
EXPECT_EQ(PowerPolicyController::GetPolicyDebugString(expected_policy),
PowerPolicyController::GetPolicyDebugString(
fake_power_client_->policy()));
// Non-media screen wake locks should still be honored.
const int other_id = policy_controller_->AddScreenWakeLock(
PowerPolicyController::REASON_OTHER, "other");
expected_policy.set_ac_idle_action(
power_manager::PowerManagementPolicy_Action_DO_NOTHING);
expected_policy.set_battery_idle_action(
power_manager::PowerManagementPolicy_Action_DO_NOTHING);
expected_policy.mutable_ac_delays()->set_screen_dim_ms(0);
expected_policy.mutable_ac_delays()->set_screen_off_ms(0);
expected_policy.mutable_ac_delays()->set_screen_lock_ms(0);
expected_policy.mutable_battery_delays()->set_screen_dim_ms(0);
expected_policy.mutable_battery_delays()->set_screen_off_ms(0);
expected_policy.mutable_battery_delays()->set_screen_lock_ms(0);
expected_policy.set_reason(std::string(PowerPolicyController::kPrefsReason) +
", other");
EXPECT_EQ(PowerPolicyController::GetPolicyDebugString(expected_policy),
PowerPolicyController::GetPolicyDebugString(
fake_power_client_->policy()));
// Start honoring audio activity and check that the audio wake lock is used.
policy_controller_->RemoveWakeLock(other_id);
prefs.use_audio_activity = true;
policy_controller_->ApplyPrefs(prefs);
expected_policy = kDefaultPolicy;
expected_policy.set_use_video_activity(false);
expected_policy.set_ac_idle_action(
power_manager::PowerManagementPolicy_Action_DO_NOTHING);
expected_policy.set_battery_idle_action(
power_manager::PowerManagementPolicy_Action_DO_NOTHING);
expected_policy.set_reason(std::string(PowerPolicyController::kPrefsReason) +
", audio");
EXPECT_EQ(PowerPolicyController::GetPolicyDebugString(expected_policy),
PowerPolicyController::GetPolicyDebugString(
fake_power_client_->policy()));
policy_controller_->RemoveWakeLock(audio_id);
policy_controller_->RemoveWakeLock(video_id);
}
TEST_F(PowerPolicyControllerTest, AvoidSendingEmptyPolicies) {
// Check that empty policies aren't sent when PowerPolicyController is created
// or destroyed.
......
......@@ -211,11 +211,10 @@ void RenderFrameDevToolsAgentHost::InnerOnClientAttached() {
render_frame_host_->GetProcess()->GetID());
#if defined(OS_ANDROID)
power_save_blocker_.reset(
static_cast<PowerSaveBlockerImpl*>(
PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
"DevTools").release()));
power_save_blocker_.reset(static_cast<PowerSaveBlockerImpl*>(
PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
PowerSaveBlocker::kReasonOther, "DevTools").release()));
RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
render_frame_host_->GetRenderViewHost());
if (rvh->GetView()) {
......
......@@ -242,10 +242,9 @@ DownloadFile* DownloadFileWithDelayFactory::CreateFile(
scoped_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer) {
scoped_ptr<PowerSaveBlocker> psb(
PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
"Download in progress"));
scoped_ptr<PowerSaveBlocker> psb(PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
PowerSaveBlocker::kReasonOther, "Download in progress"));
return new DownloadFileWithDelay(
save_info.Pass(), default_download_directory, url, referrer_url,
calculate_hash, stream.Pass(), bound_net_log,
......@@ -342,10 +341,9 @@ class CountingDownloadFileFactory : public DownloadFileFactory {
scoped_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer) override {
scoped_ptr<PowerSaveBlocker> psb(
PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
"Download in progress"));
scoped_ptr<PowerSaveBlocker> psb(PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
PowerSaveBlocker::kReasonOther, "Download in progress"));
return new CountingDownloadFile(
save_info.Pass(), default_downloads_directory, url, referrer_url,
calculate_hash, stream.Pass(), bound_net_log,
......
......@@ -131,7 +131,7 @@ DownloadResourceHandler::DownloadResourceHandler(
tab_info_));
power_save_blocker_ = PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
"Download in progress");
PowerSaveBlocker::kReasonOther, "Download in progress");
}
bool DownloadResourceHandler::OnUploadProgress(uint64 position,
......
......@@ -47,7 +47,7 @@ const char* PowerSaveBlockResourceThrottle::GetNameForLogging() const {
void PowerSaveBlockResourceThrottle::ActivatePowerSaveBlocker() {
power_save_blocker_ = PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
"Uploading data.");
PowerSaveBlocker::kReasonOther, "Uploading data");
}
} // namespace content
......@@ -174,9 +174,11 @@ void DesktopCaptureDevice::Core::AllocateAndStart(
// This capturer always outputs ARGB, non-interlaced.
capture_format_.pixel_format = media::PIXEL_FORMAT_ARGB;
power_save_blocker_.reset(PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
"DesktopCaptureDevice is running").release());
power_save_blocker_.reset(
PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
PowerSaveBlocker::kReasonOther,
"DesktopCaptureDevice is running").release());
desktop_capturer_->Start(this);
......
......@@ -218,9 +218,11 @@ bool DesktopVideoCaptureMachine::Start(
if (desktop_window_->GetHost())
desktop_window_->GetHost()->compositor()->AddObserver(this);
power_save_blocker_.reset(PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
"DesktopCaptureDevice is running").release());
power_save_blocker_.reset(
PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
PowerSaveBlocker::kReasonOther,
"DesktopCaptureDevice is running").release());
// Starts timer.
timer_.Start(FROM_HERE, oracle_proxy_->min_capture_period(),
......
......@@ -377,9 +377,11 @@ void WebRTCInternals::CreateOrReleasePowerSaveBlocker() {
} else if (!peer_connection_data_.empty() && !power_save_blocker_) {
DVLOG(1) << ("Preventing the application from being suspended while one or "
"more PeerConnections are active.");
power_save_blocker_ = content::PowerSaveBlocker::Create(
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
"WebRTC has active PeerConnections.").Pass();
power_save_blocker_ =
content::PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
PowerSaveBlocker::kReasonOther,
"WebRTC has active PeerConnections").Pass();
}
}
......
......@@ -57,7 +57,8 @@ void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
}
PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
const std::string& reason) {
Reason reason,
const std::string& description) {
// Don't support kPowerSaveBlockPreventAppSuspension
}
......
......@@ -16,13 +16,32 @@
namespace content {
namespace {
// Converts a PowerSaveBlocker::Reason to a
// chromeos::PowerPolicyController::WakeLockReason.
chromeos::PowerPolicyController::WakeLockReason GetWakeLockReason(
PowerSaveBlocker::Reason reason) {
switch (reason) {
case PowerSaveBlocker::kReasonAudioPlayback:
return chromeos::PowerPolicyController::REASON_AUDIO_PLAYBACK;
case PowerSaveBlocker::kReasonVideoPlayback:
return chromeos::PowerPolicyController::REASON_VIDEO_PLAYBACK;
case PowerSaveBlocker::kReasonOther:
return chromeos::PowerPolicyController::REASON_OTHER;
}
return chromeos::PowerPolicyController::REASON_OTHER;
}
} // namespace
class PowerSaveBlockerImpl::Delegate
: public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
public:
Delegate(PowerSaveBlockerType type, const std::string& reason)
: type_(type),
reason_(reason),
block_id_(0) {}
Delegate(PowerSaveBlockerType type,
Reason reason,
const std::string& description)
: type_(type), reason_(reason), description_(description), block_id_(0) {}
void ApplyBlock() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
......@@ -32,10 +51,12 @@ class PowerSaveBlockerImpl::Delegate
auto* controller = chromeos::PowerPolicyController::Get();
switch (type_) {
case kPowerSaveBlockPreventAppSuspension:
block_id_ = controller->AddSystemWakeLock(reason_);
block_id_ = controller->AddSystemWakeLock(GetWakeLockReason(reason_),
description_);
break;
case kPowerSaveBlockPreventDisplaySleep:
block_id_ = controller->AddScreenWakeLock(reason_);
block_id_ = controller->AddScreenWakeLock(GetWakeLockReason(reason_),
description_);
break;
default:
NOTREACHED() << "Unhandled block type " << type_;
......@@ -55,7 +76,8 @@ class PowerSaveBlockerImpl::Delegate
virtual ~Delegate() {}
PowerSaveBlockerType type_;
std::string reason_;
Reason reason_;
std::string description_;
// ID corresponding to the block request in PowerPolicyController.
int block_id_;
......@@ -64,8 +86,9 @@ class PowerSaveBlockerImpl::Delegate
};
PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
const std::string& reason)
: delegate_(new Delegate(type, reason)) {
Reason reason,
const std::string& description)
: delegate_(new Delegate(type, reason, description)) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&Delegate::ApplyBlock, delegate_));
}
......
......@@ -11,8 +11,10 @@ PowerSaveBlocker::~PowerSaveBlocker() {}
// static
scoped_ptr<PowerSaveBlocker> PowerSaveBlocker::Create(
PowerSaveBlockerType type,
const std::string& reason) {
return scoped_ptr<PowerSaveBlocker>(new PowerSaveBlockerImpl(type, reason));
Reason reason,
const std::string& description) {
return scoped_ptr<PowerSaveBlocker>(
new PowerSaveBlockerImpl(type, reason, description));
}
} // namespace content
......@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_POWER_SAVE_BLOCKER_IMPL_H_
#define CONTENT_BROWSER_POWER_SAVE_BLOCKER_IMPL_H_
#include <string>
#include "base/memory/ref_counted.h"
#include "content/public/browser/power_save_blocker.h"
#include "ui/gfx/native_widget_types.h"
......@@ -13,7 +15,9 @@ namespace content {
class PowerSaveBlockerImpl : public PowerSaveBlocker {
public:
PowerSaveBlockerImpl(PowerSaveBlockerType type, const std::string& reason);
PowerSaveBlockerImpl(PowerSaveBlockerType type,
Reason reason,
const std::string& description);
~PowerSaveBlockerImpl() override;
#if defined(OS_ANDROID)
......
......@@ -41,8 +41,10 @@ base::LazyInstance<base::Thread, PowerSaveBlockerLazyInstanceTraits>
class PowerSaveBlockerImpl::Delegate
: public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
public:
Delegate(PowerSaveBlockerType type, const std::string& reason)
: type_(type), reason_(reason), assertion_(kIOPMNullAssertionID) {}
Delegate(PowerSaveBlockerType type, const std::string& description)
: type_(type),
description_(description),
assertion_(kIOPMNullAssertionID) {}
// Does the actual work to apply or remove the desired power save block.
void ApplyBlock();
......@@ -52,7 +54,7 @@ class PowerSaveBlockerImpl::Delegate
friend class base::RefCountedThreadSafe<Delegate>;
~Delegate() {}
PowerSaveBlockerType type_;
std::string reason_;
std::string description_;
IOPMAssertionID assertion_;
};
......@@ -75,12 +77,10 @@ void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
break;
}
if (level) {
base::ScopedCFTypeRef<CFStringRef> cf_reason(
base::SysUTF8ToCFStringRef(reason_));
IOReturn result = IOPMAssertionCreateWithName(level,
kIOPMAssertionLevelOn,
cf_reason,
&assertion_);
base::ScopedCFTypeRef<CFStringRef> cf_description(
base::SysUTF8ToCFStringRef(description_));
IOReturn result = IOPMAssertionCreateWithName(level, kIOPMAssertionLevelOn,
cf_description, &assertion_);
LOG_IF(ERROR, result != kIOReturnSuccess)
<< "IOPMAssertionCreate: " << result;
}
......@@ -98,8 +98,9 @@ void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
}
PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
const std::string& reason)
: delegate_(new Delegate(type, reason)) {
Reason reason,
const std::string& description)
: delegate_(new Delegate(type, description)) {
g_power_thread.Pointer()->message_loop()->PostTask(
FROM_HERE,
base::Bind(&Delegate::ApplyBlock, delegate_));
......
......@@ -24,7 +24,8 @@ class PowerSaveBlockerImpl::Delegate
};
PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
const std::string& reason)
Reason reason,
const std::string& description)
: delegate_(new Delegate()) {
NOTIMPLEMENTED();
}
......
......@@ -17,7 +17,8 @@ namespace {
int g_blocker_count[2];
HANDLE CreatePowerRequest(POWER_REQUEST_TYPE type, const std::string& reason) {
HANDLE CreatePowerRequest(POWER_REQUEST_TYPE type,
const std::string& description) {
typedef HANDLE (WINAPI* PowerCreateRequestPtr)(PREASON_CONTEXT);
typedef BOOL (WINAPI* PowerSetRequestPtr)(HANDLE, POWER_REQUEST_TYPE);
......@@ -39,11 +40,12 @@ HANDLE CreatePowerRequest(POWER_REQUEST_TYPE type, const std::string& reason) {
if (!PowerCreateRequestFn || !PowerSetRequestFn)
return INVALID_HANDLE_VALUE;
}
base::string16 wide_reason = base::ASCIIToUTF16(reason);
base::string16 wide_description = base::ASCIIToUTF16(description);
REASON_CONTEXT context = {0};
context.Version = POWER_REQUEST_CONTEXT_VERSION;
context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
context.Reason.SimpleReasonString = const_cast<wchar_t*>(wide_reason.c_str());
context.Reason.SimpleReasonString =
const_cast<wchar_t*>(wide_description.c_str());
base::win::ScopedHandle handle(PowerCreateRequestFn(&context));
if (!handle.IsValid())
......@@ -110,8 +112,8 @@ void ApplySimpleBlock(PowerSaveBlocker::PowerSaveBlockerType type,
class PowerSaveBlockerImpl::Delegate
: public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
public:
Delegate(PowerSaveBlockerType type, const std::string& reason)
: type_(type), reason_(reason) {}
Delegate(PowerSaveBlockerType type, const std::string& description)
: type_(type), description_(description) {}
// Does the actual work to apply or remove the desired power save block.
void ApplyBlock();
......@@ -125,7 +127,7 @@ class PowerSaveBlockerImpl::Delegate
~Delegate() {}
PowerSaveBlockerType type_;
const std::string reason_;
const std::string description_;
base::win::ScopedHandle handle_;
DISALLOW_COPY_AND_ASSIGN(Delegate);
......@@ -136,7 +138,7 @@ void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
if (base::win::GetVersion() < base::win::VERSION_WIN7)
return ApplySimpleBlock(type_, 1);
handle_.Set(CreatePowerRequest(RequestType(), reason_));
handle_.Set(CreatePowerRequest(RequestType(), description_));
}
void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
......@@ -158,8 +160,9 @@ POWER_REQUEST_TYPE PowerSaveBlockerImpl::Delegate::RequestType() {
}
PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
const std::string& reason)
: delegate_(new Delegate(type, reason)) {
Reason reason,
const std::string& description)
: delegate_(new Delegate(type, description)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&Delegate::ApplyBlock, delegate_));
......
......@@ -67,7 +67,7 @@ class PowerSaveBlockerImpl::Delegate
: public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
public:
// Picks an appropriate D-Bus API to use based on the desktop environment.
Delegate(PowerSaveBlockerType type, const std::string& reason);
Delegate(PowerSaveBlockerType type, const std::string& description);
// Post a task to initialize the delegate on the UI thread, which will itself
// then post a task to apply the power save block on the FILE thread.
......@@ -104,7 +104,7 @@ class PowerSaveBlockerImpl::Delegate
static DBusAPI SelectAPI();
const PowerSaveBlockerType type_;
const std::string reason_;
const std::string description_;
// Initially, we post a message to the UI thread to select an API. When it
// finishes, it will post a message to the FILE thread to perform the actual
......@@ -125,9 +125,9 @@ class PowerSaveBlockerImpl::Delegate
};
PowerSaveBlockerImpl::Delegate::Delegate(PowerSaveBlockerType type,
const std::string& reason)
const std::string& description)
: type_(type),
reason_(reason),
description_(description),
api_(NO_API),
enqueue_apply_(false),
inhibit_cookie_(0) {
......@@ -202,7 +202,7 @@ void PowerSaveBlockerImpl::Delegate::ApplyBlock(DBusAPI api) {
message_writer->AppendString(
base::CommandLine::ForCurrentProcess()->GetProgram().value());
message_writer->AppendUint32(0); // should be toplevel_xid
message_writer->AppendString(reason_);
message_writer->AppendString(description_);
{
uint32 flags = 0;
switch (type_) {
......@@ -229,7 +229,7 @@ void PowerSaveBlockerImpl::Delegate::ApplyBlock(DBusAPI api) {
// reason: The reason for the inhibit
message_writer->AppendString(
base::CommandLine::ForCurrentProcess()->GetProgram().value());
message_writer->AppendString(reason_);
message_writer->AppendString(description_);
break;
}
......@@ -325,9 +325,10 @@ DBusAPI PowerSaveBlockerImpl::Delegate::SelectAPI() {
return NO_API;
}
PowerSaveBlockerImpl::PowerSaveBlockerImpl(
PowerSaveBlockerType type, const std::string& reason)
: delegate_(new Delegate(type, reason)) {
PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
Reason reason,
const std::string& description)
: delegate_(new Delegate(type, description)) {
delegate_->Init();
}
......
......@@ -3172,26 +3172,22 @@ void WebContentsImpl::OnUpdateFaviconURL(
}
void WebContentsImpl::CreateAudioPowerSaveBlocker() {
// ChromeOS has its own way of handling power save blocks for media.
#if !defined(OS_CHROMEOS)
DCHECK(!audio_power_save_blocker_);
audio_power_save_blocker_ = PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, "Playing Audio");
#endif
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
PowerSaveBlocker::kReasonAudioPlayback, "Playing audio");
}
void WebContentsImpl::CreateVideoPowerSaveBlocker() {
// ChromeOS has its own way of handling power save blocks for media.
#if !defined(OS_CHROMEOS)
DCHECK(!video_power_save_blocker_);
DCHECK(!active_video_players_.empty());
video_power_save_blocker_ = PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, "Playing Video");
PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
PowerSaveBlocker::kReasonVideoPlayback, "Playing video");
#if defined(OS_ANDROID)
static_cast<PowerSaveBlockerImpl*>(video_power_save_blocker_.get())
->InitDisplaySleepBlocker(GetView()->GetNativeView());
#endif
#endif
}
void WebContentsImpl::MaybeReleasePowerSaveBlockers() {
......
......@@ -32,13 +32,26 @@ class CONTENT_EXPORT PowerSaveBlocker {
kPowerSaveBlockPreventDisplaySleep,
};
// Reasons why power-saving features may be blocked.
enum Reason {
// Audio is being played.
kReasonAudioPlayback,
// Video is being played.
kReasonVideoPlayback,
// Power-saving is blocked for some other reason.
kReasonOther,
};
virtual ~PowerSaveBlocker() = 0;
// Pass in the type of power save blocking desired. If multiple types of
// blocking are desired, instantiate one PowerSaveBlocker for each type.
// |reason| may be provided to the underlying system APIs on some platforms.
// |reason| and |description| (a more-verbose, human-readable justification of
// the blocking) may be provided to the underlying system APIs on some
// platforms.
static scoped_ptr<PowerSaveBlocker> Create(PowerSaveBlockerType type,
const std::string& reason);
Reason reason,
const std::string& description);
};
} // namespace content
......
......@@ -13,7 +13,7 @@ namespace extensions {
namespace {
const char kPowerSaveBlockerReason[] = "extension";
const char kPowerSaveBlockerDescription[] = "extension";
content::PowerSaveBlocker::PowerSaveBlockerType
LevelToPowerSaveBlockerType(core_api::power::Level level) {
......@@ -98,7 +98,9 @@ void PowerApiManager::UpdatePowerSaveBlocker() {
content::PowerSaveBlocker::PowerSaveBlockerType type =
LevelToPowerSaveBlockerType(new_level);
scoped_ptr<content::PowerSaveBlocker> new_blocker(
create_blocker_function_.Run(type, kPowerSaveBlockerReason));
create_blocker_function_.Run(type,
content::PowerSaveBlocker::kReasonOther,
kPowerSaveBlockerDescription));
power_save_blocker_.swap(new_blocker);
current_level_ = new_level;
}
......
......@@ -30,6 +30,7 @@ class PowerApiManager : public BrowserContextKeyedAPI,
public:
typedef base::Callback<scoped_ptr<content::PowerSaveBlocker>(
content::PowerSaveBlocker::PowerSaveBlockerType,
content::PowerSaveBlocker::Reason,
const std::string&)> CreateBlockerFunction;
static PowerApiManager* Get(content::BrowserContext* context);
......
......@@ -91,7 +91,8 @@ class PowerSaveBlockerStubManager {
// Creates a new PowerSaveBlockerStub of type |type|.
scoped_ptr<content::PowerSaveBlocker> CreateStub(
content::PowerSaveBlocker::PowerSaveBlockerType type,
const std::string& reason) {
content::PowerSaveBlocker::Reason reason,
const std::string& description) {
Request unblock_request = NONE;
switch (type) {
case content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment