Skip to content

Commit fdcb225

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Fix a deadlock involving BatteryService." into jb-mr1-dev
2 parents 6409e44 + 605ea69 commit fdcb225

File tree

1 file changed

+74
-24
lines changed

1 file changed

+74
-24
lines changed

services/java/com/android/server/BatteryService.java

Lines changed: 74 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import android.os.BatteryManager;
2828
import android.os.Binder;
2929
import android.os.FileUtils;
30+
import android.os.Handler;
3031
import android.os.IBinder;
3132
import android.os.DropBoxManager;
3233
import android.os.RemoteException;
@@ -66,6 +67,14 @@
6667
* <p>&quot;temperature&quot; - int, current battery temperature in tenths of
6768
* a degree Centigrade</p>
6869
* <p>&quot;technology&quot; - 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
*/
7079
public 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

Comments
 (0)