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 0x2
 
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中。


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_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;
}
如果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关机流程分析到此结束。
 

猜你喜欢

转载自blog.csdn.net/sdkdlwk/article/details/89392604