最近遇到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] 基于 Linux 命令行构建 Android 应用(三):构建流程
  2. android启动过程及各个镜像间的关系
  3. Android 4.0中按键的处理流程
  4. Android 数据Parcel序列化过程源码分析
  5. Android 9.0 系统启动流程
  6. Android编译系统详解(三)——编译流程详解
  7. Android 如何自定义一个简单的组件和自定义的点击事件(中级)
  8. Android View measure流程详解
  9. Android 自定义View (入门 篇) 的使用

随机推荐

  1. Android(安卓)蓝牙调色灯/zigbee调色灯学
  2. Android下基于XML的 Graphics
  3. Android的init过程详解(一)
  4. Android: NDK编程入门笔记
  5. android 线程,服务,活动
  6. Android(安卓)UI学习1:控件和基本事件的
  7. Android的多媒体框架OpenCore(PacketVideo
  8. AndroidTouch事件的传递、拦截、消费分析
  9. Android开发入门之路(初学者必读)
  10. 用C#开发了一个Android(安卓)浏览器APP