JB的Power的source比起之前的版本有有了一些改動,不過總的來說整個流程還是沒有怎麼變,只是一些文件和路徑變了。沒有辦法,剛看完一個部份的代碼,Google又在新的版本中做了改動,唯一的辦法就只能是把代碼的思路和流程弄清,至于code是怎麼碼的是其實,因為代碼是不斷的變而思想一般來說變化并不是那么大。今天就把power部份的reboot的一個流程給理一下。Shutdonw和reboot其實是差不多的。
5shutdownInner函數如下,其調用了beginShutdownSequence(context);
1,首先我們就從PowerManager開始吧,一般來說,我們要想在代碼中調用重啟,我們可以通過下面的代碼來實現
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
pm.reboot(null);//些處我們給的是null,如果我們給的是recovery,發么系統就會重啟進入到recovery模式
2,接下我們就跟進/frameworks/base/core/java/android/os/PowerManager.java
在PowerManager.java中有如下代碼
public void reboot(String reason)
{
try {
mService.reboot(reason);//些處的mService就是PowerManagerService
} catch (RemoteException e) {
}
}
3.于是我們來到了/frameworks/base/services/java/com/android/server/PowerManagerService.java
在PowerManagerService中的reboot如下,我們看到其實它是調用了ShutdownThread的reboot.
public void reboot(String reason)
{
.......
Runnable runnable = new Runnable() {
public void run() {
synchronized (this) {
ShutdownThread.reboot(mContext, finalReason, false);//調用ShutdownThread的reboot
}
}
};
// ShutdownThread must run on a looper capable of displaying the UI.
mHandler.post(runnable);
.......
}
4,讓我們跟進/frameworks/base/services/java/com/android/server/pm/ShutdownThread.java
我們看到其調用了shutdownInner函數
public static void reboot(final Context context, String reason, boolean confirm) {
mReboot = true;
mRebootSafeMode = false;
mRebootReason = reason;
shutdownInner(context, confirm);
}
5shutdownInner函數如下,其調用了beginShutdownSequence(context);
static void shutdownInner(final Context context, boolean confirm) {
....
if (confirm) {
final CloseDialogReceiver closer = new CloseDialogReceiver(context);
final AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(mRebootSafeMode
? com.android.internal.R.string.reboot_safemode_title
: com.android.internal.R.string.power_off)
.setMessage(resourceId)
.setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
beginShutdownSequence(context);//調用beginShutdownSequence
}
})
.setNegativeButton(com.android.internal.R.string.no, null)
.create();
closer.dialog = dialog;
dialog.setOnDismissListener(closer);
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
dialog.show();
} else {
beginShutdownSequence(context);
}
}
6 beginShutdownSequence如下
private static void beginShutdownSequence(Context context) {
......
sInstance.start();//從這兒就會開始調用到run()方法
}
7在run()方法中也會做一些reboot之前的清除工作,關掉要關的服務等。基最終會調用
public void run() { 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(); } }; ......省略 // Set initial variables and time out time. mActionDone = false; final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME; synchronized (mActionDoneSync) { try { final IMountService mount = IMountService.Stub.asInterface( ServiceManager.checkService("mount")); if (mount != null) { mount.shutdown(observer); } else { Log.w(TAG, "MountService unavailable for shutdown"); } } catch (Exception e) { Log.e(TAG, "Exception during MountService shutdown", e); } while (!mActionDone) { long delay = endShutTime - SystemClock.elapsedRealtime(); if (delay <= 0) { Log.w(TAG, "Shutdown wait timed out"); break; } try { mActionDoneSync.wait(delay); } catch (InterruptedException e) { } } } rebootOrShutdown(mReboot, mRebootReason);//又繞到rebootOrShutdown函數 }
8在rebootOrShutdown函數中會根據reboot參數來決定是重啟還是關機
487 public static void rebootOrShutdown(boolean reboot, String reason) { 488 if (reboot) { 489 Log.i(TAG, "Rebooting, reason: " + reason); 490 try { 491 PowerManagerService.lowLevelReboot(reason);//我們偉進來的reboot參數為true,所以走這一支 492 } catch (Exception e) { 493 Log.e(TAG, "Reboot failed, will attempt shutdown instead", e); 494 } 495 } else if (SHUTDOWN_VIBRATE_MS > 0) { 496 // vibrate before shutting down 497 Vibrator vibrator = new SystemVibrator(); 498 try { 499 vibrator.vibrate(SHUTDOWN_VIBRATE_MS); 500 } catch (Exception e) { 501 // Failure to vibrate shouldn't interrupt shutdown. Just log it. 502 Log.w(TAG, "Failed to vibrate during shutdown.", e); 503 } 504 505 // vibrator is asynchronous so we need to wait to avoid shutting down too soon. 506 try { 507 Thread.sleep(SHUTDOWN_VIBRATE_MS); 508 } catch (InterruptedException unused) { 509 } 510 } 511 512 // Shutdown power 513 Log.i(TAG, "Performing low-level shutdown..."); 514 PowerManagerService.lowLevelShutdown();//如果我們偉進來的reboot為false那就是關機 515 } 516}
9從上面的代碼我們又回到了PowerManagerService.其實就是要開一個線程來在reboot之前把要做的一些工作先做完。好吧,我們來看一下lowLevelReboot.
723 public static void lowLevelReboot(String reason) throws IOException { 724 nativeReboot(reason);//哈哈,還是要進入到時JNI 725 }
10我們繞來繞去其實最終還是要通過JNI和下邊交流。讓我們來看一下/frameworks/base/services/jni/com_android_server_PowerManagerService.cpp中的natievReboot是怎麼樣的
199static void nativeReboot(JNIEnv *env, jobject clazz, jstring reason) { 200 if (reason == NULL) { 201 android_reboot(ANDROID_RB_RESTART, 0, 0);//這兒是直接重啟,因為沒有偉reason, 202 } else { 203 const char *chars = env->GetStringUTFChars(reason, NULL); 204 android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars);//這兒一般是上面偉入了recovery而重啟進入recovery,主要是oat或手機重置 205 env->ReleaseStringUTFChars(reason, chars); // In case it fails. 206 } 207 jniThrowIOException(env, errno); 208}
11上面的anddroid_reboot在/system/core/libcutils/android_reboot.c中。接下來我們就看一下android_reboot()又做些什麽。
104int android_reboot(int cmd, int flags, char *arg) 105{ 106 int ret; 107 108 if (!(flags & ANDROID_RB_FLAG_NO_SYNC)) 109 sync(); 110 111 if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO)) 112 remount_ro(); 113 114 switch (cmd) { 115 case ANDROID_RB_RESTART://我們一般的重啟就是偉一這個,從上面的代碼有體現 116 ret = reboot(RB_AUTOBOOT); 117 break; 118 119 case ANDROID_RB_POWEROFF://shutdown走的是這兒,其實reboot和shutdown就很相似,從powermanagerservice中才都是call了nativeReboot 120 ret = reboot(RB_POWER_OFF); 121 break; 122 123 case ANDROID_RB_RESTART2://當一開始偉入了recovery時會走這兒 124 ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 125 LINUX_REBOOT_CMD_RESTART2, arg); 126 break; 127 128 default: 129 ret = -1; 130 } 131 132 return ret; 133} 134
12上面的 reboot(RB_AUTOBOOT)又會call到/bionic/libc/unistd/reboot.c
int reboot (int mode) { return __reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL ); //這兒的__reboot和上面的case ANDROID_RB_RESTART2的__reboot就是一樣的 }
13__reboot就到了/bionic/libc/arch-arm/syscalls/__reboot.S
這兒是一個內聯彙編的函數。通過swi軟中斷來重啟設備。到此android部份的代碼重啟流程就大致完成。其實我們剛才也注意到shutdown和reboot差不多走一樣的路線下來。
5ENTRY(__reboot) 6 .save {r4, r7} 7 stmfd sp!, {r4, r7} 8 ldr r7, =__NR_reboot 9 swi #0 10 ldmfd sp!, {r4, r7} 11 movs r0, r0 12 bxpl lr 13 b __set_syscall_errno 14END(__reboot)