首页 > IT职业 > IT图书 > Android 关机、重启、recovery流程分析
上层应用可以通过PowerManager来实现关机、重启、进recovery等功能。比如RecoverySystem 中就是使用PM使系统进入recovery模式:
源码路径:frameworks/base/core/java/android/os/RecoverySystem.java
private static void bootCommand(Context context, String... args) throws IOException { ......
// Having written the command file, go ahead and reboot
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
pm.reboot(PowerManager.REBOOT_RECOVERY); ......
}
PowerManager会通过aidl与PowerManagerService交互,reboot带reason参数,像重启、关机、恢复出厂设置等等;
源码路径:frameworks/base/core/java/android/os/IPowerManager.aidl
interface IPowerManager{ // WARNING: The first five methods must remain the first five methods because their
// transaction numbers must not change unless IPowerManager.cpp is also updated.
void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, in WorkSource ws,
String historyTag); void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName, int uidtoblame); void releaseWakeLock(IBinder lock, int flags); void updateWakeLockUids(IBinder lock, in int[] uids);
...... void reboot(boolean confirm, String reason, boolean wait); void shutdown(boolean confirm, boolean wait); void crash(String message); void setStayOnSetting(int val); void boostScreenBrightness(long time); // temporarily overrides the screen brightness settings to allow the user to
// see the effect of a settings change without applying it immediately
void setTemporaryScreenBrightnessSettingOverride(int brightness); void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj); // sets the attention light (used by phone app only)
void setAttentionLight(boolean on, int color);
}
源码路径:frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
@Override // Binder call
public void reboot(boolean confirm, String reason, boolean wait) {
...... final long ident = Binder.clearCallingIdentity(); try {
shutdownOrRebootInternal(false, confirm, reason, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
public static void lowLevelShutdown() {
SystemProperties.set("sys.powerctl", "shutdown");
}
public static void lowLevelReboot(String reason) { if (reason == null) {
reason = "";
}
long duration; if (reason.equals(PowerManager.REBOOT_RECOVERY)) {
SystemProperties.set("ctl.start", "pre-recovery"); duration = 300 * 1000L;
} else {
SystemProperties.set("sys.powerctl", "reboot," + reason); duration = 20 * 1000L;
}
try { Thread.sleep(duration);
} catch (InterruptedException e) { Thread.currentThread().interrupt();
}
}
shutdownOrRebootInternal根据reason来决定是调用ShutdownThread的reboot或者shutdown:
private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm, final String reason, boolean wait) {
......
Runnable runnable = new Runnable() { @Override
public void run() { synchronized (this) { if (shutdown) {
ShutdownThread.shutdown(mContext, confirm);
} else {
ShutdownThread.reboot(mContext, reason, confirm);
}
......
不管是关机还是重启都是走shutdownInner 源码路径:frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
public static void reboot(final Context context, String reason, boolean confirm) {
mReboot = true;
mRebootSafeMode = false;
mRebootReason = reason;
shutdownInner(context, confirm);
}
...... public static void shutdown(final Context context, boolean confirm) {
mReboot = false;
mRebootSafeMode = false;
shutdownInner(context, confirm);
}
...... static void shutdownInner(final Context context, boolean confirm) {
......
beginShutdownSequence(context);
}
}
看一下beginShutdownSequence
private static void beginShutdownSequence(Context context) {
...... // start the thread that initiates shutdown
sInstance.mHandler = new Handler() {
};
sInstance.start();
}
已经start了,我们就去run里面瞧一瞧干了什么事,就对“REBOOT_SAFEMODE_PROPERTY”设置了1或者0,然后调用rebootOrShutdown。
/**
* Makes sure we handle the shutdown gracefully.
* Shuts off power regardless of radio and bluetooth state if the alloted time has passed.
*/
public void run() { ....//关机或者重启前的一些处理
String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");
SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);......
if (mRebootSafeMode) {
SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
} ......
rebootOrShutdown(mReboot, mRebootReason);
}
rebootOrShutdown中会调用PMS的lowLevelReboot或者lowLevelShutdown,这两个函数在上面有展示
public static void rebootOrShutdown(boolean reboot, String reason) { if (reboot) { Log.i(TAG, "Rebooting, reason: " + reason);
PowerManagerService.lowLevelReboot(reason);//重启
Log.e(TAG, "Reboot failed, will attempt shutdown instead");
} else if (SHUTDOWN_VIBRATE_MS > 0) { ....//关机震动相关处理
// Shutdown power
Log.i(TAG, "Performing low-level shutdown...");
PowerManagerService.lowLevelShutdown();//关机
}
再回过头去看PowerManagerService里面的lowLevelShutdown,发现关机、重启、recovery等是通过设置Properties来实现控制的:SystemProperties.set("sys.powerctl"......
Android系统开始会执行init,而init会去解析执行init.rc中的内容。其中就有对于Properties “sys.powerctl ”的处理(当“sys.powerctl 发生改变时触发进行powerctl 操作)。 位于源码:system/core/rootdir/init.rc
on property:sys.powerctl=*
powerctl ${sys.powerctl}
而powerctl 是init的内嵌命令,在init源码中: 源码路径:system/core/init/builtins.c
int do_powerctl(int nargs, char **args)
{
...... if (strncmp(command, "shutdown", 8) == 0) {
cmd = ANDROID_RB_POWEROFF; len = 8;
} else if (strncmp(command, "reboot", 6) == 0) {
cmd = ANDROID_RB_RESTART2; len = 6;
} else {
ERROR("powerctl: unrecognized command '%s'n", command); return -EINVAL;
} if (command[len] == ',') {
reboot_target = &command[len + 1];
} else if (command[len] == '
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/430/viewspace-2809611/ ,如需转载,请注明出处,否则将追究法律责任。