Skip to content
Open
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
285 changes: 285 additions & 0 deletions specs/EnergySaverStatus2/EnergySaverStatus2.md
Comment thread
RuthNjeri marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
# EnergySaverStatus2 API

# Background

The existing `Microsoft.Windows.System.Power.PowerManager.EnergySaverStatus` property reports
only two states: `Off` and `On`.
Starting with the Windows Germanium release, Windows 11, 24H2, the [Energy Saver](https://learn.microsoft.com/en-us/windows-hardware/design/component-guidelines/energy-saver)
Comment thread
RuthNjeri marked this conversation as resolved.
Outdated
feature was updated to support three distinct operating modes: **Off**, **Standard**, and
**High Savings** which are now visible to users in the Windows Settings app.

The original two-state API contains a bug: when Energy Saver is active in **Standard** mode
(battery above 20%), `EnergySaverStatus` incorrectly reports `Off`. Only the **High Savings**
state (battery at or below 20%) correctly maps to `On`.

This spec introduces `EnergySaverStatus2`, a new enum and associated APIs on
`Microsoft.Windows.System.Power.PowerManager`, that accurately reflects all three energy saver
states. The legacy `EnergySaverStatus` API is unchanged for backward compatibility.

> **Minimum OS requirement:** These APIs require a Windows 11, 24H2 build. On earlier OS versions,
> `IsEnergySaverStatus2Supported` returns `false` and `EnergySaverStatus2` returns `Unknown`.

# Conceptual pages

## Responding to Energy Saver state changes in your app

Energy Saver helps extend battery life by signaling apps to reduce resource consumption.
Energy Saver has three states that your app can respond to
with varying levels of optimization:

| State | Meaning | Recommended app behavior |
|---|---|---|
| `Off` | Energy Saver is disabled | Normal operation |
| `Standard` | Energy Saver active; mild performance impact acceptable | Reduce background sync frequency, defer non-critical work |
| `HighSavings` | Energy Saver active; maximum power savings preferred | Pause background sync, defer all non-critical work, reduce UI refresh rates |

Use `PowerManager.EnergySaverStatus2` to read the current state and subscribe to
`PowerManager.EnergySaverStatus2Changed` to respond to transitions at runtime.

Always call `PowerManager.IsEnergySaverStatus2Supported()` first if your app targets systems
that may run on OS versions earlier than Germanium. On unsupported systems, the property
returns `Unknown` and the changed event is never raised.

# API Pages
## PowerManager.EnergySaverStatus2 property

Gets the current Energy Saver v2 status for the device.

```csharp
public static EnergySaverStatus2 EnergySaverStatus2 { get; }
```

Use this property together with `EnergySaverStatus2Changed` to monitor power-state transitions
and adjust your app's resource usage accordingly. When Energy Saver is in `Standard` mode your
app should reduce non-critical background work; in `HighSavings` mode it should defer or pause
background operations entirely.

### Example – Reading the current status (C#)

```csharp
using Microsoft.Windows.System.Power;

EnergySaverStatus2 status = PowerManager.EnergySaverStatus2;
Comment thread
RuthNjeri marked this conversation as resolved.
switch (status)
{
case EnergySaverStatus2.Off:
// Normal operation
Comment thread
RuthNjeri marked this conversation as resolved.
Outdated
break;
case EnergySaverStatus2.Standard:
// Reduce background activity
break;
case EnergySaverStatus2.HighSavings:
// Pause background activity
break;
case EnergySaverStatus2.Unknown:
default:
// API not supported on this OS build
break;
}
```

### Example – Reading the current status (C++/WinRT)

```cpp
#include <winrt/Microsoft.Windows.System.Power.h>

using namespace winrt::Microsoft::Windows::System::Power;

EnergySaverStatus2 status = PowerManager::EnergySaverStatus2();
switch (status)
{
case EnergySaverStatus2::Off:
// Normal operation
break;
case EnergySaverStatus2::Standard:
// Reduce background activity
break;
case EnergySaverStatus2::HighSavings:
// Pause background activity
break;
case EnergySaverStatus2::Unknown:
default:
// API not supported on this OS build
break;
}
```

### Remarks

- Returns `Unknown` if `IsEnergySaverStatus2Supported()` returns `false`.
Comment thread
RuthNjeri marked this conversation as resolved.
Outdated

---

## PowerManager.EnergySaverStatus2Changed event

Occurs when the `EnergySaverStatus2` value changes.

```csharp
public static event System.EventHandler<object> EnergySaverStatus2Changed;
```

Subscribe to this event to receive notifications when the device transitions between Energy Saver
Comment thread
RuthNjeri marked this conversation as resolved.
states. When the event fires, call `PowerManager.EnergySaverStatus2` to retrieve the new value.

### Example – Subscribing to status changes (C#)

```csharp
using Microsoft.Windows.System.Power;

// Subscribe
PowerManager.EnergySaverStatus2Changed += OnEnergySaverStatus2Changed;

// Handler
private static void OnEnergySaverStatus2Changed(object sender, object e)
{
EnergySaverStatus2 status = PowerManager.EnergySaverStatus2;
switch (status)
{
case EnergySaverStatus2.Standard:
ReduceBackgroundActivity();
break;
case EnergySaverStatus2.HighSavings:
PauseBackgroundActivity();
break;
case EnergySaverStatus2.Off:
ResumeNormalActivity();
break;
}
}

// Unsubscribe when done
PowerManager.EnergySaverStatus2Changed -= OnEnergySaverStatus2Changed;
```

### Remarks

- The event is never raised on OS builds where `IsEnergySaverStatus2Supported()` returns `false`.
-
---

## PowerManager.IsEnergySaverStatus2Supported method

Returns a value indicating whether the current OS supports `EnergySaverStatus2`.

```csharp
public static bool IsEnergySaverStatus2Supported();
```

On unsupported builds, the property returns
`Unknown` and the event is never raised.

### Example (C#)

```csharp
using Microsoft.Windows.System.Power;

if (!PowerManager.IsEnergySaverStatus2Supported())
{
// Fall back to legacy EnergySaverStatus
return;
}

EnergySaverStatus2 status = PowerManager.EnergySaverStatus2;
```

### Remarks

- Calling this method is optional. You can use `EnergySaverStatus2` without it; if the feature is
unsupported the property safely returns `Unknown`.

---

## EnergySaverStatus2 enum

Represents the current Energy Saver mode of the device using the expanded v2 state.

```csharp
public enum EnergySaverStatus2
{
Unknown = 0,
Off = 1,
Standard = 2,
HighSavings = 3
}
```

| Value | Description |
|---|---|
| `Unknown` | The Energy Saver v2 status is unavailable, either because the OS does not support it or because the status has not yet been initialized. |
| `Off` | Energy Saver is disabled. Apps should operate normally. |
| `Standard` | Energy Saver is active with mild performance impact acceptable(at battery level greater than 20%). Energy saving behaviors that have mild performance impact are encouraged (for example, a sync client might reduce sync frequency). This state is returned when the user has opted into Energy Saver but battery life is not critical. |
| `HighSavings` | Energy Saver is active and maximum battery savings are preferred, even at the cost of performance(at battery level less than or equal to 20%). This state is returned when battery level is low and the device is not plugged in. |

### Remarks

- `EnergySaverStatus2` may be extended with additional values in future OS releases. Your code
should handle unknown enum values gracefully (for example, with a `default` case in a `switch`).
- The enum values map to the legacy `EnergySaverStatus` as follows:

| `EnergySaverStatus2` | Legacy `EnergySaverStatus` |
|---|---|
| `Off` | `Off` |
| `Standard` | `Off` _(legacy API does not distinguish this state)_ |
| `HighSavings` | `On` |

---

## Other PowerManager members

For the full list of existing `PowerManager` members see
[Microsoft.Windows.System.Power.PowerManager](https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.windows.system.power.powermanager?view=windows-app-sdk-1.7).

# API Details
```
namespace Microsoft.Windows.System.Power
{
[contractversion(3)]
apicontract PowerNotificationsContract{};

[contract(PowerNotificationsContract, 1)]
enum EnergySaverStatus
{
Uninitialized = 0,
Disabled,
Off,
On
};

/// Represents the current energy saver mode of the device using the expanded v2 state.
[contract(PowerNotificationsContract, 3)]
enum EnergySaverStatus2
{
Unknown = 0,
Off = 1,
Standard = 2,
HighSavings = 3
};

[contract(PowerNotificationsContract, 1)]
static runtimeclass PowerManager
{
// ... existing members (unchanged) ...

/// Gets the current Energy Saver v2 status for the device.
[contract(PowerNotificationsContract, 3)]
static EnergySaverStatus2 EnergySaverStatus2{ get; };
Comment thread
RuthNjeri marked this conversation as resolved.
Outdated

/// Occurs when the EnergySaverStatus2 value changes.
[contract(PowerNotificationsContract, 3)]
static event Windows.Foundation.EventHandler<Object> EnergySaverStatus2Changed;

/// Returns true if this OS build supports EnergySaverStatus2; false otherwise.
[contract(PowerNotificationsContract, 3)]
static Boolean IsEnergySaverStatus2Supported();
};
}
```

# Appendix

## Legacy API compatibility and mapping

The legacy `EnergySaverStatus` has a known limitation: when Energy Saver is active in **Standard**
Comment thread
RuthNjeri marked this conversation as resolved.
mode (battery above 20%), it reports `Off`, meaning apps using the legacy API cannot distinguish
"Energy Saver Standard active" from "Energy Saver disabled". `EnergySaverStatus2` fixes this.