Android(安卓)关机流程分析-----(2)JNI和kernel层
最近遇到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
static void nativeShutdown(JNIEnv *env, jclass clazz) { android_reboot(ANDROID_RB_POWEROFF, 0, 0);}static void nativeReboot(JNIEnv *env, jclass clazz, jstring reason) { if (reason == NULL) { android_reboot(ANDROID_RB_RESTART, 0, 0); } else { const char *chars = env->GetStringUTFChars(reason, NULL); android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars); env->ReleaseStringUTFChars(reason, chars); // In case it fails. } jniThrowIOException(env, errno);}// ----------------------------------------------------------------------------static JNINativeMethod gPowerManagerServiceMethods[] = { /* name, signature, funcPtr */ { "nativeInit", "()V", (void*) nativeInit }, { "nativeSetPowerState", "(ZZ)V", (void*) nativeSetPowerState }, { "nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V", (void*) nativeAcquireSuspendBlocker }, { "nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V", (void*) nativeReleaseSuspendBlocker }, { "nativeSetInteractive", "(Z)V", (void*) nativeSetInteractive }, { "nativeSetAutoSuspend", "(Z)V", (void*) nativeSetAutoSuspend }, { "nativeShutdown", "()V", (void*) nativeShutdown }, { "nativeReboot", "(Ljava/lang/String;)V", (void*) nativeReboot },};在JNI中,framework层中的nativeShutdown()还是被JNI成nativeShutdown(),然后进入android_reboot(ANDROID_RB_POWEROFF, 0, 0)。
android_reboot()在system/core/libcutils/Android_reboot.c中定义如下:
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: ret = reboot(RB_POWER_OFF); break; case ANDROID_RB_RESTART2: ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, arg); break; default: ret = -1; } return ret;}1. 参数cmd是命令行参数,在system/core/include/cutils/Android_reboot.h中定义如下:
/* Commands */#define ANDROID_RB_RESTART 0xDEAD0001#define ANDROID_RB_POWEROFF 0xDEAD0002#define ANDROID_RB_RESTART2 0xDEAD0003/* Flags */#define ANDROID_RB_FLAG_NO_SYNC 0x1#define ANDROID_RB_FLAG_NO_REMOUNT_RO 0x2int 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中。
int reboot (int mode) { return __reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL );}__reboot是通往linux kernel层的入口,执行__reboot就进入了linux kernel的关机过程。
六、linux kernel的shutdown过程
如前所述,__reboot()进入kernel的关机过程。进入kernel,首先执行SYSCALL_DEFINE4(),根据switch(cmd)语句选择的情况,执行不同的关机动作。
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,void __user *, arg){char buffer[256];int ret = 0;/* We only trust the superuser with rebooting the system. */if (!capable(CAP_SYS_BOOT))return -EPERM;/* For safety, we require "magic" arguments. */if (magic1 != LINUX_REBOOT_MAGIC1 || (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&magic2 != LINUX_REBOOT_MAGIC2B && magic2 != LINUX_REBOOT_MAGIC2C))return -EINVAL;/* Instead of trying to make the power_off code look like * halt when pm_power_off is not set do it the easy way. */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);panic("cannot halt");case LINUX_REBOOT_CMD_POWER_OFF:kernel_power_off();unlock_kernel();do_exit(0);break;case LINUX_REBOOT_CMD_RESTART2:if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {unlock_kernel();return -EFAULT;}buffer[sizeof(buffer) - 1] = '\0';kernel_restart(buffer);break;#ifdef CONFIG_KEXECcase LINUX_REBOOT_CMD_KEXEC:ret = kernel_kexec();break;#endif#ifdef CONFIG_HIBERNATIONcase LINUX_REBOOT_CMD_SW_SUSPEND:ret = hibernate();break;#endifdefault:ret = -EINVAL;break;}unlock_kernel();return ret;}如果cmd为LINUX_REBOOT_CMD_POWER_OFF,则进入kernel_power_off()。因为本文主要分析kernel_power_off(),其他情况类似,就不分析了。
/** *kernel_power_off - power_off the system * *Shutdown everything and perform a clean system power_off. */void kernel_power_off(void){kernel_shutdown_prepare(SYSTEM_POWER_OFF);if (pm_power_off_prepare)pm_power_off_prepare();disable_nonboot_cpus();sysdev_shutdown();printk(KERN_EMERG "Power down.\n");machine_power_off();}1. kernel_shutdown_prepare(),这个函数中首先会用一个链表的操作block notifier,关于链表的操作可以自己去研究。
然后更新system_state,最后执行device_shutdown()去关闭所有的devices。
static void kernel_shutdown_prepare(enum system_states state){blocking_notifier_call_chain(&reboot_notifier_list,(state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL);system_state = state;device_shutdown();}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()。
void machine_power_off(void){if (pm_power_off)pm_power_off();}如果pm_power_off非空,继续执行pm_power_off()进入PMIC执行硬件的power off。
拿at91sam9260举例,在这里定义了pm_power_off的具体事例。 pm_power_off = at91sam9260_poweroff;
static void at91sam9260_poweroff(void){at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);}这就是power off最后执行的平台相关的操作,接下来的操作就交给硬件了。
分析到这里,两篇Android关机流程分析到此结束。
更多相关文章
- Android(安卓)Studio中使用adb shell查看数据库
- Android(安卓)Service生命周期及用法!
- Android:异步调用详解
- Android(安卓)Service生命周期及用法
- android 如何使用Wake Lock来节电?
- 在Android中使用Handler和Thread线程执行后台操作
- 在Android中使用Handler和Thread线程执行后台操作
- arm-marvell-linux-gnueabi 交叉编译c/c++程序,并移植到android
- android AOP实现之AspectJ