Skip to content

Commit

Permalink
feat: add thermal states to powerMonitor (#38027)
Browse files Browse the repository at this point in the history
* feat: add thermal states to powerMonitor

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* update docs

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
  • Loading branch information
trop[bot] and nornagon committed May 1, 2023
1 parent 6b2a63f commit 912aa52
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 2 deletions.
30 changes: 29 additions & 1 deletion docs/api/power-monitor.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,30 @@ Emitted when the system changes to AC power.

Emitted when system changes to battery power.

### Event: 'thermal-state-change' _macOS_

* `state` string - The system's new thermal state. Can be `unknown`, `nominal`, `fair`, `serious`, `critical`.

Emitted when the thermal state of the system changes. Notification of a change
in the thermal status of the system, such as entering a critical temperature
range. Depending on the severity, the system might take steps to reduce said
temperature, for example, throttling the CPU or switching on the fans if
available.

Apps may react to the new state by reducing expensive computing tasks (e.g.
video encoding), or notifying the user. The same state might be received
repeatedly.

See https://developer.apple.com/library/archive/documentation/Performance/Conceptual/power_efficiency_guidelines_osx/RespondToThermalStateChanges.html

### Event: 'speed-limit-change' _macOS_ _Windows_

* `limit` number - The operating system's advertised speed limit for CPUs, in percent.

Notification of a change in the operating system's advertised speed limit for
CPUs, in percent. Values below 100 indicate that the system is impairing
processing power due to thermal management.

### Event: 'shutdown' _Linux_ _macOS_

Emitted when the system is about to reboot or shut down. If the event handler
Expand Down Expand Up @@ -55,7 +79,7 @@ The `powerMonitor` module has the following methods:

* `idleThreshold` Integer

Returns `string` - The system's current state. Can be `active`, `idle`, `locked` or `unknown`.
Returns `string` - The system's current idle state. Can be `active`, `idle`, `locked` or `unknown`.

Calculate the system idle state. `idleThreshold` is the amount of time (in seconds)
before considered idle. `locked` is available on supported systems only.
Expand All @@ -66,6 +90,10 @@ Returns `Integer` - Idle time in seconds

Calculate system idle time in seconds.

### `powerMonitor.getCurrentThermalState()` _macOS_

Returns `string` - The system's current thermal state. Can be `unknown`, `nominal`, `fair`, `serious`, or `critical`.

### `powerMonitor.isOnBatteryPower()`

Returns `boolean` - Whether the system is on battery power.
Expand Down
5 changes: 5 additions & 0 deletions lib/browser/api/power-monitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const {
createPowerMonitor,
getSystemIdleState,
getSystemIdleTime,
getCurrentThermalState,
isOnBatteryPower
} = process._linkedBinding('electron_browser_power_monitor');

Expand Down Expand Up @@ -43,6 +44,10 @@ class PowerMonitor extends EventEmitter {
return getSystemIdleState(idleThreshold);
}

getCurrentThermalState () {
return getCurrentThermalState();
}

getSystemIdleTime () {
return getSystemIdleTime();
}
Expand Down
47 changes: 47 additions & 0 deletions shell/browser/api/electron_api_power_monitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@

#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_device_source.h"
#include "base/power_monitor/power_observer.h"
#include "gin/data_object_builder.h"
#include "gin/handle.h"
#include "shell/browser/browser.h"
#include "shell/browser/javascript_environment.h"
#include "shell/common/gin_converters/callback_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/object_template_builder.h"
Expand All @@ -33,6 +36,26 @@ struct Converter<ui::IdleState> {
}
};

template <>
struct Converter<base::PowerThermalObserver::DeviceThermalState> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const base::PowerThermalObserver::DeviceThermalState& in) {
switch (in) {
case base::PowerThermalObserver::DeviceThermalState::kUnknown:
return StringToV8(isolate, "unknown");
case base::PowerThermalObserver::DeviceThermalState::kNominal:
return StringToV8(isolate, "nominal");
case base::PowerThermalObserver::DeviceThermalState::kFair:
return StringToV8(isolate, "fair");
case base::PowerThermalObserver::DeviceThermalState::kSerious:
return StringToV8(isolate, "serious");
case base::PowerThermalObserver::DeviceThermalState::kCritical:
return StringToV8(isolate, "critical");
}
}
};

} // namespace gin

namespace electron::api {
Expand All @@ -47,6 +70,7 @@ PowerMonitor::PowerMonitor(v8::Isolate* isolate) {

base::PowerMonitor::AddPowerStateObserver(this);
base::PowerMonitor::AddPowerSuspendObserver(this);
base::PowerMonitor::AddPowerThermalObserver(this);

#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
InitPlatformSpecificMonitors();
Expand All @@ -56,6 +80,7 @@ PowerMonitor::PowerMonitor(v8::Isolate* isolate) {
PowerMonitor::~PowerMonitor() {
base::PowerMonitor::RemovePowerStateObserver(this);
base::PowerMonitor::RemovePowerSuspendObserver(this);
base::PowerMonitor::RemovePowerThermalObserver(this);
}

bool PowerMonitor::ShouldShutdown() {
Expand All @@ -77,6 +102,22 @@ void PowerMonitor::OnResume() {
Emit("resume");
}

void PowerMonitor::OnThermalStateChange(DeviceThermalState new_state) {
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope scope(isolate);
EmitWithoutCustomEvent(
"thermal-state-change",
gin::DataObjectBuilder(isolate).Set("state", new_state).Build());
}

void PowerMonitor::OnSpeedLimitChange(int speed_limit) {
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope scope(isolate);
EmitWithoutCustomEvent(
"speed-limit-change",
gin::DataObjectBuilder(isolate).Set("limit", speed_limit).Build());
}

#if BUILDFLAG(IS_LINUX)
void PowerMonitor::SetListeningForShutdown(bool is_listening) {
if (is_listening) {
Expand Down Expand Up @@ -138,6 +179,10 @@ bool IsOnBatteryPower() {
return base::PowerMonitor::IsOnBatteryPower();
}

base::PowerThermalObserver::DeviceThermalState GetCurrentThermalState() {
return base::PowerMonitor::GetCurrentThermalState();
}

void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
Expand All @@ -148,6 +193,8 @@ void Initialize(v8::Local<v8::Object> exports,
base::BindRepeating(&PowerMonitor::Create));
dict.SetMethod("getSystemIdleState",
base::BindRepeating(&GetSystemIdleState));
dict.SetMethod("getCurrentThermalState",
base::BindRepeating(&GetCurrentThermalState));
dict.SetMethod("getSystemIdleTime", base::BindRepeating(&GetSystemIdleTime));
dict.SetMethod("isOnBatteryPower", base::BindRepeating(&IsOnBatteryPower));
}
Expand Down
7 changes: 6 additions & 1 deletion shell/browser/api/electron_api_power_monitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class PowerMonitor : public gin::Wrappable<PowerMonitor>,
public gin_helper::EventEmitterMixin<PowerMonitor>,
public gin_helper::Pinnable<PowerMonitor>,
public base::PowerStateObserver,
public base::PowerSuspendObserver {
public base::PowerSuspendObserver,
public base::PowerThermalObserver {
public:
static v8::Local<v8::Value> Create(v8::Isolate* isolate);

Expand Down Expand Up @@ -57,6 +58,10 @@ class PowerMonitor : public gin::Wrappable<PowerMonitor>,
void OnSuspend() override;
void OnResume() override;

// base::PowerThermalObserver
void OnThermalStateChange(DeviceThermalState new_state) override;
void OnSpeedLimitChange(int speed_limit) override;

#if BUILDFLAG(IS_WIN)
// Static callback invoked when a message comes in to our messaging window.
static LRESULT CALLBACK WndProcStatic(HWND hwnd,
Expand Down
6 changes: 6 additions & 0 deletions spec/api-power-monitor-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,12 @@ describe('powerMonitor', () => {
});
});

describe('powerMonitor.getCurrentThermalState', () => {
it('returns a valid state', () => {
expect(powerMonitor.getCurrentThermalState()).to.be.oneOf(['unknown', 'nominal', 'fair', 'serious', 'critical']);
});
});

describe('powerMonitor.onBatteryPower', () => {
it('returns a boolean', () => {
expect(powerMonitor.onBatteryPower).to.be.a('boolean');
Expand Down

0 comments on commit 912aa52

Please sign in to comment.