Loading api/system-current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -840,6 +840,7 @@ package android.content { } public class Intent implements java.lang.Cloneable android.os.Parcelable { field public static final java.lang.String ACTION_BATTERY_LEVEL_CHANGED = "android.intent.action.BATTERY_LEVEL_CHANGED"; field public static final java.lang.String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY"; field public static final java.lang.String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED"; field public static final java.lang.String ACTION_FACTORY_RESET = "android.intent.action.FACTORY_RESET"; Loading Loading @@ -3612,6 +3613,11 @@ package android.nfc { package android.os { public class BatteryManager { field public static final java.lang.String EXTRA_EVENTS = "android.os.extra.EVENTS"; field public static final java.lang.String EXTRA_EVENT_TIMESTAMP = "android.os.extra.EVENT_TIMESTAMP"; } public final class ConfigUpdate { field public static final java.lang.String ACTION_UPDATE_CARRIER_PROVISIONING_URLS = "android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS"; field public static final java.lang.String ACTION_UPDATE_CT_LOGS = "android.intent.action.UPDATE_CT_LOGS"; Loading core/java/android/content/Intent.java +17 −0 Original line number Diff line number Diff line Loading @@ -2448,6 +2448,23 @@ public class Intent implements Parcelable, Cloneable { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED"; /** * Broadcast Action: Sent when the current battery level changes. * * It has {@link android.os.BatteryManager#EXTRA_EVENTS} that carries a list of {@link Bundle} * instances representing individual battery level changes with associated * extras from {@link #ACTION_BATTERY_CHANGED}. * * <p class="note"> * This broadcast requires {@link android.Manifest.permission#BATTERY_STATS} permission. * * @hide */ @SystemApi public static final String ACTION_BATTERY_LEVEL_CHANGED = "android.intent.action.BATTERY_LEVEL_CHANGED"; /** * Broadcast Action: Indicates low battery condition on the device. * This broadcast corresponds to the "Low battery warning" system dialog. Loading core/java/android/os/BatteryManager.java +18 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.os; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.content.Intent; Loading Loading @@ -138,6 +139,23 @@ public class BatteryManager { */ public static final String EXTRA_SEQUENCE = "seq"; /** * Extra for {@link android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED}: * Contains list of Bundles representing battery events * @hide */ @SystemApi public static final String EXTRA_EVENTS = "android.os.extra.EVENTS"; /** * Extra for event in {@link android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED}: * Long value representing time when event occurred as returned by * {@link android.os.SystemClock#elapsedRealtime()} * @hide */ @SystemApi public static final String EXTRA_EVENT_TIMESTAMP = "android.os.extra.EVENT_TIMESTAMP"; // values for "status" field in the ACTION_BATTERY_CHANGED Intent public static final int BATTERY_STATUS_UNKNOWN = Constants.BATTERY_STATUS_UNKNOWN; public static final int BATTERY_STATUS_CHARGING = Constants.BATTERY_STATUS_CHARGING; Loading core/res/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ <protected-broadcast android:name="android.intent.action.SPLIT_CONFIGURATION_CHANGED" /> <protected-broadcast android:name="android.intent.action.LOCALE_CHANGED" /> <protected-broadcast android:name="android.intent.action.BATTERY_CHANGED" /> <protected-broadcast android:name="android.intent.action.BATTERY_LEVEL_CHANGED" /> <protected-broadcast android:name="android.intent.action.BATTERY_LOW" /> <protected-broadcast android:name="android.intent.action.BATTERY_OKAY" /> <protected-broadcast android:name="android.intent.action.ACTION_POWER_CONNECTED" /> Loading services/core/java/com/android/server/BatteryService.java +60 −10 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.app.ActivityManagerInternal; import android.database.ContentObserver; import android.os.BatteryStats; import android.os.Bundle; import android.os.PowerManager; import android.os.ResultReceiver; import android.os.ShellCallback; Loading @@ -35,7 +36,6 @@ import android.app.ActivityManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.hidl.manager.V1_0.IServiceManager; import android.hidl.manager.V1_0.IServiceNotification; import android.hardware.health.V1_0.HealthInfo; Loading Loading @@ -73,6 +73,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; Loading Loading @@ -117,6 +119,8 @@ public final class BatteryService extends SystemService { private static final int BATTERY_SCALE = 100; // battery capacity is a percentage private static final long HEALTH_HAL_WAIT_MS = 1000; private static final long BATTERY_LEVEL_CHANGE_THROTTLE_MS = 60_000; private static final int MAX_BATTERY_LEVELS_QUEUE_SIZE = 100; // Used locally for determining when to make a last ditch effort to log // discharge stats before the device dies. Loading Loading @@ -178,7 +182,8 @@ public final class BatteryService extends SystemService { private HealthServiceWrapper mHealthServiceWrapper; private HealthHalCallback mHealthHalCallback; private BatteryPropertiesRegistrar mBatteryPropertiesRegistrar; private HandlerThread mHandlerThread; private ArrayDeque<Bundle> mBatteryLevelsEventQueue; private long mLastBatteryLevelChangedSentMs; public BatteryService(Context context) { super(context); Loading @@ -198,6 +203,8 @@ public final class BatteryService extends SystemService { mShutdownBatteryTemperature = mContext.getResources().getInteger( com.android.internal.R.integer.config_shutdownBatteryTemperature); mBatteryLevelsEventQueue = new ArrayDeque<>(); // watch for invalid charger messages if the invalid_charger switch exists if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) { UEventObserver invalidChargerObserver = new UEventObserver() { Loading Loading @@ -585,7 +592,11 @@ public final class BatteryService extends SystemService { // We are doing this after sending the above broadcasts, so anything processing // them will get the new sequence number at that point. (See for example how testing // of JobScheduler's BatteryController works.) sendIntentLocked(); sendBatteryChangedIntentLocked(); if (mLastBatteryLevel != mHealthInfo.batteryLevel) { sendBatteryLevelChangedIntentLocked(); } // Update the battery LED mLed.updateLightsLocked(); Loading @@ -610,7 +621,7 @@ public final class BatteryService extends SystemService { } } private void sendIntentLocked() { private void sendBatteryChangedIntentLocked() { // Pack up the values and broadcast them to everyone final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY Loading Loading @@ -639,12 +650,51 @@ public final class BatteryService extends SystemService { + ", info:" + mHealthInfo.toString()); } mHandler.post(new Runnable() { @Override public void run() { ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL); mHandler.post(() -> ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL)); } }); private void sendBatteryLevelChangedIntentLocked() { Bundle event = new Bundle(); long now = SystemClock.elapsedRealtime(); event.putInt(BatteryManager.EXTRA_SEQUENCE, mSequence); event.putInt(BatteryManager.EXTRA_STATUS, mHealthInfo.batteryStatus); event.putInt(BatteryManager.EXTRA_HEALTH, mHealthInfo.batteryHealth); event.putBoolean(BatteryManager.EXTRA_PRESENT, mHealthInfo.batteryPresent); event.putInt(BatteryManager.EXTRA_LEVEL, mHealthInfo.batteryLevel); event.putBoolean(BatteryManager.EXTRA_BATTERY_LOW, mSentLowBatteryBroadcast); event.putInt(BatteryManager.EXTRA_SCALE, BATTERY_SCALE); event.putInt(BatteryManager.EXTRA_PLUGGED, mPlugType); event.putInt(BatteryManager.EXTRA_VOLTAGE, mHealthInfo.batteryVoltage); event.putLong(BatteryManager.EXTRA_EVENT_TIMESTAMP, now); boolean queueWasEmpty = mBatteryLevelsEventQueue.isEmpty(); mBatteryLevelsEventQueue.add(event); // Make sure queue is bounded and doesn't exceed intent payload limits if (mBatteryLevelsEventQueue.size() > MAX_BATTERY_LEVELS_QUEUE_SIZE) { mBatteryLevelsEventQueue.removeFirst(); } if (queueWasEmpty) { // send now if last event was before throttle interval, otherwise delay long delay = now - mLastBatteryLevelChangedSentMs > BATTERY_LEVEL_CHANGE_THROTTLE_MS ? 0 : mLastBatteryLevelChangedSentMs + BATTERY_LEVEL_CHANGE_THROTTLE_MS - now; mHandler.postDelayed(this::sendEnqueuedBatteryLevelChangedEvents, delay); } } private void sendEnqueuedBatteryLevelChangedEvents() { ArrayList<Bundle> events; synchronized (mLock) { events = new ArrayList<>(mBatteryLevelsEventQueue); mBatteryLevelsEventQueue.clear(); } final Intent intent = new Intent(Intent.ACTION_BATTERY_LEVEL_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); intent.putParcelableArrayListExtra(BatteryManager.EXTRA_EVENTS, events); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, android.Manifest.permission.BATTERY_STATS); mLastBatteryLevelChangedSentMs = SystemClock.elapsedRealtime(); } private void logBatteryStatsLocked() { Loading Loading
api/system-current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -840,6 +840,7 @@ package android.content { } public class Intent implements java.lang.Cloneable android.os.Parcelable { field public static final java.lang.String ACTION_BATTERY_LEVEL_CHANGED = "android.intent.action.BATTERY_LEVEL_CHANGED"; field public static final java.lang.String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY"; field public static final java.lang.String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED"; field public static final java.lang.String ACTION_FACTORY_RESET = "android.intent.action.FACTORY_RESET"; Loading Loading @@ -3612,6 +3613,11 @@ package android.nfc { package android.os { public class BatteryManager { field public static final java.lang.String EXTRA_EVENTS = "android.os.extra.EVENTS"; field public static final java.lang.String EXTRA_EVENT_TIMESTAMP = "android.os.extra.EVENT_TIMESTAMP"; } public final class ConfigUpdate { field public static final java.lang.String ACTION_UPDATE_CARRIER_PROVISIONING_URLS = "android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS"; field public static final java.lang.String ACTION_UPDATE_CT_LOGS = "android.intent.action.UPDATE_CT_LOGS"; Loading
core/java/android/content/Intent.java +17 −0 Original line number Diff line number Diff line Loading @@ -2448,6 +2448,23 @@ public class Intent implements Parcelable, Cloneable { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED"; /** * Broadcast Action: Sent when the current battery level changes. * * It has {@link android.os.BatteryManager#EXTRA_EVENTS} that carries a list of {@link Bundle} * instances representing individual battery level changes with associated * extras from {@link #ACTION_BATTERY_CHANGED}. * * <p class="note"> * This broadcast requires {@link android.Manifest.permission#BATTERY_STATS} permission. * * @hide */ @SystemApi public static final String ACTION_BATTERY_LEVEL_CHANGED = "android.intent.action.BATTERY_LEVEL_CHANGED"; /** * Broadcast Action: Indicates low battery condition on the device. * This broadcast corresponds to the "Low battery warning" system dialog. Loading
core/java/android/os/BatteryManager.java +18 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.os; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.content.Intent; Loading Loading @@ -138,6 +139,23 @@ public class BatteryManager { */ public static final String EXTRA_SEQUENCE = "seq"; /** * Extra for {@link android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED}: * Contains list of Bundles representing battery events * @hide */ @SystemApi public static final String EXTRA_EVENTS = "android.os.extra.EVENTS"; /** * Extra for event in {@link android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED}: * Long value representing time when event occurred as returned by * {@link android.os.SystemClock#elapsedRealtime()} * @hide */ @SystemApi public static final String EXTRA_EVENT_TIMESTAMP = "android.os.extra.EVENT_TIMESTAMP"; // values for "status" field in the ACTION_BATTERY_CHANGED Intent public static final int BATTERY_STATUS_UNKNOWN = Constants.BATTERY_STATUS_UNKNOWN; public static final int BATTERY_STATUS_CHARGING = Constants.BATTERY_STATUS_CHARGING; Loading
core/res/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ <protected-broadcast android:name="android.intent.action.SPLIT_CONFIGURATION_CHANGED" /> <protected-broadcast android:name="android.intent.action.LOCALE_CHANGED" /> <protected-broadcast android:name="android.intent.action.BATTERY_CHANGED" /> <protected-broadcast android:name="android.intent.action.BATTERY_LEVEL_CHANGED" /> <protected-broadcast android:name="android.intent.action.BATTERY_LOW" /> <protected-broadcast android:name="android.intent.action.BATTERY_OKAY" /> <protected-broadcast android:name="android.intent.action.ACTION_POWER_CONNECTED" /> Loading
services/core/java/com/android/server/BatteryService.java +60 −10 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.app.ActivityManagerInternal; import android.database.ContentObserver; import android.os.BatteryStats; import android.os.Bundle; import android.os.PowerManager; import android.os.ResultReceiver; import android.os.ShellCallback; Loading @@ -35,7 +36,6 @@ import android.app.ActivityManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.hidl.manager.V1_0.IServiceManager; import android.hidl.manager.V1_0.IServiceNotification; import android.hardware.health.V1_0.HealthInfo; Loading Loading @@ -73,6 +73,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; Loading Loading @@ -117,6 +119,8 @@ public final class BatteryService extends SystemService { private static final int BATTERY_SCALE = 100; // battery capacity is a percentage private static final long HEALTH_HAL_WAIT_MS = 1000; private static final long BATTERY_LEVEL_CHANGE_THROTTLE_MS = 60_000; private static final int MAX_BATTERY_LEVELS_QUEUE_SIZE = 100; // Used locally for determining when to make a last ditch effort to log // discharge stats before the device dies. Loading Loading @@ -178,7 +182,8 @@ public final class BatteryService extends SystemService { private HealthServiceWrapper mHealthServiceWrapper; private HealthHalCallback mHealthHalCallback; private BatteryPropertiesRegistrar mBatteryPropertiesRegistrar; private HandlerThread mHandlerThread; private ArrayDeque<Bundle> mBatteryLevelsEventQueue; private long mLastBatteryLevelChangedSentMs; public BatteryService(Context context) { super(context); Loading @@ -198,6 +203,8 @@ public final class BatteryService extends SystemService { mShutdownBatteryTemperature = mContext.getResources().getInteger( com.android.internal.R.integer.config_shutdownBatteryTemperature); mBatteryLevelsEventQueue = new ArrayDeque<>(); // watch for invalid charger messages if the invalid_charger switch exists if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) { UEventObserver invalidChargerObserver = new UEventObserver() { Loading Loading @@ -585,7 +592,11 @@ public final class BatteryService extends SystemService { // We are doing this after sending the above broadcasts, so anything processing // them will get the new sequence number at that point. (See for example how testing // of JobScheduler's BatteryController works.) sendIntentLocked(); sendBatteryChangedIntentLocked(); if (mLastBatteryLevel != mHealthInfo.batteryLevel) { sendBatteryLevelChangedIntentLocked(); } // Update the battery LED mLed.updateLightsLocked(); Loading @@ -610,7 +621,7 @@ public final class BatteryService extends SystemService { } } private void sendIntentLocked() { private void sendBatteryChangedIntentLocked() { // Pack up the values and broadcast them to everyone final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY Loading Loading @@ -639,12 +650,51 @@ public final class BatteryService extends SystemService { + ", info:" + mHealthInfo.toString()); } mHandler.post(new Runnable() { @Override public void run() { ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL); mHandler.post(() -> ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL)); } }); private void sendBatteryLevelChangedIntentLocked() { Bundle event = new Bundle(); long now = SystemClock.elapsedRealtime(); event.putInt(BatteryManager.EXTRA_SEQUENCE, mSequence); event.putInt(BatteryManager.EXTRA_STATUS, mHealthInfo.batteryStatus); event.putInt(BatteryManager.EXTRA_HEALTH, mHealthInfo.batteryHealth); event.putBoolean(BatteryManager.EXTRA_PRESENT, mHealthInfo.batteryPresent); event.putInt(BatteryManager.EXTRA_LEVEL, mHealthInfo.batteryLevel); event.putBoolean(BatteryManager.EXTRA_BATTERY_LOW, mSentLowBatteryBroadcast); event.putInt(BatteryManager.EXTRA_SCALE, BATTERY_SCALE); event.putInt(BatteryManager.EXTRA_PLUGGED, mPlugType); event.putInt(BatteryManager.EXTRA_VOLTAGE, mHealthInfo.batteryVoltage); event.putLong(BatteryManager.EXTRA_EVENT_TIMESTAMP, now); boolean queueWasEmpty = mBatteryLevelsEventQueue.isEmpty(); mBatteryLevelsEventQueue.add(event); // Make sure queue is bounded and doesn't exceed intent payload limits if (mBatteryLevelsEventQueue.size() > MAX_BATTERY_LEVELS_QUEUE_SIZE) { mBatteryLevelsEventQueue.removeFirst(); } if (queueWasEmpty) { // send now if last event was before throttle interval, otherwise delay long delay = now - mLastBatteryLevelChangedSentMs > BATTERY_LEVEL_CHANGE_THROTTLE_MS ? 0 : mLastBatteryLevelChangedSentMs + BATTERY_LEVEL_CHANGE_THROTTLE_MS - now; mHandler.postDelayed(this::sendEnqueuedBatteryLevelChangedEvents, delay); } } private void sendEnqueuedBatteryLevelChangedEvents() { ArrayList<Bundle> events; synchronized (mLock) { events = new ArrayList<>(mBatteryLevelsEventQueue); mBatteryLevelsEventQueue.clear(); } final Intent intent = new Intent(Intent.ACTION_BATTERY_LEVEL_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); intent.putParcelableArrayListExtra(BatteryManager.EXTRA_EVENTS, events); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, android.Manifest.permission.BATTERY_STATS); mLastBatteryLevelChangedSentMs = SystemClock.elapsedRealtime(); } private void logBatteryStatsLocked() { Loading