blob: b46e57424ae2ace0f12e9e8953b53ea00da02aff [file] [log] [blame]
// Copyright (c) 2012 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.
#include "chromeos/power/power_state_override.h"
#include "base/bind.h"
#include "base/message_loop.h"
#include "base/time.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power_manager_client.h"
namespace {
// Frequency with which overrides are renewed.
const int kHeartbeatTimeInSecs = 300;
// Duration beyond |kHeartbeatTimeInSecs| for which overrides are requested.
// This should be long enough that we're able to renew the request before it
// expires, but short enough that the power manager won't end up honoring a
// stale request for a long time if Chrome crashes and orphans its requests.
const int kRequestSlackInSecs = 15;
} // namespace
namespace chromeos {
PowerStateOverride::PowerStateOverride(Mode mode)
: override_types_(0),
request_id_(0),
dbus_thread_manager_(DBusThreadManager::Get()) {
switch (mode) {
case BLOCK_DISPLAY_SLEEP:
override_types_ |= (PowerManagerClient::DISABLE_IDLE_DIM |
PowerManagerClient::DISABLE_IDLE_BLANK);
// fallthrough
case BLOCK_SYSTEM_SUSPEND:
override_types_ |= PowerManagerClient::DISABLE_IDLE_SUSPEND;
break;
default:
NOTREACHED() << "Unhandled mode " << mode;
}
dbus_thread_manager_->AddObserver(this);
// request_id_ = 0 will create a new override request.
// We do a post task here to ensure that this request runs 'after' our
// constructor is done. If not, there is a possibility (though only in
// tests at the moment) that the power state override request executes
// and returns before the constructor has finished executing. This will
// cause an AddRef and a Release, the latter destructing our current
// instance even before the constructor has finished executing (as it does
// in the DownloadExtensionTest browsertests currently).
MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&PowerStateOverride::CallRequestPowerStateOverrides, this));
heartbeat_.Start(FROM_HERE,
base::TimeDelta::FromSeconds(kHeartbeatTimeInSecs),
this,
&PowerStateOverride::CallRequestPowerStateOverrides);
}
PowerStateOverride::~PowerStateOverride() {
if (dbus_thread_manager_)
dbus_thread_manager_->RemoveObserver(this);
CancelRequest();
}
void PowerStateOverride::OnDBusThreadManagerDestroying(
DBusThreadManager* manager) {
DCHECK_EQ(manager, dbus_thread_manager_);
CancelRequest();
dbus_thread_manager_ = NULL;
}
void PowerStateOverride::SetRequestId(uint32 request_id) {
request_id_ = request_id;
}
void PowerStateOverride::CallRequestPowerStateOverrides() {
DCHECK(dbus_thread_manager_);
dbus_thread_manager_->GetPowerManagerClient()->RequestPowerStateOverrides(
request_id_,
base::TimeDelta::FromSeconds(
kHeartbeatTimeInSecs + kRequestSlackInSecs),
override_types_,
base::Bind(&PowerStateOverride::SetRequestId, this));
}
void PowerStateOverride::CancelRequest() {
if (request_id_) {
DCHECK(dbus_thread_manager_);
dbus_thread_manager_->GetPowerManagerClient()->
CancelPowerStateOverrides(request_id_);
request_id_ = 0;
}
}
} // namespace chromeos