1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162

base / power_monitor / power_monitor.h [blame]

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_POWER_MONITOR_POWER_MONITOR_H_
#define BASE_POWER_MONITOR_POWER_MONITOR_H_

#include <memory>

#include "base/base_export.h"
#include "base/no_destructor.h"
#include "base/observer_list_threadsafe.h"
#include "base/power_monitor/power_observer.h"
#include "base/time/time.h"
#include "base/trace_event/base_tracing.h"
#include "build/build_config.h"

namespace base {

class PowerMonitorSource;

// A class used to monitor the power state change and notify the observers about
// the change event. The threading model of this class is as follows:
// Once initialized, it is threadsafe. However, the client must ensure that
// initialization happens before any other methods are invoked, including
// IsInitialized(). IsInitialized() exists only as a convenience for detection
// of test contexts where the PowerMonitor global is never created.
class BASE_EXPORT PowerMonitor {
 public:
  static PowerMonitor* GetInstance();

  // Initializes global PowerMonitor state. Takes ownership of |source|, which
  // will be leaked on process teardown. May only be called once. Not threadsafe
  // - no other PowerMonitor methods may be called on any thread while calling
  // Initialize(). |source| must not be nullptr.
  void Initialize(std::unique_ptr<PowerMonitorSource> source);

  PowerMonitor(const PowerMonitor&) = delete;
  PowerMonitor& operator=(const PowerMonitor&) = delete;

  // Returns true if Initialize() has been called. Safe to call on any thread,
  // but must not be called while Initialize() or ShutdownForTesting() is being
  // invoked.
  bool IsInitialized() const;

  // Add and remove an observer.
  // Can be called from any thread. |observer| is notified on the sequence
  // from which it was registered.
  // Must not be called from within a notification callback.
  //
  // It is safe to add observers before the PowerMonitor is initialized. It is
  // safe to remove an observer even if it was not added as an observer.
  void AddPowerSuspendObserver(PowerSuspendObserver* observer);
  void RemovePowerSuspendObserver(PowerSuspendObserver* observer);
  void AddPowerStateObserver(PowerStateObserver* observer);
  void RemovePowerStateObserver(PowerStateObserver* observer);
  void AddPowerThermalObserver(PowerThermalObserver* observer);
  void RemovePowerThermalObserver(PowerThermalObserver* observer);

  // Atomically add a PowerSuspendObserver and read the current power suspended
  // state. This variant must be used to avoid race between adding an observer
  // and reading the power state. The following code would be racy:
  //    AddOPowerSuspendbserver(...);
  //    if (PowerMonitor::IsSystemSuspended()) { ... }
  //
  // Returns true if the system is currently suspended.
  bool AddPowerSuspendObserverAndReturnSuspendedState(
      PowerSuspendObserver* observer);
  // Returns true if the system is on-battery.
  bool AddPowerStateObserverAndReturnOnBatteryState(
      PowerStateObserver* observer);
  PowerStateObserver::BatteryPowerStatus
  AddPowerStateObserverAndReturnBatteryPowerStatus(
      PowerStateObserver* observer);
  // Returns the power thermal state.
  PowerThermalObserver::DeviceThermalState
  AddPowerStateObserverAndReturnPowerThermalState(
      PowerThermalObserver* observer);

  // Is the computer currently on battery power. May only be called if the
  // PowerMonitor has been initialized.
  bool IsOnBatteryPower() const;

  // Returns the current state of the battery power, that can be unknown if the
  // value isn't initialized yet. May only be called if the PowerMonitor has
  // been initialized.
  PowerStateObserver::BatteryPowerStatus GetBatteryPowerStatus() const;

  // Returns the time of the last system resume. If no system suspend/resume was
  // observed, returns an empty time. If the system is currently suspended,
  // returns TimeTicks::Max().
  TimeTicks GetLastSystemResumeTime() const;

  // Read the current DeviceThermalState if known. Can be called on any thread.
  // May only be called if the PowerMonitor has been initialized.
  PowerThermalObserver::DeviceThermalState GetCurrentThermalState() const;

  // Update the result of thermal state.
  void SetCurrentThermalState(PowerThermalObserver::DeviceThermalState state);

#if BUILDFLAG(IS_ANDROID)
  // Read and return the current remaining battery capacity (microampere-hours).
  // Only supported with a device power source (i.e. not in child processes in
  // Chrome) and on devices with Android >= Lollipop as well as a power supply
  // that supports this counter. Returns 0 if unsupported.
  int GetRemainingBatteryCapacity() const;
#endif  // BUILDFLAG(IS_ANDROID)

  // Uninitializes the PowerMonitor. Should be called at the end of any unit
  // test that mocks out the PowerMonitor, to avoid affecting subsequent tests.
  // There must be no live observers when invoked. Safe to call even if the
  // PowerMonitor hasn't been initialized.
  void ShutdownForTesting();

 private:
  friend class PowerMonitorSource;
  friend class base::NoDestructor<PowerMonitor>;

  PowerMonitor();
  ~PowerMonitor();

  const PowerMonitorSource* Source() const;

  void NotifyPowerStateChange(bool on_battery_power);
  void NotifyPowerStateChange(
      PowerStateObserver::BatteryPowerStatus battery_power_status);
  void NotifySuspend();
  void NotifyResume();
  void NotifyThermalStateChange(
      PowerThermalObserver::DeviceThermalState new_state);
  void NotifySpeedLimitChange(int speed_limit);

  bool is_system_suspended_ GUARDED_BY(is_system_suspended_lock_) = false;
  mutable Lock is_system_suspended_lock_;
  TimeTicks last_system_resume_time_ GUARDED_BY(is_system_suspended_lock_);

  PowerStateObserver::BatteryPowerStatus battery_power_status_
      GUARDED_BY(battery_power_status_lock_) =
          PowerStateObserver::BatteryPowerStatus::kUnknown;

  mutable Lock battery_power_status_lock_;

  perfetto::NamedTrack process_track_;
  PowerThermalObserver::DeviceThermalState power_thermal_state_
      GUARDED_BY(power_thermal_state_lock_) =
          PowerThermalObserver::DeviceThermalState::kUnknown;
  int speed_limit_ GUARDED_BY(power_thermal_state_lock_) =
      PowerThermalObserver::kSpeedLimitMax;
  Lock power_thermal_state_lock_;

  scoped_refptr<ObserverListThreadSafe<PowerStateObserver>>
      power_state_observers_;
  scoped_refptr<ObserverListThreadSafe<PowerSuspendObserver>>
      power_suspend_observers_;
  scoped_refptr<ObserverListThreadSafe<PowerThermalObserver>>
      thermal_state_observers_;
  std::unique_ptr<PowerMonitorSource> source_;
};

}  // namespace base

#endif  // BASE_POWER_MONITOR_POWER_MONITOR_H_