最近遇到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关机流程分析到此结束。



更多相关文章

  1. Android(安卓)Studio中使用adb shell查看数据库
  2. Android(安卓)Service生命周期及用法!
  3. Android:异步调用详解
  4. Android(安卓)Service生命周期及用法
  5. android 如何使用Wake Lock来节电?
  6. 在Android中使用Handler和Thread线程执行后台操作
  7. 在Android中使用Handler和Thread线程执行后台操作
  8. arm-marvell-linux-gnueabi 交叉编译c/c++程序,并移植到android
  9. android AOP实现之AspectJ

随机推荐

  1. Android屏幕属性应用
  2. MTK Android 编译命令
  3. Android 倒影实现算法
  4. Android(安卓)Service 启动流程
  5. android 浮窗
  6. R文件没有生成或报错
  7. Android SDK无法更新终极解决方式
  8. Android 读取XML的两种方法。
  9. Ubuntu 12.04 Desktop 版本编译 Android
  10. Android SQLite数据库解析并使用两种方法