- 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函數
此线程中的动作为:
(1) 广播全局事件,ACTION_SHUTDOWN Intent
(2) shutdown ActivityManager 服务
(3) 停止电话服务 (radio phone service)
(4) 停止mount 服务
(5) 最后调用 rebootOrShutdown(mReboot, mRebootReason);
在rebootOrShutdown(mReboot,mRebootReason);中
调用PowerManagerService.lowLevelShutdown();
- public static void rebootOrShutdown(boolean reboot, String reason) {
- if (reboot) {
- Log.i(TAG, "Rebooting, reason: " + reason);
- try {
- PowerManagerService.lowLevelReboot(reason);//我們偉進來的reboot參數為true,所以走這一支
- } catch (Exception e) {
- Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);
- }
- } else if (SHUTDOWN_VIBRATE_MS > 0) {
- // vibrate before shutting down
- Vibrator vibrator = new SystemVibrator();
- try {
- vibrator.vibrate(SHUTDOWN_VIBRATE_MS);
- } catch (Exception e) {
- // Failure to vibrate shouldn't interrupt shutdown. Just log it.
- Log.w(TAG, "Failed to vibrate during shutdown.", e);
- }
- // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
- try {
- Thread.sleep(SHUTDOWN_VIBRATE_MS);
- } catch (InterruptedException unused) {
- }
- }
- // Shutdown power
- Log.i(TAG, "Performing low-level shutdown...");
- PowerManagerService.lowLevelShutdown();//如果我們偉進來的reboot為false那就是關機
- }
此函数在frameworks/base/services/java/com/android/server/PowerManagerService.java中
又回到了PowerManagerService.
其實就是要開一個線程來在reboot之前把要做的一些工作先做完。
好吧,我們來看一下lowLevelReboot.
- public static void lowLevelReboot(String reason) throws IOException {
- nativeReboot(reason);//哈哈,還是要進入到時JNI
- }
lowLevelReboot调用了 JNI 方法 nativeReboot
lowLevelReboot定义在
/frameworks/base/services/jni/com_android_server_PowerManagerService.cpp中
- static void nativeReboot(JNIEnv *env, jobject clazz, jstring reason) {
- if (reason == NULL) {
- android_reboot(ANDROID_RB_RESTART, 0, 0);//這兒是直接重啟,因為沒有偉reason,
- } else {
- const char *chars = env->GetStringUTFChars(reason, NULL);
- android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars);//這兒一般是上面偉入了recovery而重啟進入recovery,主要是oat或手機重置
- env->ReleaseStringUTFChars(reason, chars); // In case it fails.
- }
- jniThrowIOException(env, errno);
- }
上面的android_reboot
在/system/core/libcutils/android_reboot.c中。
接下來我們就看一下android_reboot()又做些什麽。
- int android_reboot(int cmd, int flags, char *arg)
- {
- int ret;
- if (!(flags & ANDROID_RB_FLAG_NO_SYNC))
- sync();
- if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO))
- remount_ro();
- switch (cmd) {
- case ANDROID_RB_RESTART://我們一般的重啟就是偉一這個,從上面的代碼有體現
- ret = reboot(RB_AUTOBOOT);
- break;
- case ANDROID_RB_POWEROFF://shutdown走的是這兒,其實reboot和shutdown就很相似,從powermanagerservice中才都是call了nativeReboot
- ret = reboot(RB_POWER_OFF);
- break;
- case ANDROID_RB_RESTART2://當一開始偉入了recovery時會走這兒
- ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
- LINUX_REBOOT_CMD_RESTART2, arg);
- break;
- default:
- ret = -1;
- }
- return ret;
- }
上面的 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就是一樣的
- }
__reboot就到了/bionic/libc/arch-arm/syscalls/__reboot.S
这是一個内联汇编的函数。
通過swi軟中斷來重啟設備。
到此android部份的代碼重啟流程就大致完成。
其實我們剛才也注意到shutdown和reboot差不多走一樣的路線下來。
- ENTRY(__reboot)
- .save {r4, r7}
- stmfd sp!, {r4, r7}
- ldr r7, =__NR_reboot
- swi #0
- ldmfd sp!, {r4, r7}
- movs r0, r0
- bxpl lr
- b __set_syscall_errno
- END(__reboot)
可以看出来,这里将__reboot的实现映射到了__NR_reboot,
而在bionic/libc/sys/linux-syscalls.h能够找到:
#define __NR_reboot (__NR_SYSCALL_BASE + 88)
其被指定了一个固定的偏移量,在被调用的时候就是通过这个偏移量去内核中寻找对应的入口的,
由此可见,内核中一定有着相同的定义,否则将不能成功调用。
内核中对syscall偏移量的定义在内核源码中的arch/arm/include/asm/unistd.h,
相关信息完全一致。
已经找到了内核中的对应映射,那么下一步就要去找寻真正的实现函数了,
在include/asm-generic/unistd.h中可以找到内核对__NR_reboot的syscall函数映射,即
- /* kernel/sys.c */
- #define __NR_setpriority 140 __SYSCALL(__NR_setpriority, sys_setpriority)
- #define __NR_getpriority 141 __SYSCALL(__NR_getpriority, sys_getpriority)
- #define __NR_reboot 142 __SYSCALL(__NR_reboot, sys_reboot)
kernel/sys.c
在进入这个文件前,我们先去include/linux/syscalls.h中查看一下sys_reboot的定义:
- asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user *arg);
与__reboot的调用参数一致。
进入sys.c文件后,并没有找到名为sys_reboot的函数,而通过仔细查找,
发现一个很有趣的函数,其定义为
- SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg),
对比__reboot的参数,能够符合。究竟是不是这个函数?
同样在include/linux/syscalls.h文件中,能够找到这样几个定义:
- #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
- #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
- #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
- #define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
- #define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
- #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__) ...
- #define SYSCALL_DEFINEx(x, sname, ...) \ __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) ...
- #define __SYSCALL_DEFINEx(x, name, ...) \ asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))
整合后等价于:
- #define SYSCALL_DEFINE4(name, ...) \ asmlinkage long sys##_name(__SC_DECL##4(__VA_ARGS__))
这样就不难看出,
- SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg)
就是sys_reboot,也就是上层调用的__reboot的最终实现。函数实现如下:
4 。内核部分。 kernel/sys.c
其中,
- if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
- cmd = LINUX_REBOOT_CMD_HALT;
- lock_kernel();
- switch (cmd) {
- case LINUX_REBOOT_CMD_RESTART:
- kernel_restart(NULL);
- break;
- case LINUX_REBOOT_CMD_CAD_ON:
- C_A_D = 1;
- break;
- case LINUX_REBOOT_CMD_CAD_OFF:
- C_A_D = 0;
- break;
- case LINUX_REBOOT_CMD_HALT:
- kernel_halt();
- unlock_kernel();
- do_exit(0);
- break;
- case LINUX_REBOOT_CMD_POWER_OFF:
- printk("test powe down in %s(%d)\n", __FILE__, __LINE__);
- kernel_power_off();
- unlock_kernel();
- do_exit(0);