diff options
Diffstat (limited to 'chromeos')
-rw-r--r-- | chromeos/chromeos.gyp | 45 | ||||
-rw-r--r-- | chromeos/power/power_state_override.cc | 80 | ||||
-rw-r--r-- | chromeos/power/power_state_override.h | 59 | ||||
-rw-r--r-- | chromeos/power/power_state_override_unittest.cc | 76 |
4 files changed, 239 insertions, 21 deletions
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index 48014f4..dbecc2b 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp @@ -124,6 +124,8 @@ 'display/output_configurator.h', 'network/network_sms_handler.cc', 'network/network_sms_handler.h', + 'power/power_state_override.cc', + 'power/power_state_override.h', ], 'link_settings': { 'libraries': [ @@ -209,27 +211,27 @@ ], }, { - 'target_name': 'chromeos_test_support_without_gmock', - 'type': 'static_library', - 'dependencies': [ - '../build/linux/system.gyp:dbus', - 'chromeos', - ], - 'sources': [ - 'dbus/mock_dbus_thread_manager_without_gmock.cc', - 'dbus/mock_dbus_thread_manager_without_gmock.h', - 'dbus/ibus/mock_ibus_client.cc', - 'dbus/ibus/mock_ibus_client.h', - 'dbus/ibus/mock_ibus_input_context_client.cc', - 'dbus/ibus/mock_ibus_input_context_client.h', - 'dbus/ibus/mock_ibus_engine_factory_service.cc', - 'dbus/ibus/mock_ibus_engine_factory_service.h', - 'dbus/ibus/mock_ibus_engine_service.cc', - 'dbus/ibus/mock_ibus_engine_service.h', - ], - 'include_dirs': [ - '..', - ], + 'target_name': 'chromeos_test_support_without_gmock', + 'type': 'static_library', + 'dependencies': [ + '../build/linux/system.gyp:dbus', + 'chromeos', + ], + 'sources': [ + 'dbus/mock_dbus_thread_manager_without_gmock.cc', + 'dbus/mock_dbus_thread_manager_without_gmock.h', + 'dbus/ibus/mock_ibus_client.cc', + 'dbus/ibus/mock_ibus_client.h', + 'dbus/ibus/mock_ibus_input_context_client.cc', + 'dbus/ibus/mock_ibus_input_context_client.h', + 'dbus/ibus/mock_ibus_engine_factory_service.cc', + 'dbus/ibus/mock_ibus_engine_factory_service.h', + 'dbus/ibus/mock_ibus_engine_service.cc', + 'dbus/ibus/mock_ibus_engine_service.h', + ], + 'include_dirs': [ + '..', + ], }, { 'target_name': 'chromeos_unittests', @@ -267,6 +269,7 @@ 'dbus/introspectable_client_unittest.cc', 'dbus/modem_messaging_client_unittest.cc', 'network/network_sms_handler_unittest.cc', + 'power/power_state_override_unittest.cc', ], 'include_dirs': [ '..', diff --git a/chromeos/power/power_state_override.cc b/chromeos/power/power_state_override.cc new file mode 100644 index 0000000..20582ca --- /dev/null +++ b/chromeos/power/power_state_override.cc @@ -0,0 +1,80 @@ +// 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), + weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { + 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 | + PowerManagerClient::DISABLE_IDLE_LID_SUSPEND); + break; + default: + NOTREACHED() << "Unhandled mode " << mode; + } + + // request_id_ = 0 will create a new override request. + CallRequestPowerStateOverrides(); + + heartbeat_.Start(FROM_HERE, + base::TimeDelta::FromSeconds(kHeartbeatTimeInSecs), + weak_ptr_factory_.GetWeakPtr(), + &PowerStateOverride::CallRequestPowerStateOverrides); +} + +PowerStateOverride::~PowerStateOverride() { + heartbeat_.Stop(); + + PowerManagerClient* power_manager = + DBusThreadManager::Get()->GetPowerManagerClient(); + if (power_manager) + power_manager->CancelPowerStateOverrides(request_id_); +} + +void PowerStateOverride::SetRequestId(uint32 request_id) { + request_id_ = request_id; +} + +void PowerStateOverride::CallRequestPowerStateOverrides() { + PowerManagerClient* power_manager = + DBusThreadManager::Get()->GetPowerManagerClient(); + if (power_manager) { + power_manager->RequestPowerStateOverrides( + request_id_, + kHeartbeatTimeInSecs + kRequestSlackInSecs, + override_types_, + base::Bind(&PowerStateOverride::SetRequestId, + weak_ptr_factory_.GetWeakPtr())); + } +} + +} // namespace chromeos diff --git a/chromeos/power/power_state_override.h b/chromeos/power/power_state_override.h new file mode 100644 index 0000000..4e2fab9 --- /dev/null +++ b/chromeos/power/power_state_override.h @@ -0,0 +1,59 @@ +// 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. + +#ifndef CHROMEOS_POWER_POWER_STATE_OVERRIDE_H_ +#define CHROMEOS_POWER_POWER_STATE_OVERRIDE_H_ + +#include "base/basictypes.h" +#include "base/memory/weak_ptr.h" +#include "base/timer.h" +#include "chromeos/chromeos_export.h" + +namespace chromeos { + +// This class overrides the current power state on the machine, disabling +// a set of power management features. +class CHROMEOS_EXPORT PowerStateOverride { + public: + enum Mode { + // Blocks the screen from being dimmed or blanked due to user inactivity. + // Also implies BLOCK_SYSTEM_SUSPEND. + BLOCK_DISPLAY_SLEEP, + + // Blocks the system from being suspended due to user inactivity or (in the + // case of a laptop) the lid being closed. + BLOCK_SYSTEM_SUSPEND, + }; + + explicit PowerStateOverride(Mode mode); + ~PowerStateOverride(); + + private: + // Callback from RequestPowerStateOverride which receives our request_id. + void SetRequestId(uint32 request_id); + + // Actually make a call to power manager; we need this to be able to post a + // delayed task since we cannot call back into power manager from Heartbeat + // since the last request has just been completed at that point. + void CallRequestPowerStateOverrides(); + + // Bitmap containing requested override types from + // PowerManagerClient::PowerStateOverrideType. + uint32 override_types_; + + // Outstanding override request ID, or 0 if there is no outstanding request. + uint32 request_id_; + + // Periodically invokes CallRequestPowerStateOverrides() to refresh the + // override. + base::RepeatingTimer<PowerStateOverride> heartbeat_; + + base::WeakPtrFactory<PowerStateOverride> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(PowerStateOverride); +}; + +} // namespace chromeos + +#endif // CHROMEOS_POWER_POWER_STATE_OVERRIDE_H_ diff --git a/chromeos/power/power_state_override_unittest.cc b/chromeos/power/power_state_override_unittest.cc new file mode 100644 index 0000000..3deaab9 --- /dev/null +++ b/chromeos/power/power_state_override_unittest.cc @@ -0,0 +1,76 @@ +// 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/message_loop.h" +#include "chromeos/dbus/mock_power_manager_client.h" +#include "chromeos/dbus/mock_dbus_thread_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; +using ::testing::Mock; +using ::testing::SaveArg; + +namespace chromeos { + +class PowerStateOverrideTest : public testing::Test { + protected: + virtual void SetUp() { + MockDBusThreadManager* dbus_manager = new MockDBusThreadManager; + DBusThreadManager::InitializeForTesting(dbus_manager); + power_manager_client_ = dbus_manager->mock_power_manager_client(); + } + + virtual void TearDown() { + DBusThreadManager::Shutdown(); + } + + protected: + // Needed for PowerStateOverride's timer. + MessageLoop message_loop_; + + MockPowerManagerClient* power_manager_client_; // not owned +}; + +TEST_F(PowerStateOverrideTest, AddAndRemoveOverrides) { + // An arbitrary ID to return in response to a request with ID 0. + const uint32 kRequestId = 10; + + // Override bitmaps corresponding to different modes. + const uint32 kDisplayOverrides = + PowerManagerClient::DISABLE_IDLE_DIM | + PowerManagerClient::DISABLE_IDLE_BLANK | + PowerManagerClient::DISABLE_IDLE_SUSPEND | + PowerManagerClient::DISABLE_IDLE_LID_SUSPEND; + const uint32 kSystemOverrides = + PowerManagerClient::DISABLE_IDLE_SUSPEND | + PowerManagerClient::DISABLE_IDLE_LID_SUSPEND; + + // Block display sleep and pass a request ID to the callback. + chromeos::PowerStateRequestIdCallback request_id_callback; + EXPECT_CALL(*power_manager_client_, + RequestPowerStateOverrides(0, _, kDisplayOverrides, _)) + .WillOnce(SaveArg<3>(&request_id_callback)); + scoped_ptr<PowerStateOverride> override( + new PowerStateOverride(PowerStateOverride::BLOCK_DISPLAY_SLEEP)); + request_id_callback.Run(kRequestId); + + // The request should be canceled when the PowerStateOverride is destroyed. + EXPECT_CALL(*power_manager_client_, CancelPowerStateOverrides(kRequestId)); + override.reset(); + + // Now send a request to just block the system from suspending. + Mock::VerifyAndClearExpectations(power_manager_client_); + EXPECT_CALL(*power_manager_client_, + RequestPowerStateOverrides(0, _, kSystemOverrides, _)) + .WillOnce(SaveArg<3>(&request_id_callback)); + override.reset( + new PowerStateOverride(PowerStateOverride::BLOCK_SYSTEM_SUSPEND)); + request_id_callback.Run(kRequestId); + EXPECT_CALL(*power_manager_client_, CancelPowerStateOverrides(kRequestId)); + override.reset(); +} + +} // namespace chromeos |