diff --git a/core/res/res/values/cm_strings.xml b/core/res/res/values/cm_strings.xml
index 182a994f0ce9..d4f3f126041f 100644
--- a/core/res/res/values/cm_strings.xml
+++ b/core/res/res/values/cm_strings.xml
@@ -144,6 +144,10 @@
Activity launch blocked
%1$s is protected from being launched. Tap to authenticate and launch the application.
+
+
+ Battery fully charged
+ Disconnect your device from the charger to improve battery longevity.
To unpin this screen, touch and hold the Back button.
diff --git a/core/res/res/values/cm_symbols.xml b/core/res/res/values/cm_symbols.xml
index 9dc56230b7dc..d723219e0085 100644
--- a/core/res/res/values/cm_symbols.xml
+++ b/core/res/res/values/cm_symbols.xml
@@ -105,6 +105,11 @@
+
+
+
+
+
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 702ab0ea4872..973803a6d6a0 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2951,4 +2951,7 @@
false
+
+
+ false
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 9d71d89e4885..33ed94d51718 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -28,7 +28,9 @@
import com.android.server.lights.LightsManager;
import android.app.ActivityManagerNative;
+import android.app.Notification;
import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -172,6 +174,9 @@ public final class BatteryService extends SystemService {
private boolean mMultiColorLed;
private boolean mSentLowBatteryBroadcast = false;
+
+ private boolean mShowBatteryFullyChargedNotification;
+ private boolean mIsShowingBatteryFullyChargedNotification;
private final int mVbattSamplingIntervalMsec = 30000; /* sampling frequency - 30 seconds */
private final int mWeakChgCutoffVoltageMv;
@@ -222,6 +227,9 @@ public BatteryService(Context context) {
com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
mShutdownBatteryTemperature = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shutdownBatteryTemperature);
+
+ mShowBatteryFullyChargedNotification = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_showBatteryFullyChargedNotification);
// watch for invalid charger messages if the invalid_charger switch exists
if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
@@ -624,6 +632,12 @@ public void run() {
// Update the battery LED
mLed.updateLightsLocked();
+
+ if (shouldShowBatteryFullyChargedNotificationLocked()) {
+ showBatteryFullyChargedNotificationLocked();
+ } else if (shouldClearBatteryFullyChargedNotificationLocked()) {
+ clearBatteryFullyChargedNotificationLocked();
+ }
// This needs to be done after sendIntent() so that we get the lastest battery stats.
if (logOutlier && dischargeDuration != 0) {
@@ -931,6 +945,56 @@ private void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
private synchronized void updateLedPulse() {
mLed.updateLightsLocked();
+ }
+
+ private boolean shouldShowBatteryFullyChargedNotificationLocked() {
+ return mShowBatteryFullyChargedNotification && mPlugType != 0
+ && mBatteryProps.batteryLevel == BATTERY_SCALE
+ && !mIsShowingBatteryFullyChargedNotification;
+ }
+
+ private void showBatteryFullyChargedNotificationLocked() {
+ NotificationManager nm = mContext.getSystemService(NotificationManager.class);
+ Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
+ PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
+ intent, 0, null, UserHandle.CURRENT);
+
+ CharSequence title = mContext.getText(
+ com.android.internal.R.string.notify_battery_fully_charged_title);
+ CharSequence message = mContext.getText(
+ com.android.internal.R.string.notify_battery_fully_charged_text);
+
+ Notification notification = new Notification.Builder(mContext)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_battery_charge)
+ .setWhen(0)
+ .setOngoing(false)
+ .setAutoCancel(true)
+ .setTicker(title)
+ .setDefaults(0) // please be quiet
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(message)
+ .setStyle(new Notification.BigTextStyle().bigText(message))
+ .setContentIntent(pi)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .build();
+
+ nm.notifyAsUser(null, com.android.internal.R.string.notify_battery_fully_charged_title,
+ notification, UserHandle.ALL);
+ mIsShowingBatteryFullyChargedNotification = true;
+ }
+
+ private boolean shouldClearBatteryFullyChargedNotificationLocked() {
+ return mIsShowingBatteryFullyChargedNotification &&
+ (mPlugType == 0 || mBatteryProps.batteryLevel < BATTERY_SCALE);
+ }
+
+ private void clearBatteryFullyChargedNotificationLocked() {
+ NotificationManager nm = mContext.getSystemService(NotificationManager.class);
+ nm.cancel(com.android.internal.R.string.notify_battery_fully_charged_title);
+ mIsShowingBatteryFullyChargedNotification = false;
}
private final class Led {