Loading core/res/res/values/strings.xml +4 −0 Original line number Diff line number Diff line Loading @@ -5829,6 +5829,10 @@ <string name="dynamic_mode_notification_title">Battery Saver turned on</string> <!-- Summary of notification letting users know why battery saver was turned on automatically [CHAR_LIMIT=NONE]--> <string name="dynamic_mode_notification_summary">Reducing battery usage to extend battery life</string> <!-- Title of notification letting users know why battery saver was turned on automatically [CHAR_LIMIT=NONE]--> <string name="dynamic_mode_notification_title_v2">Battery Saver is on</string> <!-- Summary of notification letting users know why battery saver was turned on automatically [CHAR_LIMIT=NONE]--> <string name="dynamic_mode_notification_summary_v2">Battery Saver is turned on to extend battery life</string> <!-- Battery saver strings --> <!-- The user visible name of the notification channel for battery saver notifications [CHAR_LIMIT=80] --> Loading core/res/res/values/symbols.xml +2 −0 Original line number Diff line number Diff line Loading @@ -4241,7 +4241,9 @@ <java-symbol type="string" name="battery_saver_charged_notification_summary" /> <java-symbol type="string" name="dynamic_mode_notification_channel_name" /> <java-symbol type="string" name="dynamic_mode_notification_title" /> <java-symbol type="string" name="dynamic_mode_notification_title_v2" /> <java-symbol type="string" name="dynamic_mode_notification_summary" /> <java-symbol type="string" name="dynamic_mode_notification_summary_v2" /> <java-symbol type="drawable" name="ic_battery" /> <java-symbol type="bool" name="config_skipSensorAvailable" /> Loading services/core/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -241,6 +241,7 @@ java_library_static { "securebox", "apache-commons-math", "backstage_power_flags_lib", "battery_saver_flag_lib", "notification_flags_lib", "biometrics_flags_lib", "am_flags_lib", Loading services/core/java/com/android/server/power/batterysaver/Android.bp 0 → 100644 +14 −0 Original line number Diff line number Diff line aconfig_declarations { name: "battery_saver_flag", package: "com.android.server.power.batterysaver", container: "system", srcs: [ "*.aconfig", ], } java_aconfig_library { name: "battery_saver_flag_lib", aconfig_declarations: "battery_saver_flag", sdk_version: "system_current", } services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java +60 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.content.Intent; import android.content.res.Resources; import android.database.ContentObserver; import android.os.BatterySaverPolicyConfig; import android.os.Bundle; import android.os.Handler; import android.os.PowerManager; import android.os.SystemClock; Loading Loading @@ -97,6 +98,9 @@ public class BatterySaverStateMachine { private static final String TAG = "BatterySaverStateMachine"; private static final String DYNAMIC_MODE_NOTIF_CHANNEL_ID = "dynamic_mode_notification"; private static final String BATTERY_SAVER_NOTIF_CHANNEL_ID = "battery_saver_channel"; private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key"; private static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_args"; private static final String PREFERENCE_KEY_BATTERY_SAVER_SCHEDULER = "battery_saver_schedule"; private static final int DYNAMIC_MODE_NOTIFICATION_ID = 1992; private static final int STICKY_AUTO_DISABLED_NOTIFICATION_ID = 1993; private final Object mLock; Loading Loading @@ -831,7 +835,11 @@ public class BatterySaverStateMachine { // Handle triggering the notification to show/hide when appropriate if (intReason == BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON || intReason == BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_ON) { triggerDynamicModeNotification(); if (Flags.updateAutoTurnOnNotificationStringAndAction()) { triggerDynamicModeNotificationV2(); } else { triggerDynamicModeNotificationV2(); } } else if (!enable) { hideDynamicModeNotification(); } Loading Loading @@ -861,6 +869,31 @@ public class BatterySaverStateMachine { }); } @VisibleForTesting void triggerDynamicModeNotificationV2() { // The current lock is the PowerManager lock, which sits very low in the service lock // hierarchy. We shouldn't call out to NotificationManager with the PowerManager lock. runOnBgThread(() -> { NotificationManager manager = mContext.getSystemService(NotificationManager.class); ensureNotificationChannelExists(manager, DYNAMIC_MODE_NOTIF_CHANNEL_ID, R.string.dynamic_mode_notification_channel_name); // The bundle is used for highlighting a settings item when launching the settings page. final var highlightBundle = new Bundle(1 /* capacity */); highlightBundle.putString( EXTRA_FRAGMENT_ARG_KEY, PREFERENCE_KEY_BATTERY_SAVER_SCHEDULER); manager.notifyAsUser(TAG, DYNAMIC_MODE_NOTIFICATION_ID, buildNotificationV2(DYNAMIC_MODE_NOTIF_CHANNEL_ID, R.string.dynamic_mode_notification_title_v2, R.string.dynamic_mode_notification_summary_v2, Settings.ACTION_BATTERY_SAVER_SETTINGS, 0L /* timeoutMs */, highlightBundle), UserHandle.ALL); }); } @VisibleForTesting void triggerStickyDisabledNotification() { if (!mBatterySaverTurnedOffNotificationEnabled) { Loading Loading @@ -915,6 +948,32 @@ public class BatterySaverStateMachine { .build(); } private Notification buildNotificationV2(@NonNull String channelId, @StringRes int titleId, @StringRes int summaryId, @NonNull String intentAction, long timeoutMs, @NonNull Bundle highlightBundle) { Resources res = mContext.getResources(); Intent intent = new Intent(intentAction) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK) .putExtra(EXTRA_SHOW_FRAGMENT_TITLE, highlightBundle); PendingIntent batterySaverIntent = PendingIntent.getActivity( mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); final String title = res.getString(titleId); final String summary = res.getString(summaryId); return new Notification.Builder(mContext, channelId) .setSmallIcon(R.drawable.ic_battery) .setContentTitle(title) .setContentText(summary) .setContentIntent(batterySaverIntent) .setStyle(new Notification.BigTextStyle().bigText(summary)) .setOnlyAlertOnce(true) .setAutoCancel(true) .setTimeoutAfter(timeoutMs) .build(); } private void hideDynamicModeNotification() { hideNotification(DYNAMIC_MODE_NOTIFICATION_ID); } Loading Loading
core/res/res/values/strings.xml +4 −0 Original line number Diff line number Diff line Loading @@ -5829,6 +5829,10 @@ <string name="dynamic_mode_notification_title">Battery Saver turned on</string> <!-- Summary of notification letting users know why battery saver was turned on automatically [CHAR_LIMIT=NONE]--> <string name="dynamic_mode_notification_summary">Reducing battery usage to extend battery life</string> <!-- Title of notification letting users know why battery saver was turned on automatically [CHAR_LIMIT=NONE]--> <string name="dynamic_mode_notification_title_v2">Battery Saver is on</string> <!-- Summary of notification letting users know why battery saver was turned on automatically [CHAR_LIMIT=NONE]--> <string name="dynamic_mode_notification_summary_v2">Battery Saver is turned on to extend battery life</string> <!-- Battery saver strings --> <!-- The user visible name of the notification channel for battery saver notifications [CHAR_LIMIT=80] --> Loading
core/res/res/values/symbols.xml +2 −0 Original line number Diff line number Diff line Loading @@ -4241,7 +4241,9 @@ <java-symbol type="string" name="battery_saver_charged_notification_summary" /> <java-symbol type="string" name="dynamic_mode_notification_channel_name" /> <java-symbol type="string" name="dynamic_mode_notification_title" /> <java-symbol type="string" name="dynamic_mode_notification_title_v2" /> <java-symbol type="string" name="dynamic_mode_notification_summary" /> <java-symbol type="string" name="dynamic_mode_notification_summary_v2" /> <java-symbol type="drawable" name="ic_battery" /> <java-symbol type="bool" name="config_skipSensorAvailable" /> Loading
services/core/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -241,6 +241,7 @@ java_library_static { "securebox", "apache-commons-math", "backstage_power_flags_lib", "battery_saver_flag_lib", "notification_flags_lib", "biometrics_flags_lib", "am_flags_lib", Loading
services/core/java/com/android/server/power/batterysaver/Android.bp 0 → 100644 +14 −0 Original line number Diff line number Diff line aconfig_declarations { name: "battery_saver_flag", package: "com.android.server.power.batterysaver", container: "system", srcs: [ "*.aconfig", ], } java_aconfig_library { name: "battery_saver_flag_lib", aconfig_declarations: "battery_saver_flag", sdk_version: "system_current", }
services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java +60 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.content.Intent; import android.content.res.Resources; import android.database.ContentObserver; import android.os.BatterySaverPolicyConfig; import android.os.Bundle; import android.os.Handler; import android.os.PowerManager; import android.os.SystemClock; Loading Loading @@ -97,6 +98,9 @@ public class BatterySaverStateMachine { private static final String TAG = "BatterySaverStateMachine"; private static final String DYNAMIC_MODE_NOTIF_CHANNEL_ID = "dynamic_mode_notification"; private static final String BATTERY_SAVER_NOTIF_CHANNEL_ID = "battery_saver_channel"; private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key"; private static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_args"; private static final String PREFERENCE_KEY_BATTERY_SAVER_SCHEDULER = "battery_saver_schedule"; private static final int DYNAMIC_MODE_NOTIFICATION_ID = 1992; private static final int STICKY_AUTO_DISABLED_NOTIFICATION_ID = 1993; private final Object mLock; Loading Loading @@ -831,7 +835,11 @@ public class BatterySaverStateMachine { // Handle triggering the notification to show/hide when appropriate if (intReason == BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON || intReason == BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_ON) { triggerDynamicModeNotification(); if (Flags.updateAutoTurnOnNotificationStringAndAction()) { triggerDynamicModeNotificationV2(); } else { triggerDynamicModeNotificationV2(); } } else if (!enable) { hideDynamicModeNotification(); } Loading Loading @@ -861,6 +869,31 @@ public class BatterySaverStateMachine { }); } @VisibleForTesting void triggerDynamicModeNotificationV2() { // The current lock is the PowerManager lock, which sits very low in the service lock // hierarchy. We shouldn't call out to NotificationManager with the PowerManager lock. runOnBgThread(() -> { NotificationManager manager = mContext.getSystemService(NotificationManager.class); ensureNotificationChannelExists(manager, DYNAMIC_MODE_NOTIF_CHANNEL_ID, R.string.dynamic_mode_notification_channel_name); // The bundle is used for highlighting a settings item when launching the settings page. final var highlightBundle = new Bundle(1 /* capacity */); highlightBundle.putString( EXTRA_FRAGMENT_ARG_KEY, PREFERENCE_KEY_BATTERY_SAVER_SCHEDULER); manager.notifyAsUser(TAG, DYNAMIC_MODE_NOTIFICATION_ID, buildNotificationV2(DYNAMIC_MODE_NOTIF_CHANNEL_ID, R.string.dynamic_mode_notification_title_v2, R.string.dynamic_mode_notification_summary_v2, Settings.ACTION_BATTERY_SAVER_SETTINGS, 0L /* timeoutMs */, highlightBundle), UserHandle.ALL); }); } @VisibleForTesting void triggerStickyDisabledNotification() { if (!mBatterySaverTurnedOffNotificationEnabled) { Loading Loading @@ -915,6 +948,32 @@ public class BatterySaverStateMachine { .build(); } private Notification buildNotificationV2(@NonNull String channelId, @StringRes int titleId, @StringRes int summaryId, @NonNull String intentAction, long timeoutMs, @NonNull Bundle highlightBundle) { Resources res = mContext.getResources(); Intent intent = new Intent(intentAction) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK) .putExtra(EXTRA_SHOW_FRAGMENT_TITLE, highlightBundle); PendingIntent batterySaverIntent = PendingIntent.getActivity( mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); final String title = res.getString(titleId); final String summary = res.getString(summaryId); return new Notification.Builder(mContext, channelId) .setSmallIcon(R.drawable.ic_battery) .setContentTitle(title) .setContentText(summary) .setContentIntent(batterySaverIntent) .setStyle(new Notification.BigTextStyle().bigText(summary)) .setOnlyAlertOnce(true) .setAutoCancel(true) .setTimeoutAfter(timeoutMs) .build(); } private void hideDynamicModeNotification() { hideNotification(DYNAMIC_MODE_NOTIFICATION_ID); } Loading