Android 关机流程分析-----(2)JNI和kernel层

转载地址:http://blog.csdn.net/xzhang76/article/details/11261965       

       最近遇到fastboot关机电流偏高的问题,虽然最后确认是硬件的问题,但还是顺便分析了一下android开关机的流程。总结一下,加深印象,也方便日后查阅。

Android智能手机和平板一般都有Power key,长按Power key弹出关机对话框,选择power off就会让系统关闭。关机动作从按键触发中断,linux kernel层给android framework层返回按键事件进入framework层,再从 framework层到kernel层执行关机任务。本文分析过程将分成两篇,(1)Framework层 (2)JNI和Kernel层,代码基于自己的android4.3源码。

前面的文章Android 关机流程分析-----(1)Framework层中,分析了framework层的关机流程,本文会继续分析JNI和Kernel层的关机流程。

五、JNI层的接口:android_reboot()

framework层最后执行lowLevelShutdown(),进入nativeShutdown()。在JNI层,有如下对nativeShutdown()以及nativeReboot()的定义。

frameworks/base/services/jni/com_android_server_power_PowerManagerService.cpp

  1. static void nativeShutdown(JNIEnv *env, jclass clazz) {  
  2.     android_reboot(ANDROID_RB_POWEROFF, 0, 0);  
  3. }  
  4.   
  5. static void nativeReboot(JNIEnv *env, jclass clazz, jstring reason) {  
  6.     if (reason == NULL) {  
  7.         android_reboot(ANDROID_RB_RESTART, 0, 0);  
  8.     } else {  
  9.         const char *chars = env->GetStringUTFChars(reason, NULL);  
  10.         android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars);  
  11.         env->ReleaseStringUTFChars(reason, chars);  // In case it fails.  
  12.     }  
  13.     jniThrowIOException(env, errno);  
  14. }  
  15.   
  16. // ----------------------------------------------------------------------------  
  17.   
  18. static JNINativeMethod gPowerManagerServiceMethods[] = {  
  19.     /* name, signature, funcPtr */  
  20.     { "nativeInit""()V",  
  21.             (void*) nativeInit },  
  22.     { "nativeSetPowerState""(ZZ)V",  
  23.             (void*) nativeSetPowerState },  
  24.     { "nativeAcquireSuspendBlocker""(Ljava/lang/String;)V",  
  25.             (void*) nativeAcquireSuspendBlocker },  
  26.     { "nativeReleaseSuspendBlocker""(Ljava/lang/String;)V",  
  27.             (void*) nativeReleaseSuspendBlocker },  
  28.     { "nativeSetInteractive""(Z)V",  
  29.             (void*) nativeSetInteractive },  
  30.     { "nativeSetAutoSuspend""(Z)V",  
  31.             (void*) nativeSetAutoSuspend },  
  32.     { "nativeShutdown""()V",  
  33.             (void*) nativeShutdown },  
  34.     { "nativeReboot""(Ljava/lang/String;)V",  
  35.             (void*) nativeReboot },  
  36. };  
在JNI中,framework层中的nativeShutdown()还是被JNI成nativeShutdown(),然后进入android_reboot(ANDROID_RB_POWEROFF, 0, 0)。
android_reboot()在system/core/libcutils/Android_reboot.c中定义如下:

  1. int android_reboot(int cmd, int flags, char *arg)  
  2. {  
  3.     int ret;  
  4.   
  5.     if (!(flags & ANDROID_RB_FLAG_NO_SYNC))  
  6.         sync();  
  7.   
  8.     if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO))  
  9.         remount_ro();  
  10.   
  11.     switch (cmd) {  
  12.         case ANDROID_RB_RESTART:  
  13.             ret = reboot(RB_AUTOBOOT);  
  14.             break;  
  15.   
  16.         case ANDROID_RB_POWEROFF:  
  17.             ret = reboot(RB_POWER_OFF);  
  18.             break;  
  19.   
  20.         case ANDROID_RB_RESTART2:  
  21.             ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,  
  22.                            LINUX_REBOOT_CMD_RESTART2, arg);  
  23.             break;  
  24.   
  25.         default:  
  26.             ret = -1;  
  27.     }  
  28.   
  29.     return ret;  
  30. }  
1. 参数cmd是命令行参数,在system/core/include/cutils/Android_reboot.h中定义如下:

  1. /* Commands */  
  2. #define ANDROID_RB_RESTART  0xDEAD0001  
  3. #define ANDROID_RB_POWEROFF 0xDEAD0002  
  4. #define ANDROID_RB_RESTART2 0xDEAD0003  
  5.   
  6. /* Flags */  
  7. #define ANDROID_RB_FLAG_NO_SYNC       0x1  
  8. #define ANDROID_RB_FLAG_NO_REMOUNT_RO 0x2  
  9.   
  10. int android_reboot(int cmd, int flags, char *arg);  
分别代表三种不同的shutdown动作。

2. switch(cmd)如果进入ANDROID_RB_POWEROFF,则会执行reboot(RB_POWER_OFF),即shutdown的linux系统调用。reboot()定义在bionic/libc/bionic/reboot.c中。

  1. int reboot (int  mode)   
  2. {  
  3.     return __reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL );  
  4. }  
__reboot是通往linux kernel层的入口,执行__reboot就进入了linux kernel的关机过程。

六、linux kernel的shutdown过程

如前所述,__reboot()进入kernel的关机过程。进入kernel,首先执行SYSCALL_DEFINE4(),根据switch(cmd)语句选择的情况,执行不同的关机动作。

  1. SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,  
  2.         void __user *, arg)  
  3. {  
  4.     char buffer[256];  
  5.     int ret = 0;  
  6.   
  7.     /* We only trust the superuser with rebooting the system. */  
  8.     if (!capable(CAP_SYS_BOOT))  
  9.         return -EPERM;  
  10.   
  11.     /* For safety, we require "magic" arguments. */  
  12.     if (magic1 != LINUX_REBOOT_MAGIC1 ||  
  13.         (magic2 != LINUX_REBOOT_MAGIC2 &&  
  14.                     magic2 != LINUX_REBOOT_MAGIC2A &&  
  15.             magic2 != LINUX_REBOOT_MAGIC2B &&  
  16.                     magic2 != LINUX_REBOOT_MAGIC2C))  
  17.         return -EINVAL;  
  18.   
  19.     /* Instead of trying to make the power_off code look like 
  20.      * halt when pm_power_off is not set do it the easy way. 
  21.      */  
  22.     if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)  
  23.         cmd = LINUX_REBOOT_CMD_HALT;  
  24.   
  25.     lock_kernel();  
  26.     switch (cmd) {  
  27.     case LINUX_REBOOT_CMD_RESTART:  
  28.         kernel_restart(NULL);  
  29.         break;  
  30.   
  31.     case LINUX_REBOOT_CMD_CAD_ON:  
  32.         C_A_D = 1;  
  33.         break;  
  34.   
  35.     case LINUX_REBOOT_CMD_CAD_OFF:  
  36.         C_A_D = 0;  
  37.         break;  
  38.   
  39.     case LINUX_REBOOT_CMD_HALT:  
  40.         kernel_halt();  
  41.         unlock_kernel();  
  42.         do_exit(0);  
  43.         panic("cannot halt");  
  44.   
  45.     case LINUX_REBOOT_CMD_POWER_OFF:  
  46.         kernel_power_off();  
  47.         unlock_kernel();  
  48.         do_exit(0);  
  49.         break;  
  50.   
  51.     case LINUX_REBOOT_CMD_RESTART2:  
  52.         if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {  
  53.             unlock_kernel();  
  54.             return -EFAULT;  
  55.         }  
  56.         buffer[sizeof(buffer) - 1] = '\0';  
  57.   
  58.         kernel_restart(buffer);  
  59.         break;  
  60.   
  61. #ifdef CONFIG_KEXEC  
  62.     case LINUX_REBOOT_CMD_KEXEC:  
  63.         ret = kernel_kexec();  
  64.         break;  
  65. #endif  
  66.   
  67. #ifdef CONFIG_HIBERNATION  
  68.     case LINUX_REBOOT_CMD_SW_SUSPEND:  
  69.         ret = hibernate();  
  70.         break;  
  71. #endif  
  72.   
  73.     default:  
  74.         ret = -EINVAL;  
  75.         break;  
  76.     }  
  77.     unlock_kernel();  
  78.     return ret;  
  79. }  
如果cmd为LINUX_REBOOT_CMD_POWER_OFF,则进入kernel_power_off()。因为本文主要分析kernel_power_off(),其他情况类似,就不分析了。
  1. /** 
  2.  *  kernel_power_off - power_off the system 
  3.  * 
  4.  *  Shutdown everything and perform a clean system power_off. 
  5.  */  
  6. void kernel_power_off(void)  
  7. {  
  8.     kernel_shutdown_prepare(SYSTEM_POWER_OFF);  
  9.     if (pm_power_off_prepare)  
  10.         pm_power_off_prepare();  
  11.     disable_nonboot_cpus();  
  12.     sysdev_shutdown();  
  13.     printk(KERN_EMERG "Power down.\n");  
  14.     machine_power_off();  
  15. }  
1. kernel_shutdown_prepare(),这个函数中首先会用一个链表的操作block notifier,关于链表的操作可以自己去研究。

然后更新system_state,最后执行device_shutdown()去关闭所有的devices。

  1. static void kernel_shutdown_prepare(enum system_states state)  
  2. {  
  3.     blocking_notifier_call_chain(&reboot_notifier_list,  
  4.         (state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL);  
  5.     system_state = state;  
  6.     device_shutdown();  
  7. }  
2. disable_nonboot_cpus(),这一步骤和系统suspend时调用的disable_nonboot_cpus()是一样的,即关掉nonboot的cpu。

3. sysdev_shutdown(),系统设备的shutdown。

4. machine_power_off(),这是一个平台相关的关机指针,执行最后的关机动作。在include/kernel/reboot.h中声明此函数为外部的,针对不同的平台,就会编译不同的machine_power_off()函数。

对应找到arch/arm/kernel/process.c的machine_power_off()。

  1. void machine_power_off(void)  
  2. {  
  3.     if (pm_power_off)  
  4.         pm_power_off();  
  5. }  
如果pm_power_off非空,继续执行pm_power_off()进入PMIC执行硬件的power off。

拿at91sam9260举例,在这里定义了pm_power_off的具体事例。pm_power_off = at91sam9260_poweroff;

  1. static void at91sam9260_poweroff(void)  
  2. {  
  3.     at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);  
  4. }  
这就是power off最后执行的平台相关的操作,接下来的操作就交给硬件了。

分析到这里,两篇Android关机流程分析到此结束。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值