fake_power_manager_client.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. // Copyright (c) 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "chromeos/dbus/power/fake_power_manager_client.h"
  5. #include <set>
  6. #include <utility>
  7. #include <vector>
  8. #include "base/bind.h"
  9. #include "base/callback.h"
  10. #include "base/callback_helpers.h"
  11. #include "base/containers/contains.h"
  12. #include "base/location.h"
  13. #include "base/logging.h"
  14. #include "base/posix/unix_domain_socket.h"
  15. #include "base/strings/string_util.h"
  16. #include "base/threading/thread_restrictions.h"
  17. #include "base/threading/thread_task_runner_handle.h"
  18. #include "base/time/time.h"
  19. #include "base/timer/timer.h"
  20. namespace chromeos {
  21. namespace {
  22. FakePowerManagerClient* g_instance = nullptr;
  23. // Minimum power for a USB power source to be classified as AC.
  24. constexpr double kUsbMinAcWatts = 24;
  25. // The time power manager will wait before resuspending from a dark resume.
  26. constexpr base::TimeDelta kDarkSuspendDelayTimeout = base::Seconds(20);
  27. // Callback fired when timer started through |StartArcTimer| expires. In
  28. // non-test environments this does a potentially blocking call on the UI
  29. // thread. However, the clients that exercise this code path don't run in
  30. // non-test environments.
  31. void ArcTimerExpirationCallback(int expiration_fd) {
  32. // The instance expects 8 bytes on the read end similar to what happens on
  33. // a timerfd expiration. The timerfd API expects this to be the number of
  34. // expirations, however, more than one expiration isn't tracked currently.
  35. const uint64_t timer_data = 1;
  36. if (!base::UnixDomainSocket::SendMsg(
  37. expiration_fd, &timer_data, sizeof(timer_data), std::vector<int>())) {
  38. PLOG(ERROR) << "Failed to indicate timer expiration to the instance";
  39. }
  40. }
  41. power_manager::BacklightBrightnessChange_Cause RequestCauseToChangeCause(
  42. power_manager::SetBacklightBrightnessRequest_Cause cause) {
  43. switch (cause) {
  44. case power_manager::SetBacklightBrightnessRequest_Cause_USER_REQUEST:
  45. return power_manager::BacklightBrightnessChange_Cause_USER_REQUEST;
  46. case power_manager::SetBacklightBrightnessRequest_Cause_MODEL:
  47. return power_manager::BacklightBrightnessChange_Cause_MODEL;
  48. }
  49. NOTREACHED() << "Unhandled brightness request cause " << cause;
  50. return power_manager::BacklightBrightnessChange_Cause_USER_REQUEST;
  51. }
  52. // Copied from Chrome's //base/time/time_now_posix.cc.
  53. // Returns count of |clk_id| in the form of a time delta. Returns an empty
  54. // time delta if |clk_id| isn't present on the system.
  55. base::TimeDelta ClockNow(clockid_t clk_id) {
  56. struct timespec ts;
  57. if (clock_gettime(clk_id, &ts) != 0) {
  58. NOTREACHED() << "clock_gettime(" << clk_id << ") failed.";
  59. return base::TimeDelta();
  60. }
  61. return base::TimeDelta::FromTimeSpec(ts);
  62. }
  63. std::string SysnameFromBluetoothAddress(const std::string& address) {
  64. return "/sys/class/power_supply/hid-" + base::ToLowerASCII(address) +
  65. "-battery";
  66. }
  67. } // namespace
  68. // static
  69. FakePowerManagerClient* FakePowerManagerClient::Get() {
  70. CHECK(g_instance);
  71. return g_instance;
  72. }
  73. FakePowerManagerClient::FakePowerManagerClient()
  74. : props_(power_manager::PowerSupplyProperties()), tick_clock_(nullptr) {
  75. CHECK(!g_instance);
  76. g_instance = this;
  77. props_->set_battery_percent(50);
  78. props_->set_is_calculating_battery_time(false);
  79. props_->set_battery_state(
  80. power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
  81. props_->set_external_power(
  82. power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED);
  83. props_->set_battery_time_to_full_sec(0);
  84. props_->set_battery_time_to_empty_sec(18000);
  85. }
  86. FakePowerManagerClient::~FakePowerManagerClient() {
  87. CHECK_EQ(g_instance, this);
  88. g_instance = nullptr;
  89. }
  90. void FakePowerManagerClient::AddObserver(Observer* observer) {
  91. observers_.AddObserver(observer);
  92. observer->PowerManagerBecameAvailable(true);
  93. observer->PowerManagerInitialized();
  94. }
  95. void FakePowerManagerClient::RemoveObserver(Observer* observer) {
  96. observers_.RemoveObserver(observer);
  97. }
  98. bool FakePowerManagerClient::HasObserver(const Observer* observer) const {
  99. return observers_.HasObserver(observer);
  100. }
  101. void FakePowerManagerClient::SetRenderProcessManagerDelegate(
  102. base::WeakPtr<RenderProcessManagerDelegate> delegate) {
  103. render_process_manager_delegate_ = delegate;
  104. }
  105. void FakePowerManagerClient::DecreaseScreenBrightness(bool allow_off) {}
  106. void FakePowerManagerClient::IncreaseScreenBrightness() {}
  107. void FakePowerManagerClient::SetScreenBrightness(
  108. const power_manager::SetBacklightBrightnessRequest& request) {
  109. screen_brightness_percent_ = request.percent();
  110. requested_screen_brightness_percent_ = request.percent();
  111. power_manager::BacklightBrightnessChange change;
  112. change.set_percent(request.percent());
  113. change.set_cause(RequestCauseToChangeCause(request.cause()));
  114. base::ThreadTaskRunnerHandle::Get()->PostTask(
  115. FROM_HERE,
  116. base::BindOnce(&FakePowerManagerClient::SendScreenBrightnessChanged,
  117. weak_ptr_factory_.GetWeakPtr(), change));
  118. }
  119. void FakePowerManagerClient::GetScreenBrightnessPercent(
  120. DBusMethodCallback<double> callback) {
  121. base::ThreadTaskRunnerHandle::Get()->PostTask(
  122. FROM_HERE,
  123. base::BindOnce(std::move(callback), screen_brightness_percent_));
  124. }
  125. void FakePowerManagerClient::DecreaseKeyboardBrightness() {}
  126. void FakePowerManagerClient::IncreaseKeyboardBrightness() {}
  127. void FakePowerManagerClient::GetKeyboardBrightnessPercent(
  128. DBusMethodCallback<double> callback) {
  129. base::ThreadTaskRunnerHandle::Get()->PostTask(
  130. FROM_HERE,
  131. base::BindOnce(std::move(callback), keyboard_brightness_percent_));
  132. }
  133. void FakePowerManagerClient::SetKeyboardBacklightToggledOff(bool toggled_off) {}
  134. void FakePowerManagerClient::GetKeyboardBacklightToggledOff(
  135. DBusMethodCallback<bool> callback) {}
  136. const absl::optional<power_manager::PowerSupplyProperties>&
  137. FakePowerManagerClient::GetLastStatus() {
  138. return props_;
  139. }
  140. void FakePowerManagerClient::RequestStatusUpdate() {
  141. // RequestStatusUpdate() calls and notifies the observers
  142. // asynchronously on a real device. On the fake implementation, we call
  143. // observers in a posted task to emulate the same behavior.
  144. base::ThreadTaskRunnerHandle::Get()->PostTask(
  145. FROM_HERE, base::BindOnce(&FakePowerManagerClient::NotifyObservers,
  146. weak_ptr_factory_.GetWeakPtr()));
  147. }
  148. void FakePowerManagerClient::RequestAllPeripheralBatteryUpdate() {}
  149. void FakePowerManagerClient::RequestThermalState() {}
  150. void FakePowerManagerClient::RequestSuspend() {}
  151. void FakePowerManagerClient::RequestRestart(
  152. power_manager::RequestRestartReason reason,
  153. const std::string& description) {
  154. ++num_request_restart_calls_;
  155. if (restart_callback_)
  156. std::move(restart_callback_).Run();
  157. }
  158. void FakePowerManagerClient::RequestShutdown(
  159. power_manager::RequestShutdownReason reason,
  160. const std::string& description) {
  161. ++num_request_shutdown_calls_;
  162. }
  163. void FakePowerManagerClient::NotifyUserActivity(
  164. power_manager::UserActivityType type) {
  165. if (user_activity_callback_)
  166. user_activity_callback_.Run();
  167. }
  168. void FakePowerManagerClient::NotifyVideoActivity(bool is_fullscreen) {
  169. video_activity_reports_.push_back(is_fullscreen);
  170. }
  171. void FakePowerManagerClient::NotifyWakeNotification() {
  172. ++num_wake_notification_calls_;
  173. }
  174. void FakePowerManagerClient::SetPolicy(
  175. const power_manager::PowerManagementPolicy& policy) {
  176. policy_ = policy;
  177. ++num_set_policy_calls_;
  178. if (power_policy_quit_closure_)
  179. std::move(power_policy_quit_closure_).Run();
  180. }
  181. void FakePowerManagerClient::SetIsProjecting(bool is_projecting) {
  182. ++num_set_is_projecting_calls_;
  183. is_projecting_ = is_projecting;
  184. }
  185. void FakePowerManagerClient::SetPowerSource(const std::string& id) {
  186. props_->set_external_power_source_id(id);
  187. props_->set_external_power(
  188. power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED);
  189. for (const auto& source : props_->available_external_power_source()) {
  190. if (source.id() == id) {
  191. props_->set_external_power(
  192. !source.active_by_default() || source.max_power() < kUsbMinAcWatts
  193. ? power_manager::PowerSupplyProperties_ExternalPower_USB
  194. : power_manager::PowerSupplyProperties_ExternalPower_AC);
  195. break;
  196. }
  197. }
  198. NotifyObservers();
  199. }
  200. void FakePowerManagerClient::SetBacklightsForcedOff(bool forced_off) {
  201. backlights_forced_off_ = forced_off;
  202. ++num_set_backlights_forced_off_calls_;
  203. power_manager::BacklightBrightnessChange change;
  204. change.set_percent(forced_off ? 0 : requested_screen_brightness_percent_);
  205. change.set_cause(
  206. forced_off ? power_manager::BacklightBrightnessChange_Cause_FORCED_OFF
  207. : power_manager::
  208. BacklightBrightnessChange_Cause_NO_LONGER_FORCED_OFF);
  209. if (enqueue_brightness_changes_on_backlights_forced_off_) {
  210. pending_screen_brightness_changes_.push(change);
  211. } else {
  212. screen_brightness_percent_ = change.percent();
  213. base::ThreadTaskRunnerHandle::Get()->PostTask(
  214. FROM_HERE,
  215. base::BindOnce(&FakePowerManagerClient::SendScreenBrightnessChanged,
  216. weak_ptr_factory_.GetWeakPtr(), change));
  217. }
  218. }
  219. void FakePowerManagerClient::GetBacklightsForcedOff(
  220. DBusMethodCallback<bool> callback) {
  221. base::ThreadTaskRunnerHandle::Get()->PostTask(
  222. FROM_HERE, base::BindOnce(std::move(callback), backlights_forced_off_));
  223. }
  224. void FakePowerManagerClient::GetSwitchStates(
  225. DBusMethodCallback<SwitchStates> callback) {
  226. base::ThreadTaskRunnerHandle::Get()->PostTask(
  227. FROM_HERE, base::BindOnce(std::move(callback),
  228. SwitchStates{lid_state_, tablet_mode_}));
  229. }
  230. void FakePowerManagerClient::GetInactivityDelays(
  231. DBusMethodCallback<power_manager::PowerManagementPolicy::Delays> callback) {
  232. base::ThreadTaskRunnerHandle::Get()->PostTask(
  233. FROM_HERE, base::BindOnce(std::move(callback), inactivity_delays_));
  234. }
  235. void FakePowerManagerClient::BlockSuspend(const base::UnguessableToken& token,
  236. const std::string& debug_info) {
  237. ++num_pending_suspend_readiness_callbacks_;
  238. }
  239. void FakePowerManagerClient::UnblockSuspend(
  240. const base::UnguessableToken& token) {
  241. CHECK_GT(num_pending_suspend_readiness_callbacks_, 0);
  242. --num_pending_suspend_readiness_callbacks_;
  243. }
  244. bool FakePowerManagerClient::SupportsAmbientColor() {
  245. return supports_ambient_color_;
  246. }
  247. void FakePowerManagerClient::CreateArcTimers(
  248. const std::string& tag,
  249. std::vector<std::pair<clockid_t, base::ScopedFD>> arc_timer_requests,
  250. DBusMethodCallback<std::vector<TimerId>> callback) {
  251. // Return error if tag is empty.
  252. if (tag.empty()) {
  253. base::ThreadTaskRunnerHandle::Get()->PostTask(
  254. FROM_HERE, base::BindOnce(std::move(callback), std::vector<TimerId>()));
  255. return;
  256. }
  257. // Just like the real implementation, delete any old timers associated with
  258. // |tag|.
  259. DeleteArcTimersInternal(tag);
  260. // First, ensure that there are no duplicate clocks in the arguments. Return
  261. // error if there are.
  262. std::set<clockid_t> seen_clock_ids;
  263. for (const auto& request : arc_timer_requests) {
  264. if (!seen_clock_ids.emplace(request.first).second) {
  265. base::ThreadTaskRunnerHandle::Get()->PostTask(
  266. FROM_HERE,
  267. base::BindOnce(std::move(callback), std::vector<TimerId>()));
  268. return;
  269. }
  270. }
  271. // For each request, create a timer id and map the timer id to the expiration
  272. // fd that will be written to on timer expiry.
  273. std::vector<TimerId> timer_ids;
  274. for (auto& request : arc_timer_requests) {
  275. // Insert is safe as |next_timer_id_| is always incremented.
  276. arc_timers_.emplace(
  277. next_timer_id_,
  278. std::make_pair(new base::OneShotTimer(), std::move(request.second)));
  279. timer_ids.emplace_back(next_timer_id_);
  280. next_timer_id_++;
  281. }
  282. // Associate timer ids with the client's tag. The insert is safe because
  283. // duplicate client tags are checked for earlier.
  284. client_timer_ids_[tag] = timer_ids;
  285. base::ThreadTaskRunnerHandle::Get()->PostTask(
  286. FROM_HERE, base::BindOnce(std::move(callback), std::move(timer_ids)));
  287. }
  288. void FakePowerManagerClient::StartArcTimer(
  289. TimerId timer_id,
  290. base::TimeTicks absolute_expiration_time,
  291. VoidDBusMethodCallback callback) {
  292. if (simulate_start_arc_timer_failure_) {
  293. base::ThreadTaskRunnerHandle::Get()->PostTask(
  294. FROM_HERE, base::BindOnce(std::move(callback), false));
  295. return;
  296. }
  297. auto it = arc_timers_.find(timer_id);
  298. if (it == arc_timers_.end()) {
  299. base::ThreadTaskRunnerHandle::Get()->PostTask(
  300. FROM_HERE, base::BindOnce(std::move(callback), false));
  301. return;
  302. }
  303. // Post task to run |callback| and indicate success to the caller.
  304. base::ThreadTaskRunnerHandle::Get()->PostTask(
  305. FROM_HERE, base::BindOnce(std::move(callback), true));
  306. // Post task to write to |clock_id|'s expiration fd. This will simulate the
  307. // timer expiring to the caller. Ignore delaying by
  308. // |absolute_expiration_time| for test purposes.
  309. base::TimeTicks current_ticks = GetCurrentBootTime();
  310. base::TimeDelta task_delay;
  311. if (absolute_expiration_time > current_ticks)
  312. task_delay = absolute_expiration_time - current_ticks;
  313. auto& timer = it->second.first;
  314. int expiration_fd = it->second.second.get();
  315. timer->Start(FROM_HERE, task_delay,
  316. base::BindOnce(&ArcTimerExpirationCallback, expiration_fd));
  317. }
  318. void FakePowerManagerClient::DeleteArcTimers(const std::string& tag,
  319. VoidDBusMethodCallback callback) {
  320. DeleteArcTimersInternal(tag);
  321. base::ThreadTaskRunnerHandle::Get()->PostTask(
  322. FROM_HERE, base::BindOnce(std::move(callback), true));
  323. }
  324. base::TimeDelta FakePowerManagerClient::GetDarkSuspendDelayTimeout() {
  325. return kDarkSuspendDelayTimeout;
  326. }
  327. void FakePowerManagerClient::RefreshBluetoothBattery(
  328. const std::string& address) {
  329. if (!base::Contains(peripheral_battery_refresh_levels_, address))
  330. return;
  331. for (auto& observer : observers_) {
  332. observer.PeripheralBatteryStatusReceived(
  333. SysnameFromBluetoothAddress(address), "somename",
  334. peripheral_battery_refresh_levels_[address],
  335. power_manager::
  336. PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_UNKNOWN,
  337. /*serial_number=*/"",
  338. /*active_update=*/true);
  339. }
  340. }
  341. void FakePowerManagerClient::SetExternalDisplayALSBrightness(bool enabled) {
  342. external_display_als_brightness_enabled_ = enabled;
  343. }
  344. void FakePowerManagerClient::GetExternalDisplayALSBrightness(
  345. DBusMethodCallback<bool> callback) {
  346. base::ThreadTaskRunnerHandle::Get()->PostTask(
  347. FROM_HERE, base::BindOnce(std::move(callback),
  348. external_display_als_brightness_enabled_));
  349. }
  350. // The real implementation of ChargeNowForAdaptiveCharging is just a simple
  351. // Dbus call without any callback, so there is not much to test for now.
  352. void FakePowerManagerClient::ChargeNowForAdaptiveCharging() {}
  353. bool FakePowerManagerClient::PopVideoActivityReport() {
  354. CHECK(!video_activity_reports_.empty());
  355. bool fullscreen = video_activity_reports_.front();
  356. video_activity_reports_.pop_front();
  357. return fullscreen;
  358. }
  359. void FakePowerManagerClient::SendSuspendImminent(
  360. power_manager::SuspendImminent::Reason reason) {
  361. for (auto& observer : observers_)
  362. observer.SuspendImminent(reason);
  363. if (render_process_manager_delegate_)
  364. render_process_manager_delegate_->SuspendImminent();
  365. }
  366. void FakePowerManagerClient::SendSuspendDone(base::TimeDelta sleep_duration) {
  367. if (render_process_manager_delegate_)
  368. render_process_manager_delegate_->SuspendDone();
  369. for (auto& observer : observers_)
  370. observer.SuspendDone(sleep_duration);
  371. }
  372. void FakePowerManagerClient::SendDarkSuspendImminent() {
  373. for (auto& observer : observers_)
  374. observer.DarkSuspendImminent();
  375. }
  376. void FakePowerManagerClient::SendScreenBrightnessChanged(
  377. const power_manager::BacklightBrightnessChange& change) {
  378. for (auto& observer : observers_)
  379. observer.ScreenBrightnessChanged(change);
  380. }
  381. void FakePowerManagerClient::SendKeyboardBrightnessChanged(
  382. const power_manager::BacklightBrightnessChange& change) {
  383. for (auto& observer : observers_)
  384. observer.KeyboardBrightnessChanged(change);
  385. }
  386. void FakePowerManagerClient::SendScreenIdleStateChanged(
  387. const power_manager::ScreenIdleState& proto) {
  388. for (auto& observer : observers_)
  389. observer.ScreenIdleStateChanged(proto);
  390. }
  391. void FakePowerManagerClient::SendPowerButtonEvent(
  392. bool down,
  393. const base::TimeTicks& timestamp) {
  394. for (auto& observer : observers_)
  395. observer.PowerButtonEventReceived(down, timestamp);
  396. }
  397. void FakePowerManagerClient::SetLidState(LidState state,
  398. const base::TimeTicks& timestamp) {
  399. lid_state_ = state;
  400. for (auto& observer : observers_)
  401. observer.LidEventReceived(state, timestamp);
  402. }
  403. void FakePowerManagerClient::SetTabletMode(TabletMode mode,
  404. const base::TimeTicks& timestamp) {
  405. tablet_mode_ = mode;
  406. for (auto& observer : observers_)
  407. observer.TabletModeEventReceived(mode, timestamp);
  408. }
  409. void FakePowerManagerClient::SetInactivityDelays(
  410. const power_manager::PowerManagementPolicy::Delays& delays) {
  411. inactivity_delays_ = delays;
  412. for (auto& observer : observers_)
  413. observer.InactivityDelaysChanged(delays);
  414. }
  415. void FakePowerManagerClient::UpdatePowerProperties(
  416. const power_manager::PowerSupplyProperties& power_props) {
  417. props_ = power_props;
  418. NotifyObservers();
  419. }
  420. void FakePowerManagerClient::NotifyObservers() {
  421. for (auto& observer : observers_)
  422. observer.PowerChanged(*props_);
  423. }
  424. void FakePowerManagerClient::DeleteArcTimersInternal(const std::string& tag) {
  425. // Retrieve all timer ids associated with |tag|. Delete all timers associated
  426. // with these timer ids.
  427. auto it = client_timer_ids_.find(tag);
  428. if (it == client_timer_ids_.end())
  429. return;
  430. for (auto timer_id : it->second)
  431. arc_timers_.erase(timer_id);
  432. client_timer_ids_.erase(it);
  433. }
  434. void FakePowerManagerClient::SetPowerPolicyQuitClosure(
  435. base::OnceClosure quit_closure) {
  436. power_policy_quit_closure_ = std::move(quit_closure);
  437. }
  438. bool FakePowerManagerClient::ApplyPendingScreenBrightnessChange() {
  439. if (pending_screen_brightness_changes_.empty())
  440. return false;
  441. power_manager::BacklightBrightnessChange change =
  442. pending_screen_brightness_changes_.front();
  443. pending_screen_brightness_changes_.pop();
  444. screen_brightness_percent_ = change.percent();
  445. SendScreenBrightnessChanged(change);
  446. return true;
  447. }
  448. // Returns time ticks from boot including time ticks spent during sleeping.
  449. base::TimeTicks FakePowerManagerClient::GetCurrentBootTime() {
  450. if (tick_clock_)
  451. return tick_clock_->NowTicks();
  452. return base::TimeTicks() + ClockNow(CLOCK_BOOTTIME);
  453. }
  454. } // namespace chromeos