Commit fe34b817 authored by Yury Khmel's avatar Yury Khmel Committed by Commit Bot

arc: add interface to request power mode

This adds notifications from ARC about power mode changes and request to
read current state.
Android part: ag/12863924

DD: go/arc_power_control

BUG=b:170982650
TEST=In context of prototype.

Change-Id: I4593eb8284d8473a249d71f00aa5c979bd1c3bdf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2480707Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarYusuke Sato <yusukes@chromium.org>
Commit-Queue: Yury Khmel <khmel@google.com>
Auto-Submit: Yury Khmel <khmel@google.com>
Cr-Commit-Position: refs/heads/master@{#818814}
parent 4a1b513d
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Next MinVersion: 6 // Next MinVersion: 7
module arc.mojom; module arc.mojom;
...@@ -19,12 +19,42 @@ enum DisplayWakeLockType { ...@@ -19,12 +19,42 @@ enum DisplayWakeLockType {
DIM = 1 DIM = 1
}; };
// Next method ID: 4 // Enumerates the types of wakefullness modes.
// Must match to PowerManager.WAKEFULNESS_* constants.
[Extensible]
enum WakefulnessMode {
// Device mode is unknown.
UNKNOWN = -1,
// The device is asleep. It can only be awoken.
// The device typically passes through the dozing state first.
ASLEEP = 0,
// The device is fully awake. It can be put to sleep.
// When the user activity timeout expires, the device may start dreaming
// or go to sleep.
AWAKE,
// The device is dreaming. It can be awoken which ends the dream.
DREAMING,
// The device is dozing. It is almost asleep but is allowing a special
// low-power "doze" dream to run which keeps the display on but lets the
// application processor be suspended. It can be awoken which ends the
// dream.The device fully goes to sleep if the dream cannot be started or
// ends on its own.
DOZING
};
// Next method ID: 5
interface PowerHost { interface PowerHost {
// Acquire and release wake locks on the host side. // Acquire and release wake locks on the host side.
OnAcquireDisplayWakeLock@0(DisplayWakeLockType type); OnAcquireDisplayWakeLock@0(DisplayWakeLockType type);
OnReleaseDisplayWakeLock@1(DisplayWakeLockType type); OnReleaseDisplayWakeLock@1(DisplayWakeLockType type);
// Notifies wakefulness mode is changed.
[MinVersion=6] OnWakefulnessChanged@5(WakefulnessMode mode);
// Checks if there is a display on. // Checks if there is a display on.
[MinVersion=1] IsDisplayOn@2() => (bool is_on); [MinVersion=1] IsDisplayOn@2() => (bool is_on);
...@@ -33,7 +63,7 @@ interface PowerHost { ...@@ -33,7 +63,7 @@ interface PowerHost {
[MinVersion=3] OnScreenBrightnessUpdateRequest@3(double percent); [MinVersion=3] OnScreenBrightnessUpdateRequest@3(double percent);
}; };
// Next method ID: 7 // Next method ID: 8
interface PowerInstance { interface PowerInstance {
// DEPRECATED: Please use Init@5 instead. // DEPRECATED: Please use Init@5 instead.
InitDeprecated@0(pending_remote<PowerHost> host_remote); InitDeprecated@0(pending_remote<PowerHost> host_remote);
...@@ -59,4 +89,7 @@ interface PowerInstance { ...@@ -59,4 +89,7 @@ interface PowerInstance {
// TODO(b/136427446): Rearchitect ARC power info management with more // TODO(b/136427446): Rearchitect ARC power info management with more
// explicit data / event passing. // explicit data / event passing.
[MinVersion=5] PowerSupplyInfoChanged@6(); [MinVersion=5] PowerSupplyInfoChanged@6();
// Requests current wakefulness mode.
[MinVersion=6] GetWakefulnessMode@7() => (WakefulnessMode mode);
}; };
...@@ -134,6 +134,14 @@ ArcPowerBridge::~ArcPowerBridge() { ...@@ -134,6 +134,14 @@ ArcPowerBridge::~ArcPowerBridge() {
arc_bridge_service_->power()->SetHost(nullptr); arc_bridge_service_->power()->SetHost(nullptr);
} }
void ArcPowerBridge::AddObserver(Observer* observer) {
observer_list_.AddObserver(observer);
}
void ArcPowerBridge::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
}
void ArcPowerBridge::SetUserIdHash(const std::string& user_id_hash) { void ArcPowerBridge::SetUserIdHash(const std::string& user_id_hash) {
user_id_hash_ = user_id_hash; user_id_hash_ = user_id_hash;
} }
...@@ -359,6 +367,11 @@ void ArcPowerBridge::OnGetScreenBrightnessPercent( ...@@ -359,6 +367,11 @@ void ArcPowerBridge::OnGetScreenBrightnessPercent(
UpdateAndroidScreenBrightness(percent.value()); UpdateAndroidScreenBrightness(percent.value());
} }
void ArcPowerBridge::OnWakefulnessChanged(mojom::WakefulnessMode mode) {
for (auto& observer : observer_list_)
observer.OnWakefulnessChanged(mode);
}
void ArcPowerBridge::UpdateAndroidScreenBrightness(double percent) { void ArcPowerBridge::UpdateAndroidScreenBrightness(double percent) {
mojom::PowerInstance* power_instance = ARC_GET_INSTANCE_FOR_METHOD( mojom::PowerInstance* power_instance = ARC_GET_INSTANCE_FOR_METHOD(
arc_bridge_service_->power(), UpdateScreenBrightnessSettings); arc_bridge_service_->power(), UpdateScreenBrightnessSettings);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <string> #include <string>
#include "base/macros.h" #include "base/macros.h"
#include "base/observer_list.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "chromeos/dbus/concierge_client.h" #include "chromeos/dbus/concierge_client.h"
...@@ -38,6 +39,12 @@ class ArcPowerBridge : public KeyedService, ...@@ -38,6 +39,12 @@ class ArcPowerBridge : public KeyedService,
public display::DisplayConfigurator::Observer, public display::DisplayConfigurator::Observer,
public mojom::PowerHost { public mojom::PowerHost {
public: public:
class Observer : public base::CheckedObserver {
public:
// Notifies that wakefulness mode is changed.
virtual void OnWakefulnessChanged(mojom::WakefulnessMode mode) = 0;
};
// Returns singleton instance for the given BrowserContext, // Returns singleton instance for the given BrowserContext,
// or nullptr if the browser |context| is not allowed to use ARC. // or nullptr if the browser |context| is not allowed to use ARC.
static ArcPowerBridge* GetForBrowserContext(content::BrowserContext* context); static ArcPowerBridge* GetForBrowserContext(content::BrowserContext* context);
...@@ -46,6 +53,9 @@ class ArcPowerBridge : public KeyedService, ...@@ -46,6 +53,9 @@ class ArcPowerBridge : public KeyedService,
ArcBridgeService* bridge_service); ArcBridgeService* bridge_service);
~ArcPowerBridge() override; ~ArcPowerBridge() override;
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
void SetUserIdHash(const std::string& user_id_hash); void SetUserIdHash(const std::string& user_id_hash);
// If |notify_brightness_timer_| is set, runs it and returns true. Returns // If |notify_brightness_timer_| is set, runs it and returns true. Returns
...@@ -75,6 +85,7 @@ class ArcPowerBridge : public KeyedService, ...@@ -75,6 +85,7 @@ class ArcPowerBridge : public KeyedService,
void OnReleaseDisplayWakeLock(mojom::DisplayWakeLockType type) override; void OnReleaseDisplayWakeLock(mojom::DisplayWakeLockType type) override;
void IsDisplayOn(IsDisplayOnCallback callback) override; void IsDisplayOn(IsDisplayOnCallback callback) override;
void OnScreenBrightnessUpdateRequest(double percent) override; void OnScreenBrightnessUpdateRequest(double percent) override;
void OnWakefulnessChanged(mojom::WakefulnessMode mode) override;
void SetWakeLockProviderForTesting( void SetWakeLockProviderForTesting(
mojo::Remote<device::mojom::WakeLockProvider> provider) { mojo::Remote<device::mojom::WakeLockProvider> provider) {
...@@ -127,6 +138,9 @@ class ArcPowerBridge : public KeyedService, ...@@ -127,6 +138,9 @@ class ArcPowerBridge : public KeyedService,
// about brightness changes. // about brightness changes.
base::OneShotTimer notify_brightness_timer_; base::OneShotTimer notify_brightness_timer_;
// List of observers.
base::ObserverList<Observer> observer_list_;
base::WeakPtrFactory<ArcPowerBridge> weak_ptr_factory_{this}; base::WeakPtrFactory<ArcPowerBridge> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcPowerBridge); DISALLOW_COPY_AND_ASSIGN(ArcPowerBridge);
......
...@@ -22,6 +22,37 @@ ...@@ -22,6 +22,37 @@
namespace arc { namespace arc {
namespace {
class TestObserver : public ArcPowerBridge::Observer {
public:
TestObserver() = default;
~TestObserver() override = default;
// ArcPowerBridge::Observer:
void OnWakefulnessChanged(mojom::WakefulnessMode mode) override {
last_mode_ = mode;
++update_count_;
}
int GetUpdateCountAndReset() {
const int update_count = update_count_;
update_count_ = 0;
return update_count;
}
mojom::WakefulnessMode last_mode() const { return last_mode_; }
private:
int update_count_ = 0;
mojom::WakefulnessMode last_mode_ = mojom::WakefulnessMode::UNKNOWN;
TestObserver(TestObserver const&) = delete;
TestObserver& operator=(TestObserver const&) = delete;
};
} // namespace
using device::mojom::WakeLockType; using device::mojom::WakeLockType;
class ArcPowerBridgeTest : public testing::Test { class ArcPowerBridgeTest : public testing::Test {
...@@ -104,40 +135,43 @@ class ArcPowerBridgeTest : public testing::Test { ...@@ -104,40 +135,43 @@ class ArcPowerBridgeTest : public testing::Test {
return chromeos::FakePowerManagerClient::Get(); return chromeos::FakePowerManagerClient::Get();
} }
FakePowerInstance* power_instance() { return power_instance_.get(); }
ArcPowerBridge* power_bridge() { return power_bridge_.get(); }
private:
base::test::TaskEnvironment task_environment_; base::test::TaskEnvironment task_environment_;
std::unique_ptr<ArcBridgeService> bridge_service_; std::unique_ptr<ArcBridgeService> bridge_service_;
std::unique_ptr<FakePowerInstance> power_instance_; std::unique_ptr<FakePowerInstance> power_instance_;
std::unique_ptr<ArcPowerBridge> power_bridge_; std::unique_ptr<ArcPowerBridge> power_bridge_;
private:
std::unique_ptr<device::TestWakeLockProvider> wake_lock_provider_; std::unique_ptr<device::TestWakeLockProvider> wake_lock_provider_;
DISALLOW_COPY_AND_ASSIGN(ArcPowerBridgeTest); DISALLOW_COPY_AND_ASSIGN(ArcPowerBridgeTest);
}; };
TEST_F(ArcPowerBridgeTest, SuspendAndResume) { TEST_F(ArcPowerBridgeTest, SuspendAndResume) {
ASSERT_EQ(0, power_instance_->num_suspend()); ASSERT_EQ(0, power_instance()->num_suspend());
ASSERT_EQ(0, power_instance_->num_resume()); ASSERT_EQ(0, power_instance()->num_resume());
// When powerd notifies Chrome that the system is about to suspend, // When powerd notifies Chrome that the system is about to suspend,
// ArcPowerBridge should notify Android and take a suspend readiness callback // ArcPowerBridge should notify Android and take a suspend readiness callback
// to defer the suspend operation. // to defer the suspend operation.
power_manager_client()->SendSuspendImminent( power_manager_client()->SendSuspendImminent(
power_manager::SuspendImminent_Reason_OTHER); power_manager::SuspendImminent_Reason_OTHER);
EXPECT_EQ(1, power_instance_->num_suspend()); EXPECT_EQ(1, power_instance()->num_suspend());
EXPECT_EQ(0, power_instance_->num_resume()); EXPECT_EQ(0, power_instance()->num_resume());
EXPECT_EQ(1, EXPECT_EQ(1,
power_manager_client()->num_pending_suspend_readiness_callbacks()); power_manager_client()->num_pending_suspend_readiness_callbacks());
// Simulate Android acknowledging that it's ready for the system to suspend. // Simulate Android acknowledging that it's ready for the system to suspend.
power_instance_->GetSuspendCallback().Run(); power_instance()->GetSuspendCallback().Run();
EXPECT_EQ(0, EXPECT_EQ(0,
power_manager_client()->num_pending_suspend_readiness_callbacks()); power_manager_client()->num_pending_suspend_readiness_callbacks());
power_manager_client()->SendSuspendDone(); power_manager_client()->SendSuspendDone();
EXPECT_EQ(1, power_instance_->num_suspend()); EXPECT_EQ(1, power_instance()->num_suspend());
EXPECT_EQ(1, power_instance_->num_resume()); EXPECT_EQ(1, power_instance()->num_resume());
// We shouldn't crash if the instance isn't ready. // We shouldn't crash if the instance isn't ready.
DestroyPowerInstance(); DestroyPowerInstance();
...@@ -149,21 +183,21 @@ TEST_F(ArcPowerBridgeTest, SuspendAndResume) { ...@@ -149,21 +183,21 @@ TEST_F(ArcPowerBridgeTest, SuspendAndResume) {
} }
TEST_F(ArcPowerBridgeTest, SetInteractive) { TEST_F(ArcPowerBridgeTest, SetInteractive) {
power_bridge_->OnPowerStateChanged(chromeos::DISPLAY_POWER_ALL_OFF); power_bridge()->OnPowerStateChanged(chromeos::DISPLAY_POWER_ALL_OFF);
EXPECT_FALSE(power_instance_->interactive()); EXPECT_FALSE(power_instance()->interactive());
power_bridge_->OnPowerStateChanged(chromeos::DISPLAY_POWER_ALL_ON); power_bridge()->OnPowerStateChanged(chromeos::DISPLAY_POWER_ALL_ON);
EXPECT_TRUE(power_instance_->interactive()); EXPECT_TRUE(power_instance()->interactive());
// We shouldn't crash if the instance isn't ready. // We shouldn't crash if the instance isn't ready.
DestroyPowerInstance(); DestroyPowerInstance();
power_bridge_->OnPowerStateChanged(chromeos::DISPLAY_POWER_ALL_OFF); power_bridge()->OnPowerStateChanged(chromeos::DISPLAY_POWER_ALL_OFF);
} }
TEST_F(ArcPowerBridgeTest, ScreenBrightness) { TEST_F(ArcPowerBridgeTest, ScreenBrightness) {
// Let the initial GetScreenBrightnessPercent() task run. // Let the initial GetScreenBrightnessPercent() task run.
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_DOUBLE_EQ(kInitialBrightness, power_instance_->screen_brightness()); EXPECT_DOUBLE_EQ(kInitialBrightness, power_instance()->screen_brightness());
// Check that Chrome OS brightness changes are passed to Android. // Check that Chrome OS brightness changes are passed to Android.
const double kUpdatedBrightness = 45.0; const double kUpdatedBrightness = 45.0;
...@@ -172,11 +206,11 @@ TEST_F(ArcPowerBridgeTest, ScreenBrightness) { ...@@ -172,11 +206,11 @@ TEST_F(ArcPowerBridgeTest, ScreenBrightness) {
change.set_percent(kUpdatedBrightness); change.set_percent(kUpdatedBrightness);
change.set_cause(power_manager::BacklightBrightnessChange_Cause_USER_REQUEST); change.set_cause(power_manager::BacklightBrightnessChange_Cause_USER_REQUEST);
power_manager_client()->SendScreenBrightnessChanged(change); power_manager_client()->SendScreenBrightnessChanged(change);
EXPECT_DOUBLE_EQ(kUpdatedBrightness, power_instance_->screen_brightness()); EXPECT_DOUBLE_EQ(kUpdatedBrightness, power_instance()->screen_brightness());
// Requests from Android should update the Chrome OS brightness. // Requests from Android should update the Chrome OS brightness.
const double kAndroidBrightness = 70.0; const double kAndroidBrightness = 70.0;
power_bridge_->OnScreenBrightnessUpdateRequest(kAndroidBrightness); power_bridge()->OnScreenBrightnessUpdateRequest(kAndroidBrightness);
EXPECT_DOUBLE_EQ(kAndroidBrightness, EXPECT_DOUBLE_EQ(kAndroidBrightness,
power_manager_client()->screen_brightness_percent()); power_manager_client()->screen_brightness_percent());
...@@ -185,9 +219,9 @@ TEST_F(ArcPowerBridgeTest, ScreenBrightness) { ...@@ -185,9 +219,9 @@ TEST_F(ArcPowerBridgeTest, ScreenBrightness) {
// the timer fires. // the timer fires.
change.set_percent(kAndroidBrightness); change.set_percent(kAndroidBrightness);
power_manager_client()->SendScreenBrightnessChanged(change); power_manager_client()->SendScreenBrightnessChanged(change);
EXPECT_DOUBLE_EQ(kUpdatedBrightness, power_instance_->screen_brightness()); EXPECT_DOUBLE_EQ(kUpdatedBrightness, power_instance()->screen_brightness());
ASSERT_TRUE(power_bridge_->TriggerNotifyBrightnessTimerForTesting()); ASSERT_TRUE(power_bridge()->TriggerNotifyBrightnessTimerForTesting());
EXPECT_DOUBLE_EQ(kAndroidBrightness, power_instance_->screen_brightness()); EXPECT_DOUBLE_EQ(kAndroidBrightness, power_instance()->screen_brightness());
} }
TEST_F(ArcPowerBridgeTest, PowerSupplyInfoChanged) { TEST_F(ArcPowerBridgeTest, PowerSupplyInfoChanged) {
...@@ -198,10 +232,10 @@ TEST_F(ArcPowerBridgeTest, PowerSupplyInfoChanged) { ...@@ -198,10 +232,10 @@ TEST_F(ArcPowerBridgeTest, PowerSupplyInfoChanged) {
power_manager_client()->UpdatePowerProperties(prop.value()); power_manager_client()->UpdatePowerProperties(prop.value());
// Check that Chrome OS power changes are passed to Android. // Check that Chrome OS power changes are passed to Android.
const int prev_call_count = power_instance_->num_power_supply_info(); const int prev_call_count = power_instance()->num_power_supply_info();
prop->set_battery_state(power_manager::PowerSupplyProperties::DISCHARGING); prop->set_battery_state(power_manager::PowerSupplyProperties::DISCHARGING);
power_manager_client()->UpdatePowerProperties(prop.value()); power_manager_client()->UpdatePowerProperties(prop.value());
EXPECT_EQ(1 + prev_call_count, power_instance_->num_power_supply_info()); EXPECT_EQ(1 + prev_call_count, power_instance()->num_power_supply_info());
} }
TEST_F(ArcPowerBridgeTest, DifferentWakeLocks) { TEST_F(ArcPowerBridgeTest, DifferentWakeLocks) {
...@@ -261,4 +295,19 @@ TEST_F(ArcPowerBridgeTest, ReleaseWakeLocksWhenInstanceClosed) { ...@@ -261,4 +295,19 @@ TEST_F(ArcPowerBridgeTest, ReleaseWakeLocksWhenInstanceClosed) {
EXPECT_EQ(1, GetActiveWakeLocks(WakeLockType::kPreventDisplaySleep)); EXPECT_EQ(1, GetActiveWakeLocks(WakeLockType::kPreventDisplaySleep));
} }
// Verifies that observer methods are called on power mode change.
TEST_F(ArcPowerBridgeTest, Observer) {
TestObserver test_observer;
power_bridge()->AddObserver(&test_observer);
EXPECT_EQ(0, test_observer.GetUpdateCountAndReset());
power_bridge()->OnWakefulnessChanged(mojom::WakefulnessMode::ASLEEP);
EXPECT_EQ(mojom::WakefulnessMode::ASLEEP, test_observer.last_mode());
EXPECT_EQ(1, test_observer.GetUpdateCountAndReset());
// Observe is removed, no calls are expected.
power_bridge()->RemoveObserver(&test_observer);
power_bridge()->OnWakefulnessChanged(mojom::WakefulnessMode::AWAKE);
EXPECT_EQ(mojom::WakefulnessMode::ASLEEP, test_observer.last_mode());
EXPECT_EQ(0, test_observer.GetUpdateCountAndReset());
}
} // namespace arc } // namespace arc
...@@ -52,4 +52,9 @@ void FakePowerInstance::PowerSupplyInfoChanged() { ...@@ -52,4 +52,9 @@ void FakePowerInstance::PowerSupplyInfoChanged() {
num_power_supply_info_++; num_power_supply_info_++;
} }
void FakePowerInstance::GetWakefulnessMode(
GetWakefulnessModeCallback callback) {
std::move(callback).Run(mojom::WakefulnessMode::AWAKE);
}
} // namespace arc } // namespace arc
...@@ -36,6 +36,7 @@ class FakePowerInstance : public mojom::PowerInstance { ...@@ -36,6 +36,7 @@ class FakePowerInstance : public mojom::PowerInstance {
void Resume() override; void Resume() override;
void UpdateScreenBrightnessSettings(double percent) override; void UpdateScreenBrightnessSettings(double percent) override;
void PowerSupplyInfoChanged() override; void PowerSupplyInfoChanged() override;
void GetWakefulnessMode(GetWakefulnessModeCallback callback) override;
private: private:
mojo::Remote<mojom::PowerHost> host_remote_; mojo::Remote<mojom::PowerHost> host_remote_;
......
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