diff options
author | mozartalouis <mozartalouis@google.com> | 2015-07-15 16:38:38 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-15 23:39:15 +0000 |
commit | 7e81ea890d6df774ad8c16868492f1d6d1ef4672 (patch) | |
tree | 0f7a8574122279fb6caf9b0d0062b2e0371954d4 | |
parent | c4222fae98c2c891a7206df770b29370f150af8a (diff) | |
download | chromium_src-7e81ea890d6df774ad8c16868492f1d6d1ef4672.zip chromium_src-7e81ea890d6df774ad8c16868492f1d6d1ef4672.tar.gz chromium_src-7e81ea890d6df774ad8c16868492f1d6d1ef4672.tar.bz2 |
ChromeOs Power Emulation Impl
BUG=499095
Here is the design doc for those who are wondering exactly what is being done:
https://docs.google.com/a/google.com/document/d/1X84nVB9r7Soe2VT2vB16wpE8TqFQ3J5tbkMDFmgVq-k/edit?usp=sharing
Review URL: https://codereview.chromium.org/1206733002
Cr-Commit-Position: refs/heads/master@{#338947}
-rw-r--r-- | chromeos/BUILD.gn | 2 | ||||
-rw-r--r-- | chromeos/chromeos.gyp | 6 | ||||
-rw-r--r-- | chromeos/dbus/fake_power_manager_client.cc | 33 | ||||
-rw-r--r-- | chromeos/dbus/fake_power_manager_client.h | 20 | ||||
-rw-r--r-- | chromeos/dbus/fake_power_manager_client_unittest.cc | 137 | ||||
-rw-r--r-- | chromeos/dbus/power_manager_client.cc | 224 |
6 files changed, 191 insertions, 231 deletions
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index 9521b8c..ea0a9d0 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn @@ -111,8 +111,6 @@ static_library("test_support_without_gmock") { sources = [ "dbus/fake_cros_disks_client.cc", "dbus/fake_cros_disks_client.h", - "dbus/fake_power_manager_client.cc", - "dbus/fake_power_manager_client.h", "dbus/fake_session_manager_client.cc", "dbus/fake_session_manager_client.h", "dbus/fake_shill_manager_client.cc", diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index 18548ab..e84d8cd 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp @@ -192,6 +192,8 @@ 'dbus/fake_peer_daemon_manager_client.h', 'dbus/fake_permission_broker_client.cc', 'dbus/fake_permission_broker_client.h', + 'dbus/fake_power_manager_client.cc', + 'dbus/fake_power_manager_client.h', 'dbus/fake_privet_daemon_manager_client.cc', 'dbus/fake_privet_daemon_manager_client.h', 'dbus/fake_shill_device_client.cc', @@ -472,6 +474,7 @@ 'dbus/cros_disks_client_unittest.cc', 'dbus/dbus_client_bundle_unittest.cc', 'dbus/fake_easy_unlock_client_unittest.cc', + 'dbus/fake_power_manager_client_unittest.cc', 'dbus/gsm_sms_client_unittest.cc', 'dbus/introspectable_client_unittest.cc', 'dbus/modem_messaging_client_unittest.cc', @@ -631,7 +634,6 @@ 'target_name': 'chromeos_test_support_without_gmock', 'type': 'static_library', 'export_dependent_settings': [ - # fake_power_manager_client.h includes pb.h files. 'power_manager_proto', ], 'dependencies': [ @@ -644,8 +646,6 @@ ], # If you edit the file list of this target, please edit BUILD.gn as well. 'sources': [ - 'dbus/fake_power_manager_client.cc', - 'dbus/fake_power_manager_client.h', 'dbus/fake_session_manager_client.cc', 'dbus/fake_session_manager_client.h', 'dbus/fake_shill_manager_client.cc', diff --git a/chromeos/dbus/fake_power_manager_client.cc b/chromeos/dbus/fake_power_manager_client.cc index 6c9a387..1809f3f 100644 --- a/chromeos/dbus/fake_power_manager_client.cc +++ b/chromeos/dbus/fake_power_manager_client.cc @@ -6,6 +6,8 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/location.h" +#include "base/thread_task_runner_handle.h" #include "base/time/time.h" namespace chromeos { @@ -16,13 +18,22 @@ FakePowerManagerClient::FakePowerManagerClient() num_set_policy_calls_(0), num_set_is_projecting_calls_(0), num_pending_suspend_readiness_callbacks_(0), - is_projecting_(false) { + is_projecting_(false), + weak_ptr_factory_(this) { } FakePowerManagerClient::~FakePowerManagerClient() { } void FakePowerManagerClient::Init(dbus::Bus* bus) { + props_.set_battery_percent(50); + props_.set_is_calculating_battery_time(false); + props_.set_battery_state( + power_manager::PowerSupplyProperties_BatteryState_DISCHARGING); + props_.set_external_power( + power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED); + props_.set_battery_time_to_full_sec(0); + props_.set_battery_time_to_empty_sec(18000); } void FakePowerManagerClient::AddObserver(Observer* observer) { @@ -34,7 +45,7 @@ void FakePowerManagerClient::RemoveObserver(Observer* observer) { } bool FakePowerManagerClient::HasObserver(const Observer* observer) const { - return false; + return observers_.HasObserver(observer); } void FakePowerManagerClient::SetRenderProcessManagerDelegate( @@ -63,6 +74,12 @@ void FakePowerManagerClient::IncreaseKeyboardBrightness() { } void FakePowerManagerClient::RequestStatusUpdate() { + // RequestStatusUpdate() calls and notifies the observers + // asynchronously on a real device. On the fake implementation, we call + // observers in a posted task to emulate the same behavior. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&FakePowerManagerClient::NotifyObservers, + weak_ptr_factory_.GetWeakPtr())); } void FakePowerManagerClient::RequestSuspend() { @@ -129,10 +146,20 @@ void FakePowerManagerClient::SendPowerButtonEvent( PowerButtonEventReceived(down, timestamp)); } +void FakePowerManagerClient::UpdatePowerProperties( + const power_manager::PowerSupplyProperties& power_props) { + props_ = power_props; + NotifyObservers(); +} + +void FakePowerManagerClient::NotifyObservers() { + FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(props_)); +} + void FakePowerManagerClient::HandleSuspendReadiness() { CHECK(num_pending_suspend_readiness_callbacks_ > 0); --num_pending_suspend_readiness_callbacks_; } -} // namespace chromeos +} // namespace chromeos diff --git a/chromeos/dbus/fake_power_manager_client.h b/chromeos/dbus/fake_power_manager_client.h index d6cd042..2b88833 100644 --- a/chromeos/dbus/fake_power_manager_client.h +++ b/chromeos/dbus/fake_power_manager_client.h @@ -9,8 +9,11 @@ #include "base/basictypes.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "base/observer_list.h" +#include "chromeos/chromeos_export.h" #include "chromeos/dbus/power_manager/policy.pb.h" +#include "chromeos/dbus/power_manager/power_supply_properties.pb.h" #include "chromeos/dbus/power_manager/suspend.pb.h" #include "chromeos/dbus/power_manager_client.h" @@ -19,12 +22,13 @@ namespace chromeos { // A fake implementation of PowerManagerClient. This remembers the policy passed // to SetPolicy() and the user of this class can inspect the last set policy by // get_policy(). -class FakePowerManagerClient : public PowerManagerClient { +class CHROMEOS_EXPORT FakePowerManagerClient : public PowerManagerClient { public: FakePowerManagerClient(); ~FakePowerManagerClient() override; power_manager::PowerManagementPolicy& policy() { return policy_; } + const power_manager::PowerSupplyProperties& props() const { return props_; } int num_request_restart_calls() const { return num_request_restart_calls_; } int num_request_shutdown_calls() const { return num_request_shutdown_calls_; } int num_set_policy_calls() const { return num_set_policy_calls_; } @@ -67,16 +71,26 @@ class FakePowerManagerClient : public PowerManagerClient { // Notifies observers that the power button has been pressed or released. void SendPowerButtonEvent(bool down, const base::TimeTicks& timestamp); + // Updates |props_| and notifies observers of its changes. + void UpdatePowerProperties( + const power_manager::PowerSupplyProperties& power_props); + private: // Callback that will be run by asynchronous suspend delays to report // readiness. void HandleSuspendReadiness(); + // Notifies |observers_| that |props_| has been updated. + void NotifyObservers(); + base::ObserverList<Observer> observers_; // Last policy passed to SetPolicy(). power_manager::PowerManagementPolicy policy_; + // Power status received from the power manager. + power_manager::PowerSupplyProperties props_; + // Number of times that various methods have been called. int num_request_restart_calls_; int num_request_shutdown_calls_; @@ -92,6 +106,10 @@ class FakePowerManagerClient : public PowerManagerClient { // Delegate for managing power consumption of Chrome's renderer processes. base::WeakPtr<RenderProcessManagerDelegate> render_process_manager_delegate_; + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<FakePowerManagerClient> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(FakePowerManagerClient); }; diff --git a/chromeos/dbus/fake_power_manager_client_unittest.cc b/chromeos/dbus/fake_power_manager_client_unittest.cc new file mode 100644 index 0000000..021459e --- /dev/null +++ b/chromeos/dbus/fake_power_manager_client_unittest.cc @@ -0,0 +1,137 @@ +// 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. + +#include "chromeos/dbus/fake_power_manager_client.h" + +#include "base/basictypes.h" +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace { + +const double kInitialBatteryPercent = 85; +const double kUpdatedBatteryPercent = 70; +const power_manager::PowerSupplyProperties_BatteryState kInitialBatteryState = + power_manager::PowerSupplyProperties_BatteryState_DISCHARGING; +const power_manager::PowerSupplyProperties_ExternalPower kInitialExternalPower = + power_manager::PowerSupplyProperties_ExternalPower_USB; + +class TestObserver : public PowerManagerClient::Observer { + public: + TestObserver() : num_power_changed_(0) {} + ~TestObserver() override {} + + const power_manager::PowerSupplyProperties& props() const { return props_; } + int num_power_changed() const { return num_power_changed_; } + + void ClearProps() { props_.Clear(); } + + void PowerChanged( + const power_manager::PowerSupplyProperties& proto) override { + props_ = proto; + ++num_power_changed_; + } + + private: + int num_power_changed_; + power_manager::PowerSupplyProperties props_; + + DISALLOW_COPY_AND_ASSIGN(TestObserver); +}; + +void SetTestProperties(power_manager::PowerSupplyProperties* props) { + props->set_battery_percent(kInitialBatteryPercent); + props->set_is_calculating_battery_time(true); + props->set_battery_state(kInitialBatteryState); + props->set_external_power(kInitialExternalPower); +} + +} // namespace + +TEST(FakePowerManagerClientTest, UpdatePowerPropertiesTest) { + // Checking to verify when UpdatePowerProperties is called, + // |props_| values are updated. + FakePowerManagerClient client; + power_manager::PowerSupplyProperties props; + + SetTestProperties(&props); + client.UpdatePowerProperties(props); + + EXPECT_EQ(kInitialBatteryPercent, client.props().battery_percent()); + EXPECT_TRUE(client.props().is_calculating_battery_time()); + EXPECT_EQ(kInitialBatteryState, client.props().battery_state()); + EXPECT_EQ(kInitialExternalPower, client.props().external_power()); + + // Test if when the values are changed, the correct data is set in the + // FakePowerManagerClient. + props = client.props(); + props.set_battery_percent(kUpdatedBatteryPercent); + client.UpdatePowerProperties(props); + + EXPECT_EQ(kUpdatedBatteryPercent, client.props().battery_percent()); + EXPECT_TRUE(client.props().is_calculating_battery_time()); + EXPECT_EQ(kInitialBatteryState, client.props().battery_state()); + EXPECT_EQ(kInitialExternalPower, client.props().external_power()); +}; + +TEST(FakePowerManagerClientTest, NotifyObserversTest) { + FakePowerManagerClient client; + TestObserver test_observer; + + // Test adding observer. + client.AddObserver(&test_observer); + EXPECT_TRUE(client.HasObserver(&test_observer)); + + // Test if NotifyObservers() sends the correct values to |observer|. + // Check number of times NotifyObservers() is called. + power_manager::PowerSupplyProperties props; + SetTestProperties(&props); + client.UpdatePowerProperties(props); + + EXPECT_EQ(kInitialBatteryPercent, test_observer.props().battery_percent()); + EXPECT_TRUE(test_observer.props().is_calculating_battery_time()); + EXPECT_EQ(kInitialBatteryState, test_observer.props().battery_state()); + EXPECT_EQ(kInitialExternalPower, test_observer.props().external_power()); + EXPECT_EQ(1, test_observer.num_power_changed()); + + // Test if RequestStatusUpdate() will propagate the data to the observer. + // Check number of times NotifyObservers is called. + // RequestStatusUpdate posts to the current message loop. This is + // necessary because we want to make sure that NotifyObservers() is + // called as a result of RequestStatusUpdate(). + base::MessageLoopForUI message_loop; + test_observer.ClearProps(); + client.RequestStatusUpdate(); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(kInitialBatteryPercent, test_observer.props().battery_percent()); + EXPECT_TRUE(test_observer.props().is_calculating_battery_time()); + EXPECT_EQ(kInitialBatteryState, test_observer.props().battery_state()); + EXPECT_EQ(kInitialExternalPower, test_observer.props().external_power()); + EXPECT_EQ(2, test_observer.num_power_changed()); + + // Check when values are changed, the correct values are propagated to the + // observer + props = client.props(); + props.set_battery_percent(kUpdatedBatteryPercent); + props.set_external_power( + power_manager::PowerSupplyProperties_ExternalPower_AC); + client.UpdatePowerProperties(props); + + EXPECT_EQ(kUpdatedBatteryPercent, test_observer.props().battery_percent()); + EXPECT_TRUE(test_observer.props().is_calculating_battery_time()); + EXPECT_EQ(kInitialBatteryState, test_observer.props().battery_state()); + EXPECT_EQ(power_manager::PowerSupplyProperties_ExternalPower_AC, + test_observer.props().external_power()); + EXPECT_EQ(3, test_observer.num_power_changed()); + + // Test removing observer. + client.RemoveObserver(&test_observer); + EXPECT_FALSE(client.HasObserver(&test_observer)); +}; + +} // namespace chromeos diff --git a/chromeos/dbus/power_manager_client.cc b/chromeos/dbus/power_manager_client.cc index a5d2322..d3cbc81 100644 --- a/chromeos/dbus/power_manager_client.cc +++ b/chromeos/dbus/power_manager_client.cc @@ -20,6 +20,7 @@ #include "base/threading/platform_thread.h" #include "base/timer/timer.h" #include "chromeos/chromeos_switches.h" +#include "chromeos/dbus/fake_power_manager_client.h" #include "chromeos/dbus/power_manager/input_event.pb.h" #include "chromeos/dbus/power_manager/peripheral_battery_status.pb.h" #include "chromeos/dbus/power_manager/policy.pb.h" @@ -768,227 +769,6 @@ class PowerManagerClientImpl : public PowerManagerClient { DISALLOW_COPY_AND_ASSIGN(PowerManagerClientImpl); }; -// The PowerManagerClient implementation used on Linux desktop, -// which does nothing. -class PowerManagerClientStubImpl : public PowerManagerClient { - public: - PowerManagerClientStubImpl() - : discharging_(true), - battery_percentage_(40), - brightness_(50.0), - pause_count_(2), - cycle_count_(0), - num_pending_suspend_readiness_callbacks_(0), - weak_ptr_factory_(this) {} - - ~PowerManagerClientStubImpl() override {} - - int num_pending_suspend_readiness_callbacks() const { - return num_pending_suspend_readiness_callbacks_; - } - - // PowerManagerClient overrides: - void Init(dbus::Bus* bus) override { - ParseCommandLineSwitch(); - if (power_cycle_delay_ != base::TimeDelta()) { - update_timer_.Start(FROM_HERE, - power_cycle_delay_, - this, - &PowerManagerClientStubImpl::UpdateStatus); - } - } - - void AddObserver(Observer* observer) override { - observers_.AddObserver(observer); - } - - void RemoveObserver(Observer* observer) override { - observers_.RemoveObserver(observer); - } - - bool HasObserver(const Observer* observer) const override { - return observers_.HasObserver(observer); - } - - void SetRenderProcessManagerDelegate( - base::WeakPtr<RenderProcessManagerDelegate> delegate) override {} - - void DecreaseScreenBrightness(bool allow_off) override { - POWER_LOG(USER) << "Requested to descrease screen brightness"; - SetBrightness(brightness_ - 5.0, true); - } - - void IncreaseScreenBrightness() override { - POWER_LOG(USER) << "Requested to increase screen brightness"; - SetBrightness(brightness_ + 5.0, true); - } - - void SetScreenBrightnessPercent(double percent, bool gradual) override { - POWER_LOG(USER) << "Requested to set screen brightness to " << percent - << "% " << (gradual ? "gradually" : "instantaneously"); - SetBrightness(percent, false); - } - - void GetScreenBrightnessPercent( - const GetScreenBrightnessPercentCallback& callback) override { - POWER_LOG(USER) << "Requested to get screen brightness"; - callback.Run(brightness_); - } - - void DecreaseKeyboardBrightness() override { - POWER_LOG(USER) << "Requested to descrease keyboard brightness"; - } - - void IncreaseKeyboardBrightness() override { - POWER_LOG(USER) << "Requested to increase keyboard brightness"; - } - - void RequestStatusUpdate() override { - POWER_LOG(USER) << "Requested status update"; - base::MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(&PowerManagerClientStubImpl::UpdateStatus, - weak_ptr_factory_.GetWeakPtr())); - } - - void RequestSuspend() override {} - void RequestRestart() override {} - void RequestShutdown() override {} - - void NotifyUserActivity(power_manager::UserActivityType type) override {} - void NotifyVideoActivity(bool is_fullscreen) override {} - void SetPolicy(const power_manager::PowerManagementPolicy& policy) override {} - void SetIsProjecting(bool is_projecting) override {} - base::Closure GetSuspendReadinessCallback() override { - num_pending_suspend_readiness_callbacks_++; - return base::Bind(&PowerManagerClientStubImpl::HandleSuspendReadiness, - weak_ptr_factory_.GetWeakPtr()); - } - int GetNumPendingSuspendReadinessCallbacks() override { - return num_pending_suspend_readiness_callbacks_; - } - - private: - void HandleSuspendReadiness() { - num_pending_suspend_readiness_callbacks_--; - } - - void UpdateStatus() { - if (pause_count_ > 0) { - pause_count_--; - if (pause_count_ == 2) - discharging_ = !discharging_; - } else { - if (discharging_) - battery_percentage_ -= (battery_percentage_ <= 10 ? 1 : 10); - else - battery_percentage_ += (battery_percentage_ >= 10 ? 10 : 1); - battery_percentage_ = std::min(std::max(battery_percentage_, 0), 100); - // We pause at 0 and 100% so that it's easier to check those conditions. - if (battery_percentage_ == 0 || battery_percentage_ == 100) { - pause_count_ = 4; - if (battery_percentage_ == 100) - cycle_count_ = (cycle_count_ + 1) % 3; - } - } - - const int kSecondsToEmptyFullBattery = 3 * 60 * 60; // 3 hours. - int64 remaining_battery_time = - std::max(1, battery_percentage_ * kSecondsToEmptyFullBattery / 100); - - props_.Clear(); - - switch (cycle_count_) { - case 0: - // Say that the system is charging with AC connected and - // discharging without any charger connected. - props_.set_external_power(discharging_ ? - power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED : - power_manager::PowerSupplyProperties_ExternalPower_AC); - break; - case 1: - // Say that the system is both charging and discharging on USB - // (i.e. a low-power charger). - props_.set_external_power( - power_manager::PowerSupplyProperties_ExternalPower_USB); - break; - case 2: - // Say that the system is both charging and discharging on AC. - props_.set_external_power( - power_manager::PowerSupplyProperties_ExternalPower_AC); - break; - default: - NOTREACHED() << "Unhandled cycle " << cycle_count_; - } - - if (battery_percentage_ == 100 && !discharging_) { - props_.set_battery_state( - power_manager::PowerSupplyProperties_BatteryState_FULL); - } else if (!discharging_) { - props_.set_battery_state( - power_manager::PowerSupplyProperties_BatteryState_CHARGING); - props_.set_battery_time_to_full_sec(std::max(static_cast<int64>(1), - kSecondsToEmptyFullBattery - remaining_battery_time)); - } else { - props_.set_battery_state( - power_manager::PowerSupplyProperties_BatteryState_DISCHARGING); - props_.set_battery_time_to_empty_sec(remaining_battery_time); - } - - props_.set_battery_percent(battery_percentage_); - props_.set_is_calculating_battery_time(pause_count_ > 1); - - FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(props_)); - } - - void SetBrightness(double percent, bool user_initiated) { - brightness_ = std::min(std::max(0.0, percent), 100.0); - int brightness_level = static_cast<int>(brightness_); - FOR_EACH_OBSERVER(Observer, observers_, - BrightnessChanged(brightness_level, user_initiated)); - } - - void ParseCommandLineSwitch() { - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (!command_line || !command_line->HasSwitch(switches::kPowerStub)) - return; - std::string option_str = - command_line->GetSwitchValueASCII(switches::kPowerStub); - base::StringPairs string_pairs; - base::SplitStringIntoKeyValuePairs(option_str, '=', ',', &string_pairs); - for (base::StringPairs::iterator iter = string_pairs.begin(); - iter != string_pairs.end(); ++iter) { - ParseOption((*iter).first, (*iter).second); - } - } - - void ParseOption(const std::string& arg0, const std::string& arg1) { - if (arg0 == "cycle" || arg0 == "interactive") { - int seconds = 1; - if (!arg1.empty()) - base::StringToInt(arg1, &seconds); - power_cycle_delay_ = base::TimeDelta::FromSeconds(seconds); - } - } - - base::TimeDelta power_cycle_delay_; // Time over which to cycle power state - bool discharging_; - int battery_percentage_; - double brightness_; - int pause_count_; - int cycle_count_; - base::ObserverList<Observer> observers_; - base::RepeatingTimer<PowerManagerClientStubImpl> update_timer_; - power_manager::PowerSupplyProperties props_; - - // Number of callbacks returned by GetSuspendReadinessCallback() but not yet - // invoked. - int num_pending_suspend_readiness_callbacks_; - - // Note: This should remain the last member so it'll be destroyed and - // invalidate its weak pointers before any other members are destroyed. - base::WeakPtrFactory<PowerManagerClientStubImpl> weak_ptr_factory_; -}; - PowerManagerClient::PowerManagerClient() { } @@ -1001,7 +781,7 @@ PowerManagerClient* PowerManagerClient::Create( if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) return new PowerManagerClientImpl(); DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); - return new PowerManagerClientStubImpl(); + return new FakePowerManagerClient(); } } // namespace chromeos |