--------------------------------Introduction--------------------------
1. 在PowerManager的API文档中,给出了一个关机/重启接口:
public voidreboot (String reason)
2. 对于这个接口的描述很简单,就是几句话。
接口的作用就是重启设备,而且,就算重启成功了也没有返回值。
需要包含REBOOT权限,也就是android.permission.REBOOT
唯一参数reason代表需要的特定重启模式,比如recovery,当然也可以为null。
--------------------------------上层空间--------------------------------
1.frameworks/base/core/java/android/os/PowerManager.java
/**
* Reboot the device. Will not return if the reboot is
* successful. Requires the {@link android.Manifest.permission#REBOOT}
* permission.
*
* @param reason code to pass to the kernel (e.g., "recovery") to
* request special boot modes, or null.
*/
publicvoidreboot(String reason)
{
try{
mService.reboot(reason);
} catch(RemoteException e) {
}
}
mService为IPowerManager Binder接口服务。
/**
* {@hide}
*/
publicPowerManager(IPowerManager service, Handler handler)
{
mService = service;
mHandler = handler;
}
2.frameworks/base/core/java/android/os/IPowerManager.aidl
interfaceIPowerManager
{
...
voidreboot(String reason);
...
}
3.frameworks/base/services/java/com/android/server/PowerManagerService.java
/**
* Reboot the device immediately, passing 'reason' (may be null)
* to the underlying __reboot system call. Should not return.
*/
publicvoidreboot(String reason)
{
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
if(mHandler ==null|| !ActivityManagerNative.isSystemReady()) {
thrownewIllegalStateException("Too early to call reboot()");
}
finalString finalReason = reason;
Runnable runnable = newRunnable() {
publicvoidrun() {
synchronized(this) {
ShutdownThread.reboot(getUiContext(), finalReason, false);
}
}
};
// ShutdownThread must run on a looper capable of displaying the UI.
mHandler.post(runnable);
// PowerManager.reboot() is documented not to return so just wait for the inevitable.
synchronized(runnable) {
while(true) {
try{
runnable.wait();
} catch(InterruptedException e) {
}
}
}
}
4.frameworks/base/services/java/com/android/server/pm/ShutdownThread.java
/**
* Request a clean shutdown, waiting for subsystems to clean up their
* state etc. Must be called from a Looper thread in which its UI
* is shown.
*
* @param context Context used to display the shutdown progress dialog.
* @param reason code to pass to the kernel (e.g. "recovery"), or null.
* @param confirm true if user confirmation is needed before shutting down.
*/
publicstaticvoidreboot(finalContext context, String reason,booleanconfirm) {
mReboot = true;
mRebootSafeMode = false;
mRebootReason = reason;
shutdownInner(context, confirm);
}
如上所叙述,这里说明是需要重启,且不是安全模式,重启参数为传递下来的reason,shutdownInner的confirm参数是用来设置是否有确认提示框的,通过reboot接口调用重启是没有的,为false。
重启的实现在run()中,因为ShutdownThread是Thread的扩展,所以run会自动运行,如下。
/**
* 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() {
checkShutdownFlow();
while (mShutdownFlow == IPO_SHUTDOWN_FLOW) {
stMgr.saveStates(mContext);
stMgr.enterShutdown(mContext);
running();
}
if (mShutdownFlow != IPO_SHUTDOWN_FLOW) {
stMgr.enterShutdown(mContext);
running();
}
}
public void running() {
if(sPreShutdownApi != null){
try {
sPreShutdownApi.onPowerOff();
} catch (RemoteException e) {
Log.e(TAG, "onPowerOff exception" + e.getMessage());
}
}else{
Log.w(TAG, "sPreShutdownApi is null");
}
command = SystemProperties.get("sys.ipo.pwrdncap");
BroadcastReceiver br = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
// We don't allow apps to cancel this, so ignore the result.
actionDone();
}
};
/*
* Write a system property in case the system_server reboots before we
* get to the actual hardware restart. If that happens, we'll retry at
* the beginning of the SystemServer startup.
*/
{
String reason = (mReboot ? "1":"0") + (mRebootReason !=null? mRebootReason :"");
SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
}
/*
* If we are rebooting into safe mode, write a system property
* indicating so.
*/
if(mRebootSafeMode) {
SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
}
...
rebootOrShutdown(mReboot, mRebootReason);
}
如上所叙述,在重启前会将重启原因写入sys.shutdown.requested,如果没有则为空,如果是安全模式还会将persist.sys.safemode置1,之后会进行一些关机前的预处理,关闭ActivityManager以及MountService,最终调用rebootOrShutdown进行关机操作。
======>>>>>>android2中的rebootOrShutdown
/**
* Do not call this directly. Use {@link #reboot(Context, String, boolean)}
* or {@link #shutdown(Context, boolean)} instead.
*
* @param reboot true to reboot or false to shutdown
* @param reason reason for reboot
*/
publicstaticvoidrebootOrShutdown(booleanreboot, String reason) {
if(reboot) {
Log.i(TAG, "Rebooting, reason: "+ reason);
try{
PowerManagerService.lowLevelReboot(reason); ///重启Reboot
} catch(Exception e) {
Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);
}
} elseif(SHUTDOWN_VIBRATE_MS >0) { ///关机的时候需要震动,就是这里了
//SHUTDOWN_VIBRATE_MS,默认的定义是500ms。
// vibrate before shutting down
Vibrator vibrator = newSystemVibrator();
try{
vibrator.vibrate(SHUTDOWN_VIBRATE_MS);</