[Battery Saver] Power Setting UI
This change is the initial (incomplete) implementation of the settings
UI for ChromeOS's battery saver feature.
Everything is behind a feature+flag, so regular users won't see the
incomplete (and not internationalized) UI. But this makes it available
for teamfood and fishfood.
Battery saver is a mode that trades reduced performance for increased
battery life.
The toggle should appear in settings when the feature is enabled and the
device has a battery.
Battery saver can not be enabled when on AC power, so the toggle should
be ghosted when charging.
Screenshot: https://screenshot.googleplex.com/hdAxcqGHLETwiLC
UI design: go/cros-bsm-mocks
BUG=b:278957245
TEST=Locally, reenable OSSettingsDevicePageTest and run it.
Change-Id: Icae4bd1aac80e6cf135aec2c9e842cb32859ef5c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4318204
Reviewed-by: Wes Okuhara <wesokuhara@google.com>
Commit-Queue: Charles William Dick <cwd@google.com>
Reviewed-by: Takashi Toyoshima <toyoshim@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1157352}
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index 6620233..6595c62f 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -4615,6 +4615,12 @@
<message name="IDS_SETTINGS_BATTERY_STATUS_SHORT" desc="In Device Settings > Power, the battery status when the time left cannot be shown.">
<ph name="percentage">$1<ex>56</ex></ph>%
</message>
+ <message name="IDS_SETTINGS_POWER_BATTERY_SAVER_LABEL" desc="In Device Settings > Power, label for toggling battery saver mode" translateable="false">
+ Battery Saver
+ </message>
+ <message name="IDS_SETTINGS_POWER_BATTERY_SAVER_SUBTEXT" desc="In Device Settings > Power, description of the behavior of battery saver mode" translateable="false">
+ Enable Energy saver to extend battery life by turning off background functions such as[...]
+ </message>
<!-- Reset Page (OS settings)-->
<message name="IDS_SETTINGS_RESET_TITLE" desc="Title of a section of settings. This section describes settings for resetting the device.">
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc
index d0ef1a00..0e68454 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -928,6 +928,8 @@
settings_api::PrefType::PREF_TYPE_LIST;
(*s_allowlist)[ash::prefs::kPowerAdaptiveChargingEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_allowlist)[ash::prefs::kPowerBatterySaver] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_allowlist)[::prefs::kConsumerAutoUpdateToggle] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_allowlist)[::ash::prefs::kChargingSoundsEnabled] =
diff --git a/chrome/browser/resources/settings/chromeos/device_page/device_page.html b/chrome/browser/resources/settings/chromeos/device_page/device_page.html
index c15d741..f740fe2 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/device_page.html
+++ b/chrome/browser/resources/settings/chromeos/device_page/device_page.html
@@ -182,7 +182,7 @@
<template is="dom-if" route-path="/power">
<os-settings-subpage
page-title="$i18n{powerTitle}">
- <settings-power></settings-power>
+ <settings-power prefs="{{prefs}}"></settings-power>
</os-settings-subpage>
</template>
</os-settings-animated-pages>
diff --git a/chrome/browser/resources/settings/chromeos/device_page/device_page_browser_proxy.ts b/chrome/browser/resources/settings/chromeos/device_page/device_page_browser_proxy.ts
index 137ab60..8dbc90b 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/device_page_browser_proxy.ts
+++ b/chrome/browser/resources/settings/chromeos/device_page/device_page_browser_proxy.ts
@@ -78,6 +78,7 @@
hasLid: boolean;
adaptiveCharging: boolean;
adaptiveChargingManaged: boolean;
+ batterySaverFeatureEnabled: boolean;
}
/**
diff --git a/chrome/browser/resources/settings/chromeos/device_page/power.html b/chrome/browser/resources/settings/chromeos/device_page/power.html
index c254544..b645d825 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/power.html
+++ b/chrome/browser/resources/settings/chromeos/device_page/power.html
@@ -36,6 +36,16 @@
</div>
</div>
+<settings-toggle-button id="batterySaverToggle"
+ hidden$="[[batterySaverHidden_]]"
+ pref="{{prefs.power.cros_battery_saver_active}}"
+ label="$i18n{powerBatterySaverLabel}"
+ sub-label="$i18n{powerBatterySaverSubtext}"
+ learn-more-url="$i18n{powerBatterySaverLearnMoreUrl}"
+ disabled="[[batterySaverToggleDisabled_]]"
+ deep-link-focus-id$="[[Setting.kBatterySaver]]">
+</settings-toggle-button>
+
<settings-toggle-button hidden$="[[!adaptiveChargingEnabled_]]"
class$="[[getClassForRow_(batteryStatus_.present, 'adaptiveCharging')]]"
id="adaptiveChargingToggle"
diff --git a/chrome/browser/resources/settings/chromeos/device_page/power.ts b/chrome/browser/resources/settings/chromeos/device_page/power.ts
index 5f341fc..f08010a 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/power.ts
+++ b/chrome/browser/resources/settings/chromeos/device_page/power.ts
@@ -15,6 +15,7 @@
import '../settings_shared.css.js';
import {SettingsToggleButtonElement} from '/shared/settings/controls/settings_toggle_button.js';
+import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
import {assertNotReached} from 'chrome://resources/js/assert_ts.js';
@@ -39,13 +40,14 @@
interface SettingsPowerElement {
$: {
adaptiveChargingToggle: SettingsToggleButtonElement,
+ batterySaverToggle: SettingsToggleButtonElement,
lidClosedToggle: SettingsToggleButtonElement,
powerSource: HTMLSelectElement,
};
}
-const SettingsPowerElementBase = DeepLinkingMixin(
- RouteObserverMixin(WebUiListenerMixin(I18nMixin(PolymerElement))));
+const SettingsPowerElementBase = DeepLinkingMixin(RouteObserverMixin(
+ PrefsMixin(WebUiListenerMixin(I18nMixin(PolymerElement)))));
class SettingsPowerElement extends SettingsPowerElementBase {
static get is() {
@@ -163,6 +165,20 @@
},
},
+ batterySaverFeatureEnabled_: Boolean,
+
+ batterySaverHidden_: {
+ type: Boolean,
+ computed:
+ 'computeBatterySaverHidden_(batteryStatus_, batterySaverFeatureEnabled_)',
+ },
+
+ batterySaverToggleDisabled_: {
+ type: Boolean,
+ computed:
+ 'computeBatterySaverToggleDisabled_(powerSources_, lowPowerCharger_)',
+ },
+
/**
* Used by DeepLinkingMixin to focus this page's deep links.
*/
@@ -174,6 +190,7 @@
Setting.kSleepWhenLaptopLidClosed,
Setting.kPowerIdleBehaviorWhileOnBattery,
Setting.kAdaptiveCharging,
+ Setting.kBatterySaver,
]),
},
@@ -195,6 +212,7 @@
private lowPowerCharger_: boolean;
private powerSources_: PowerSource[]|undefined;
private selectedPowerSourceId_: string;
+ private batterySaverFeatureEnabled_: boolean;
constructor() {
super();
@@ -275,6 +293,24 @@
return '';
}
+ private computeBatterySaverHidden_(
+ batteryStatus: BatteryStatus|undefined,
+ featureEnabled: boolean): boolean {
+ if (batteryStatus === undefined) {
+ return true;
+ }
+ return !featureEnabled || !batteryStatus.present;
+ }
+
+ private computeBatterySaverToggleDisabled_(
+ powerSources: PowerSource[]|undefined,
+ lowPowerCharger: boolean): boolean {
+ if (powerSources === undefined) {
+ return true;
+ }
+ return powerSources.length > 0 && !lowPowerCharger;
+ }
+
private onPowerSourceChange_(): void {
this.browserProxy_.setPowerSource(this.$.powerSource.value);
}
@@ -452,6 +488,8 @@
chrome.settingsPrivate.ControlledBy.DEVICE_POLICY;
}
this.adaptiveChargingPref_ = adaptiveChargingPref;
+ this.batterySaverFeatureEnabled_ =
+ powerManagementSettings.batterySaverFeatureEnabled;
}
/**
diff --git a/chrome/browser/ui/webui/settings/ash/device_power_handler.cc b/chrome/browser/ui/webui/settings/ash/device_power_handler.cc
index 7762497..ea31884a 100644
--- a/chrome/browser/ui/webui/settings/ash/device_power_handler.cc
+++ b/chrome/browser/ui/webui/settings/ash/device_power_handler.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/public/cpp/power_utils.h"
#include "base/functional/bind.h"
@@ -115,6 +116,8 @@
const char PowerHandler::kAdaptiveChargingKey[] = "adaptiveCharging";
const char PowerHandler::kAdaptiveChargingManagedKey[] =
"adaptiveChargingManaged";
+const char PowerHandler::kBatterySaverFeatureEnabledKey[] =
+ "batterySaverFeatureEnabled";
PowerHandler::TestAPI::TestAPI(PowerHandler* handler) : handler_(handler) {}
@@ -401,7 +404,8 @@
prefs_->GetBoolean(ash::prefs::kPowerAdaptiveChargingEnabled);
const bool adaptive_charging_managed =
prefs_->IsManagedPreference(ash::prefs::kPowerAdaptiveChargingEnabled);
-
+ const bool battery_saver_feature_enabled =
+ ash::features::IsBatterySaverAvailable();
// Don't notify the UI if nothing changed.
if (!force && ac_idle_info == last_ac_idle_info_ &&
battery_idle_info == last_battery_idle_info_ &&
@@ -409,7 +413,8 @@
lid_closed_controlled == last_lid_closed_controlled_ &&
has_lid == last_has_lid_ &&
adaptive_charging == last_adaptive_charging_ &&
- adaptive_charging_managed == last_adaptive_charging_managed_) {
+ adaptive_charging_managed == last_adaptive_charging_managed_ &&
+ battery_saver_feature_enabled == last_battery_saver_feature_enabled_) {
return;
}
@@ -432,6 +437,7 @@
dict.Set(kHasLidKey, has_lid);
dict.Set(kAdaptiveChargingKey, adaptive_charging);
dict.Set(kAdaptiveChargingManagedKey, adaptive_charging_managed);
+ dict.Set(kBatterySaverFeatureEnabledKey, battery_saver_feature_enabled);
FireWebUIListener(kPowerManagementSettingsChangedName, dict);
last_ac_idle_info_ = ac_idle_info;
@@ -441,6 +447,7 @@
last_has_lid_ = has_lid;
last_adaptive_charging_ = adaptive_charging;
last_adaptive_charging_managed_ = adaptive_charging_managed;
+ last_battery_saver_feature_enabled_ = battery_saver_feature_enabled;
}
void PowerHandler::OnGotSwitchStates(
diff --git a/chrome/browser/ui/webui/settings/ash/device_power_handler.h b/chrome/browser/ui/webui/settings/ash/device_power_handler.h
index 7a271c2..4088dc9 100644
--- a/chrome/browser/ui/webui/settings/ash/device_power_handler.h
+++ b/chrome/browser/ui/webui/settings/ash/device_power_handler.h
@@ -53,6 +53,7 @@
static const char kHasLidKey[];
static const char kAdaptiveChargingKey[];
static const char kAdaptiveChargingManagedKey[];
+ static const char kBatterySaverFeatureEnabledKey[];
// Class used by tests to interact with PowerHandler internals.
class TestAPI {
@@ -186,6 +187,7 @@
bool last_has_lid_ = true;
bool last_adaptive_charging_ = false;
bool last_adaptive_charging_managed_ = false;
+ bool last_battery_saver_feature_enabled_ = false;
base::WeakPtrFactory<PowerHandler> weak_ptr_factory_{this};
};
diff --git a/chrome/browser/ui/webui/settings/ash/device_power_handler_browsertest.cc b/chrome/browser/ui/webui/settings/ash/device_power_handler_browsertest.cc
index 6c4c386..2da9e6b 100644
--- a/chrome/browser/ui/webui/settings/ash/device_power_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/settings/ash/device_power_handler_browsertest.cc
@@ -78,6 +78,7 @@
bool has_lid = true;
bool adaptive_charging = true;
bool adaptive_charging_managed = false;
+ bool battery_saver_feature_enabled = false;
};
PowerHandlerTest() = default;
@@ -161,6 +162,8 @@
dict.Set(PowerHandler::kAdaptiveChargingKey, settings.adaptive_charging);
dict.Set(PowerHandler::kAdaptiveChargingManagedKey,
settings.adaptive_charging_managed);
+ dict.Set(PowerHandler::kBatterySaverFeatureEnabledKey,
+ settings.battery_saver_feature_enabled);
std::string out;
EXPECT_TRUE(base::JSONWriter::Write(dict, &out));
return out;
diff --git a/chrome/browser/ui/webui/settings/ash/device_section.cc b/chrome/browser/ui/webui/settings/ash/device_section.cc
index 6c9208b..af260ef 100644
--- a/chrome/browser/ui/webui/settings/ash/device_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/device_section.cc
@@ -1059,11 +1059,16 @@
{"powerSourceLowPowerCharger",
IDS_SETTINGS_POWER_SOURCE_LOW_POWER_CHARGER},
{"powerTitle", IDS_SETTINGS_POWER_TITLE},
+ {"powerBatterySaverLabel", IDS_SETTINGS_POWER_BATTERY_SAVER_LABEL},
+ {"powerBatterySaverSubtext", IDS_SETTINGS_POWER_BATTERY_SAVER_SUBTEXT},
};
html_source->AddLocalizedStrings(kPowerStrings);
// TODO(b:216035280): create and link to real "learn more" webpage.
html_source->AddString("powerAdaptiveChargingLearnMoreUrl", u"about://blank");
+
+ // TODO(b:278957245): create and link to real "learn more" webpage.
+ html_source->AddString("powerBatterySaverLearnMoreUrl", "about://blank");
}
// Mirrors enum of the same name in enums.xml.
@@ -1394,6 +1399,7 @@
mojom::Setting::kPowerSource,
mojom::Setting::kSleepWhenLaptopLidClosed,
mojom::Setting::kAdaptiveCharging,
+ mojom::Setting::kBatterySaver,
};
RegisterNestedSettingBulk(mojom::Subpage::kPower, kPowerSettings, generator);
}
diff --git a/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom b/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom
index 428d966..02bfa2e4 100644
--- a/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom
+++ b/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom
@@ -146,6 +146,7 @@
kKeyboardRemapKeys = 442,
kChargingSounds = 443,
kLowBatterySound = 444,
+ kBatterySaver = 445,
// Personalization section.
kOpenWallpaper = 500,
diff --git a/chrome/test/data/webui/settings/chromeos/device_page/device_page_tests.js b/chrome/test/data/webui/settings/chromeos/device_page/device_page_tests.js
index 58bedaf..84a67c0 100644
--- a/chrome/test/data/webui/settings/chromeos/device_page/device_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/device_page/device_page_tests.js
@@ -83,6 +83,13 @@
},
},
},
+ power: {
+ cros_battery_saver_active: {
+ key: 'power.cros_battery_saver_active',
+ type: chrome.settingsPrivate.PrefType.BOOLEAN,
+ value: false,
+ },
+ },
settings: {
// TODO(afakhry): Write tests to validate the Night Light slider
// behavior with 24-hour setting.
@@ -405,22 +412,23 @@
* @param {boolean} adaptiveChargingManaged
*/
function sendPowerManagementSettings(
- possibleAcIdleBehaviors, possibleBatteryIdleBehaviors, currAcIdleBehavior,
- currBatteryIdleBehavior, acIdleManaged, batteryIdleManaged,
- lidClosedBehavior, lidClosedControlled, hasLid, adaptiveCharging,
- adaptiveChargingManaged) {
+ possibleAcIdleBehaviors, possibleBatteryIdleBehaviors,
+ currentAcIdleBehavior, currentBatteryIdleBehavior, acIdleManaged,
+ batteryIdleManaged, lidClosedBehavior, lidClosedControlled, hasLid,
+ adaptiveCharging, adaptiveChargingManaged, batterySaverFeatureEnabled) {
webUIListenerCallback('power-management-settings-changed', {
- possibleAcIdleBehaviors: possibleAcIdleBehaviors,
- possibleBatteryIdleBehaviors: possibleBatteryIdleBehaviors,
- currentAcIdleBehavior: currAcIdleBehavior,
- currentBatteryIdleBehavior: currBatteryIdleBehavior,
- acIdleManaged: acIdleManaged,
- batteryIdleManaged: batteryIdleManaged,
- lidClosedBehavior: lidClosedBehavior,
- lidClosedControlled: lidClosedControlled,
- hasLid: hasLid,
- adaptiveCharging: adaptiveCharging,
- adaptiveChargingManaged: adaptiveChargingManaged,
+ possibleAcIdleBehaviors,
+ possibleBatteryIdleBehaviors,
+ currentAcIdleBehavior,
+ currentBatteryIdleBehavior,
+ acIdleManaged,
+ batteryIdleManaged,
+ lidClosedBehavior,
+ lidClosedControlled,
+ hasLid,
+ adaptiveCharging,
+ adaptiveChargingManaged,
+ batterySaverFeatureEnabled,
});
flush();
}
@@ -2435,6 +2443,7 @@
let acIdleSelect;
let lidClosedToggle;
let adaptiveChargingToggle;
+ let batterySaverToggle;
suiteSetup(function() {
// Adaptive charging setting should be shown.
@@ -2462,6 +2471,8 @@
adaptiveChargingToggle =
assert(powerPage.shadowRoot.querySelector(
'#adaptiveChargingToggle'));
+ batterySaverToggle = assert(
+ powerPage.shadowRoot.querySelector('#batterySaverToggle'));
assertEquals(
1,
@@ -2483,7 +2494,8 @@
false /* batteryIdleManaged */, LidClosedBehavior.SUSPEND,
false /* lidClosedControlled */, true /* hasLid */,
false /* adaptiveCharging */,
- false /* adaptiveChargingManaged */);
+ false /* adaptiveChargingManaged */,
+ true /* batterySaverFeatureEnabled */);
});
});
@@ -2502,6 +2514,8 @@
// Power source row is hidden since there's no battery.
assertTrue(powerSourceRow.hidden);
+ // Battery Saver is also hidden.
+ assertTrue(batterySaverToggle.hidden);
// Idle settings while on battery and while charging should not be
// visible if the battery is not present.
assertEquals(
@@ -2537,6 +2551,8 @@
// Power sources row is visible but dropdown is hidden.
assertFalse(powerSourceRow.hidden);
assertTrue(powerSourceSelect.hidden);
+ // Battery saver should be toggleable when not charging.
+ assertFalse(batterySaverToggle.disabled);
// Attach a dual-role USB device.
const powerSource = {
@@ -2550,12 +2566,18 @@
// "Battery" should be selected.
assertFalse(powerSourceSelect.hidden);
assertEquals('', powerSourceSelect.value);
+ // We are charging on a non-low power charger, battery saver should be
+ // grayed out.
+ assertTrue(batterySaverToggle.disabled);
// Select the power source.
setPowerSources([powerSource], powerSource.id, true);
flush();
assertFalse(powerSourceSelect.hidden);
assertEquals(powerSource.id, powerSourceSelect.value);
+ // Charging, but on a low-power charger, battery saver should be
+ // toggleable.
+ assertFalse(batterySaverToggle.disabled);
// Send another power source; the first should still be selected.
const otherPowerSource = Object.assign({}, powerSource);
@@ -2564,6 +2586,7 @@
flush();
assertFalse(powerSourceSelect.hidden);
assertEquals(powerSource.id, powerSourceSelect.value);
+ assertFalse(batterySaverToggle.disabled);
});
test('choose power source', function() {
@@ -2656,8 +2679,8 @@
IdleBehavior.DISPLAY_OFF, IdleBehavior.DISPLAY_OFF,
false /* acIdleManaged */, false /* batteryIdleManaged */,
lidBehavior, false /* lidClosedControlled */, true /* hasLid */,
- false /* adaptiveCharging */,
- false /* adaptiveChargingManaged */);
+ false /* adaptiveCharging */, false /* adaptiveChargingManaged */,
+ true /* batterySaverFeatureEnabled */);
};
sendLid(LidClosedBehavior.SUSPEND);
@@ -2700,7 +2723,8 @@
LidClosedBehavior.DO_NOTHING,
false /* lidClosedControlled */, true /* hasLid */,
false /* adaptiveCharging */,
- false /* adaptiveChargingManaged */);
+ false /* adaptiveChargingManaged */,
+ true /* batterySaverFeatureEnabled */);
microTask.run(resolve);
})
.then(function() {
@@ -2758,7 +2782,8 @@
true /* acIdleManaged */, true /* batteryIdleManaged */,
LidClosedBehavior.DO_NOTHING, false /* lidClosedControlled */,
true /* hasLid */, false /* adaptiveCharging */,
- false /* adaptiveChargingManaged */);
+ false /* adaptiveChargingManaged */,
+ true /* batterySaverFeatureEnabled */);
return new Promise(function(resolve) {
microTask.run(resolve);
});
@@ -2800,7 +2825,8 @@
LidClosedBehavior.DO_NOTHING,
false /* lidClosedControlled */, true /* hasLid */,
false /* adaptiveCharging */,
- false /* adaptiveChargingManaged */);
+ false /* adaptiveChargingManaged */,
+ true /* batterySaverFeatureEnabled */);
microTask.run(resolve);
})
.then(function() {
@@ -2857,7 +2883,8 @@
false /* acIdleManaged */, false /* batteryIdleManaged */,
LidClosedBehavior.SUSPEND, false /* lidClosedControlled */,
true /* hasLid */, false /* adaptiveCharging */,
- false /* adaptiveChargingManaged */);
+ false /* adaptiveChargingManaged */,
+ true /* batterySaverFeatureEnabled */);
return new Promise(function(resolve) {
microTask.run(resolve);
});
@@ -2910,7 +2937,8 @@
LidClosedBehavior.SHUT_DOWN,
true /* lidClosedControlled */, true /* hasLid */,
false /* adaptiveCharging */,
- false /* adaptiveChargingManaged */);
+ false /* adaptiveChargingManaged */,
+ true /* batterySaverFeatureEnabled */);
microTask.run(resolve);
})
.then(function() {
@@ -2946,7 +2974,8 @@
LidClosedBehavior.STOP_SESSION,
true /* lidClosedControlled */, true /* hasLid */,
false /* adaptiveCharging */,
- false /* adaptiveChargingManaged */);
+ false /* adaptiveChargingManaged */,
+ true /* batterySaverFeatureEnabled */);
return new Promise(function(resolve) {
microTask.run(resolve);
});
@@ -2997,7 +3026,8 @@
false /* batteryIdleManaged */, LidClosedBehavior.SUSPEND,
false /* lidClosedControlled */, false /* hasLid */,
false /* adaptiveCharging */,
- false /* adaptiveChargingManaged */);
+ false /* adaptiveChargingManaged */,
+ true /* batterySaverFeatureEnabled */);
microTask.run(resolve);
})
.then(function() {
@@ -3054,7 +3084,8 @@
false /* acIdleManaged */, false /* batteryIdleManaged */,
LidClosedBehavior.SUSPEND, false /* lidClosedControlled */,
true /* hasLid */, true /* adaptiveCharging */,
- true /* adaptiveCharingManaged */);
+ true /* adaptiveCharingManaged */,
+ true /* batterySaverFeatureEnabled */);
assertTrue(adaptiveChargingToggle.shadowRoot.querySelector('cr-toggle')
.checked);
@@ -3074,6 +3105,78 @@
adaptiveChargingToggle.shadowRoot.querySelector('cr-toggle'),
'Adaptive charging toggle');
});
+
+ test('Battery Saver hidden when feature disabled', () => {
+ sendPowerManagementSettings(
+ [
+ IdleBehavior.DISPLAY_OFF_SLEEP,
+ IdleBehavior.DISPLAY_OFF,
+ IdleBehavior.DISPLAY_ON,
+ ],
+ [
+ IdleBehavior.DISPLAY_OFF_SLEEP,
+ IdleBehavior.DISPLAY_OFF,
+ IdleBehavior.DISPLAY_ON,
+ ],
+ IdleBehavior.DISPLAY_OFF_SLEEP, IdleBehavior.DISPLAY_OFF_SLEEP,
+ false /* acIdleManaged */, false /* batteryIdleManaged */,
+ LidClosedBehavior.SUSPEND, false /* lidClosedControlled */,
+ true /* hasLid */, false /* adaptiveCharging */,
+ false /* adaptiveChargingManaged */,
+ false /* batterySaverFeatureEnabled */);
+
+ assertTrue(batterySaverToggle.hidden);
+ });
+
+ test('Battery Saver toggleable', () => {
+ // Battery is present.
+ webUIListenerCallback('battery-status-changed', {
+ present: true,
+ charging: false,
+ calculating: false,
+ percent: 50,
+ statusText: '5 hours left',
+ });
+ // There are no power sources.
+ setPowerSources([], '', false);
+ // Battery saver feature is enabled.
+ sendPowerManagementSettings(
+ [
+ IdleBehavior.DISPLAY_OFF_SLEEP,
+ IdleBehavior.DISPLAY_OFF,
+ IdleBehavior.DISPLAY_ON,
+ ],
+ [
+ IdleBehavior.DISPLAY_OFF_SLEEP,
+ IdleBehavior.DISPLAY_OFF,
+ IdleBehavior.DISPLAY_ON,
+ ],
+ IdleBehavior.DISPLAY_OFF_SLEEP, IdleBehavior.DISPLAY_OFF_SLEEP,
+ false /* acIdleManaged */, false /* batteryIdleManaged */,
+ LidClosedBehavior.SUSPEND, false /* lidClosedControlled */,
+ true /* hasLid */, false /* adaptiveCharging */,
+ false /* adaptiveChargingManaged */,
+ true /* batterySaverFeatureEnabled */);
+
+ // Battery saver should be visible and toggleable.
+ assertFalse(batterySaverToggle.hidden);
+ assertFalse(batterySaverToggle.disabled);
+ });
+
+ test('Battery Saver updates when pref updates', () => {
+ function setPref(value) {
+ const newPrefs = getFakePrefs();
+ newPrefs.power.cros_battery_saver_active.value = value;
+ powerPage.prefs = newPrefs;
+ flush();
+ }
+
+ setPref(true);
+ assertTrue(batterySaverToggle.checked);
+
+ setPref(false);
+ assertFalse(batterySaverToggle.checked);
+ });
});
});
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 2967ada..edce33b 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -78462,6 +78462,7 @@
<int value="442" label="Keyboard: Remap Keys"/>
<int value="443" label="Charging sounds: On/Off"/>
<int value="444" label="Low battery sound: On/Off"/>
+ <int value="445" label="Battery Saver: On/Off"/>
<int value="500" label="Open Wallpaper"/>
<int value="501" label="Ambient Mode On/Off"/>
<int value="502" label="Ambient Mode Source"/>