2727import android .os .BatteryManager ;
2828import android .os .Binder ;
2929import android .os .FileUtils ;
30+ import android .os .Handler ;
3031import android .os .IBinder ;
3132import android .os .DropBoxManager ;
3233import android .os .RemoteException ;
6667 * <p>"temperature" - int, current battery temperature in tenths of
6768 * a degree Centigrade</p>
6869 * <p>"technology" - String, the type of battery installed, e.g. "Li-ion"</p>
70+ *
71+ * <p>
72+ * The battery service may be called by the power manager while holding its locks so
73+ * we take care to post all outcalls into the activity manager to a handler.
74+ *
75+ * FIXME: Ideally the power manager would perform all of its calls into the battery
76+ * service asynchronously itself.
77+ * </p>
6978 */
7079public final class BatteryService extends Binder {
7180 private static final String TAG = BatteryService .class .getSimpleName ();
@@ -89,6 +98,7 @@ public final class BatteryService extends Binder {
8998
9099 private final Context mContext ;
91100 private final IBatteryStats mBatteryStats ;
101+ private final Handler mHandler ;
92102
93103 private final Object mLock = new Object ();
94104
@@ -137,6 +147,7 @@ public final class BatteryService extends Binder {
137147
138148 public BatteryService (Context context , LightsService lights ) {
139149 mContext = context ;
150+ mHandler = new Handler (true /*async*/ );
140151 mLed = new Led (context , lights );
141152 mBatteryStats = BatteryStatsService .getService ();
142153
@@ -228,25 +239,37 @@ public boolean isBatteryLow() {
228239 private void shutdownIfNoPowerLocked () {
229240 // shut down gracefully if our battery is critically low and we are not powered.
230241 // wait until the system has booted before attempting to display the shutdown dialog.
231- if (mBatteryLevel == 0 && !isPoweredLocked (BatteryManager .BATTERY_PLUGGED_ANY )
232- && ActivityManagerNative .isSystemReady ()) {
233- Intent intent = new Intent (Intent .ACTION_REQUEST_SHUTDOWN );
234- intent .putExtra (Intent .EXTRA_KEY_CONFIRM , false );
235- intent .setFlags (Intent .FLAG_ACTIVITY_NEW_TASK );
236- mContext .startActivityAsUser (intent , UserHandle .CURRENT );
242+ if (mBatteryLevel == 0 && !isPoweredLocked (BatteryManager .BATTERY_PLUGGED_ANY )) {
243+ mHandler .post (new Runnable () {
244+ @ Override
245+ public void run () {
246+ if (ActivityManagerNative .isSystemReady ()) {
247+ Intent intent = new Intent (Intent .ACTION_REQUEST_SHUTDOWN );
248+ intent .putExtra (Intent .EXTRA_KEY_CONFIRM , false );
249+ intent .setFlags (Intent .FLAG_ACTIVITY_NEW_TASK );
250+ mContext .startActivityAsUser (intent , UserHandle .CURRENT );
251+ }
252+ }
253+ });
237254 }
238255 }
239256
240257 private void shutdownIfOverTempLocked () {
241258 // shut down gracefully if temperature is too high (> 68.0C by default)
242259 // wait until the system has booted before attempting to display the
243260 // shutdown dialog.
244- if (mBatteryTemperature > mShutdownBatteryTemperature
245- && ActivityManagerNative .isSystemReady ()) {
246- Intent intent = new Intent (Intent .ACTION_REQUEST_SHUTDOWN );
247- intent .putExtra (Intent .EXTRA_KEY_CONFIRM , false );
248- intent .setFlags (Intent .FLAG_ACTIVITY_NEW_TASK );
249- mContext .startActivityAsUser (intent , UserHandle .CURRENT );
261+ if (mBatteryTemperature > mShutdownBatteryTemperature ) {
262+ mHandler .post (new Runnable () {
263+ @ Override
264+ public void run () {
265+ if (ActivityManagerNative .isSystemReady ()) {
266+ Intent intent = new Intent (Intent .ACTION_REQUEST_SHUTDOWN );
267+ intent .putExtra (Intent .EXTRA_KEY_CONFIRM , false );
268+ intent .setFlags (Intent .FLAG_ACTIVITY_NEW_TASK );
269+ mContext .startActivityAsUser (intent , UserHandle .CURRENT );
270+ }
271+ }
272+ });
250273 }
251274 }
252275
@@ -373,25 +396,47 @@ private void processValuesLocked() {
373396 // Separate broadcast is sent for power connected / not connected
374397 // since the standard intent will not wake any applications and some
375398 // applications may want to have smart behavior based on this.
376- Intent statusIntent = new Intent ();
377- statusIntent .setFlags (Intent .FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT );
378399 if (mPlugType != 0 && mLastPlugType == 0 ) {
379- statusIntent .setAction (Intent .ACTION_POWER_CONNECTED );
380- mContext .sendBroadcastAsUser (statusIntent , UserHandle .ALL );
400+ mHandler .post (new Runnable () {
401+ @ Override
402+ public void run () {
403+ Intent statusIntent = new Intent (Intent .ACTION_POWER_CONNECTED );
404+ statusIntent .setFlags (Intent .FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT );
405+ mContext .sendBroadcastAsUser (statusIntent , UserHandle .ALL );
406+ }
407+ });
381408 }
382409 else if (mPlugType == 0 && mLastPlugType != 0 ) {
383- statusIntent .setAction (Intent .ACTION_POWER_DISCONNECTED );
384- mContext .sendBroadcastAsUser (statusIntent , UserHandle .ALL );
410+ mHandler .post (new Runnable () {
411+ @ Override
412+ public void run () {
413+ Intent statusIntent = new Intent (Intent .ACTION_POWER_DISCONNECTED );
414+ statusIntent .setFlags (Intent .FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT );
415+ mContext .sendBroadcastAsUser (statusIntent , UserHandle .ALL );
416+ }
417+ });
385418 }
386419
387420 if (sendBatteryLow ) {
388421 mSentLowBatteryBroadcast = true ;
389- statusIntent .setAction (Intent .ACTION_BATTERY_LOW );
390- mContext .sendBroadcastAsUser (statusIntent , UserHandle .ALL );
422+ mHandler .post (new Runnable () {
423+ @ Override
424+ public void run () {
425+ Intent statusIntent = new Intent (Intent .ACTION_BATTERY_LOW );
426+ statusIntent .setFlags (Intent .FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT );
427+ mContext .sendBroadcastAsUser (statusIntent , UserHandle .ALL );
428+ }
429+ });
391430 } else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel ) {
392431 mSentLowBatteryBroadcast = false ;
393- statusIntent .setAction (Intent .ACTION_BATTERY_OKAY );
394- mContext .sendBroadcastAsUser (statusIntent , UserHandle .ALL );
432+ mHandler .post (new Runnable () {
433+ @ Override
434+ public void run () {
435+ Intent statusIntent = new Intent (Intent .ACTION_BATTERY_OKAY );
436+ statusIntent .setFlags (Intent .FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT );
437+ mContext .sendBroadcastAsUser (statusIntent , UserHandle .ALL );
438+ }
439+ });
395440 }
396441
397442 // Update the battery LED
@@ -416,7 +461,7 @@ else if (mPlugType == 0 && mLastPlugType != 0) {
416461
417462 private void sendIntentLocked () {
418463 // Pack up the values and broadcast them to everyone
419- Intent intent = new Intent (Intent .ACTION_BATTERY_CHANGED );
464+ final Intent intent = new Intent (Intent .ACTION_BATTERY_CHANGED );
420465 intent .addFlags (Intent .FLAG_RECEIVER_REGISTERED_ONLY
421466 | Intent .FLAG_RECEIVER_REPLACE_PENDING );
422467
@@ -446,7 +491,12 @@ private void sendIntentLocked() {
446491 ", icon:" + icon + ", invalid charger:" + mInvalidCharger );
447492 }
448493
449- ActivityManagerNative .broadcastStickyIntent (intent , null , UserHandle .USER_ALL );
494+ mHandler .post (new Runnable () {
495+ @ Override
496+ public void run () {
497+ ActivityManagerNative .broadcastStickyIntent (intent , null , UserHandle .USER_ALL );
498+ }
499+ });
450500 }
451501
452502 private void logBatteryStatsLocked () {
0 commit comments