转载地址: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
- 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 },
- };
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;
- }
- /* 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 0x2
- int android_reboot(int cmd, int flags, char *arg);
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 );
- }
六、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_KEXEC
- case LINUX_REBOOT_CMD_KEXEC:
- ret = kernel_kexec();
- break;
- #endif
- #ifdef CONFIG_HIBERNATION
- case LINUX_REBOOT_CMD_SW_SUSPEND:
- ret = hibernate();
- break;
- #endif
- default:
- ret = -EINVAL;
- break;
- }
- unlock_kernel();
- return ret;
- }
- /**
- * 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();
- }
然后更新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();
- }
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();
- }
拿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);
- }
分析到这里,两篇Android关机流程分析到此结束。