一,主要涉及的类
-
./base/services/java/com/android/server/BatteryService.java
-
./base/services/java/com/android/server/ShutdownActivity.java
-
./base/services/java/com/android/server/power/PowerManagerService.java
-
./base/services/java/com/android/server/power/ShutdownThread.java
-
./base/core/java/android/os/PowerManager.java
二.BatteryService 监控电池电量等信息
android系统app上层更新显示电池电量信息,主要是靠BatterySerivice不断为其更新数据信息。至于如何更新的,另外的博文有分析。
这里主要分析低电量关机相关流程。
BatteryService中的update方法会间隔时间的不断更新。
// 低电量的时候会弹出对话框并且接着关机。
private void shutdownIfNoPowerLocked() {
// shut down gracefully if our battery is critically low and we are not powered.
// wait until the system has booted before attempting to display the shutdown dialog.
//从这里的if判断条件可以看出低电量关机条件电量接近0并且没有连接充电。
if (mBatteryProps.batteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {
mHandler.post(new Runnable() { // the battery is low and battery plugged .
@Override
public void run() {
//跳转到ShutdownActivity.java
if (ActivityManagerNative.isSystemReady()) {
Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
}
}
});
}
}
接下来,跳转到ShutdownActivity.java,这个acitivity比较简单,他吧另外的逻辑放在了子线程,直接获得PowerManagerService并调用其中的方法,因此重点是PowerManagerService.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if(intent==null){return ;} // google do not add this . but i add .
mReboot = Intent.ACTION_REBOOT.equals(intent.getAction()); //false from the batteryService.java
mConfirm = intent.getBooleanExtra(Intent.EXTRA_KEY_CONFIRM, false); // false from the BatteryService.java
Slog.i(TAG, "onCreate(): confirm=" + mConfirm);
Thread thr = new Thread("ShutdownActivity") {
@Override
public void run() {
IPowerManager pm = IPowerManager.Stub.asInterface(
ServiceManager.getService(Context.POWER_SERVICE));
try {
if (mReboot) {
pm.reboot(mConfirm, null, false);
} else {
pm.shutdown(mConfirm, false); //mConfirm ==false
}
} catch (RemoteException e) {
}
}
};
thr.start();
finish();
// Wait for us to tell the power manager to shutdown.
try {
thr.join(); // wait for worker thread to do has job.
} catch (InterruptedException e) {
}
}
接下来,逻辑转移到PowerManagerService中、
/**
* Shuts down the device.
*
* @param confirm If true, shows a shutdown confirmation dialog.
* @param wait If true, this call waits for the shutdown to complete and does not return.
*/
@Override // Binder call
public void shutdown(boolean confirm, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
// u must get get the permission of reboot .
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(true, confirm, null, wait);// true ,false ,null,false
} finally {
Binder.restoreCallingIdentity(ident);
}
}
private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,
final String reason, boolean wait) {
if (mHandler == null || !mSystemReady) {
throw new IllegalStateException("Too early to call shutdown() or reboot()");
}
//看到这里你是否和我一样有点不解? why: 在ShutdownActivity中,是放在了子线程的,而到了这里继续被放到新的子线程。这样?
Runnable runnable = new Runnable() {
@Override
public void run() {
synchronized (this) {
if (shutdown) {
ShutdownThread.shutdown(mContext, confirm);//confirm == false
} else {
ShutdownThread.reboot(mContext, reason, confirm);
}
}
}
};
// ShutdownThread must run on a looper capable of displaying the UI.
Message msg = Message.obtain(mHandler, runnable) ;
msg.setAsynchronous(true); //异步消息
mHandler.sendMessage(msg);
// PowerManager.reboot() is documented not to return so just wait for the inevitable.
下面这段代码...... if (wait) {
synchronized (runnable) {
while (true) {
try {
runnable.wait();
} catch (InterruptedException e) {
}
}