android 关机充电 充电动画 从入门到精通

android手机关机充电的过程就像一个我们看到的一样,插上充电接口->手机启动->屏幕进入log画面->再进入充电动画界面。
稍微有点开发经验的就可以大致了解到它的启动经历了从bootloader->kernal->充电动画应用。
所以我们可以先分析下在bootloader的状态获取。
APP_START(aboot)
    .init = aboot_init,

在aboot_init 中可以就是bootloader的app了,它几乎实现了所有的最低层的逻辑,所以电源插上后,没有任何按键触发的或者没有相应的处理,一般会通过从flash或mmc启动内核。

boot_linux_from_mmc();
boot_linux_from_flash();

同理大家应该了解bootloader引导内核启动有一种通过命令行的传参的方式来告知内核一段信息,这个机制就不细说了,毕竟bootloader干了太多的事情,有将内核启动,有留下了遗言,实在辛苦。

void boot_linux(void *kernel, unsigned *tags,
        const char *cmdline, unsigned machtype,
        void *ramdisk, unsigned ramdisk_size)

上面的函数就是最后的晚餐开始。

update_cmdline((const char*)cmdline);

通过对cmdline 的最后的处理,

static const char *emmc_cmdline = " androidboot.emmc=true";
static const char *usb_sn_cmdline = " androidboot.serialno=";
static const char *efuse_cmdline = " androidboot.efuse=";
static const char *androidboot_mode = " androidboot.mode=";
static const char *display_cmdline = " mdss_mdp.panel=";
static const char *loglevel         = " quiet";
static const char *battchg_pause = " androidboot.mode=charger";
static const char *auth_kernel = " androidboot.authorized_kernel=true";
static const char *secondary_gpt_enable = " gpt";

static const char *baseband_apq     = " androidboot.baseband=apq";
static const char *baseband_msm     = " androidboot.baseband=msm";
static const char *baseband_csfb    = " androidboot.baseband=csfb";
static const char *baseband_svlte2a = " androidboot.baseband=svlte2a";
static const char *baseband_mdm     = " androidboot.baseband=mdm";
static const char *baseband_sglte   = " androidboot.baseband=sglte";
static const char *baseband_dsda    = " androidboot.baseband=dsda";
static const char *baseband_dsda2   = " androidboot.baseband=dsda2";
static const char *baseband_sglte2  = " androidboot.baseband=sglte2";

通过选择性的对cmdline的拼接,就把遗言写好了,然后就是内核态了。

static void export_kernel_boot_props(void)
{
    char tmp[PROP_VALUE_MAX];
    int ret;
    unsigned i;
    struct {
        const char *src_prop;
        const char *dest_prop;
        const char *def_val;
    } prop_map[] = {
        { "ro.boot.serialno", "ro.serialno", "", },
        { "ro.boot.mode", "ro.bootmode", "unknown", },
        { "ro.boot.baseband", "ro.baseband", "unknown", },
        { "ro.boot.bootloader", "ro.bootloader", "unknown", },
    };

    for (i = 0; i < ARRAY_SIZE(prop_map); i++) {
        ret = property_get(prop_map[i].src_prop, tmp);
        if (ret > 0)
            property_set(prop_map[i].dest_prop, tmp);
        else
            property_set(prop_map[i].dest_prop, prop_map[i].def_val);
    }

    ret = property_get("ro.boot.console", tmp);
    if (ret)
        strlcpy(console, tmp, sizeof(console));

    /* save a copy for init's usage during boot */
    property_get("ro.bootmode", tmp);
    strlcpy(bootmode, tmp, sizeof(bootmode));

    /* if this was given on kernel command line, override what we read
     * before (e.g. from /proc/cpuinfo), if anything */
    ret = property_get("ro.boot.hardware", tmp);
    if (ret)
        strlcpy(hardware, tmp, sizeof(hardware));
    property_set("ro.hardware", hardware);

    snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
    property_set("ro.revision", tmp);

    /* TODO: these are obsolete. We should delete them */
    if (!strcmp(bootmode,"factory"))
        property_set("ro.factorytest", "1");
    else if (!strcmp(bootmode,"factory2"))
        property_set("ro.factorytest", "2");
    else
        property_set("ro.factorytest", "0");
}

通过属性服务获取了bootmode。

        is_charger = !strcmp(bootmode, "charger");

判断成功后就可以启动的一个叫
service charger /charger
class charger
的服务,
这个应用 charger就是实现充电动画的应用。

static struct healthd_mode_ops android_ops = {
    .init = healthd_mode_android_init,
    .preparetowait = healthd_mode_android_preparetowait,
    .heartbeat = healthd_mode_nop_heartbeat,
    .battery_update = healthd_mode_android_battery_update,
};

static struct healthd_mode_ops charger_ops = {
    .init = healthd_mode_charger_init,
    .preparetowait = healthd_mode_charger_preparetowait,
    .heartbeat = healthd_mode_charger_heartbeat,
    .battery_update = healthd_mode_charger_battery_update,
};

static struct healthd_mode_ops recovery_ops = {
    .init = healthd_mode_nop_init,
    .preparetowait = healthd_mode_nop_preparetowait,
    .heartbeat = healthd_mode_nop_heartbeat,
    .battery_update = healthd_mode_nop_battery_update,
};

三种状态下的操作方式。

其中healthd_mode_charger_init就是初始化充电图片。

void healthd_mode_charger_init(struct healthd_config* config)
{
    int ret;
    int charging_enabled = 1;
    struct charger *charger = &charger_state;
    int i;
    int epollfd;

    dump_last_kmsg();

    LOGW("--------------- STARTING CHARGER MODE ---------------\n");

    if (mode == NORMAL) {
        /* check the charging is enabled or not */
        ret = read_file_int(CHARGING_ENABLED_PATH, &charging_enabled);
        if (!ret && !charging_enabled) {
            /* if charging is disabled, reboot and exit power off charging */
            LOGW("android charging is disabled, exit!\n");
            android_reboot(ANDROID_RB_RESTART, 0, 0);
        }
    }

    ret = ev_init(input_callback, charger);
    if (!ret) {
        epollfd = ev_get_epollfd();
        healthd_register_event(epollfd, charger_event_handler);
    }

    ret = res_create_display_surface("charger/battery_fail", &charger->surf_unknown);
    if (ret < 0) {
        LOGE("Cannot load battery_fail image\n");
        charger->surf_unknown = NULL;
    }

    charger->batt_anim = &battery_animation;

for (i = 0; i < charger->batt_anim->num_frames; i++) {
    struct frame *frame = &charger->batt_anim->frames[i];  
    //ret = res_create_surface(frame->name, &frame->surface);  
    ret = res_create_display_surface(frame->name, &frame->surface);  
    if (ret < 0) {  
        LOGE("Cannot load image %s\n", frame->name);  
        /* TODO: free the already allocated surfaces... */  
        charger->batt_anim->num_frames = 0;  
        charger->batt_anim->num_cycles = 1;  
        break;  
    }  
}

/*
    gr_surface* scale_frames;
    int scale_count;
    ret = res_create_multi_display_surface("charger/battery_scale", &scale_count, &scale_frames);
    if (ret < 0) {
        LOGE("Cannot load battery_scale image\n");
        charger->batt_anim->num_frames = 0;
        charger->batt_anim->num_cycles = 1;
    } else if (scale_count != charger->batt_anim->num_frames) {
        LOGE("battery_scale image has unexpected frame count (%d, expected %d)\n",
             scale_count, charger->batt_anim->num_frames);
        charger->batt_anim->num_frames = 0;
        charger->batt_anim->num_cycles = 1;
    } else {
        for (i = 0; i < charger->batt_anim->num_frames; i++) {
            charger->batt_anim->frames[i].surface = scale_frames[i];
        }
    }
*/
    ev_sync_key_state(set_key_callback, charger);

    charger->next_screen_transition = -1;
    charger->next_key_check = -1;
    charger->next_pwr_check = -1;
    healthd_config = config;
}

这块代码主要实现就是初始化一个

static int healthd_init() {
    epollfd = epoll_create(MAX_EPOLL_EVENTS);
    if (epollfd == -1) {
        KLOG_ERROR(LOG_TAG,
                   "epoll_create failed; errno=%d\n",
                   errno);
        return -1;
    }

    healthd_board_init(&healthd_config);
    healthd_mode_ops->init(&healthd_config);
    wakealarm_init();
    uevent_init();
    gBatteryMonitor = new BatteryMonitor();
    gBatteryMonitor->init(&healthd_config);
    return 0;
}

定时启动的函数。

static void healthd_mainloop(void) {
    while (1) {
        struct epoll_event events[eventct];
        int nevents;
        int timeout = awake_poll_interval;
        int mode_timeout;

        mode_timeout = healthd_mode_ops->preparetowait(); //刷图等动作
        if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout))
            timeout = mode_timeout;
        nevents = epoll_wait(epollfd, events, eventct, timeout);

        if (nevents == -1) {
            if (errno == EINTR)
                continue;
            KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n");
            break;
        }

        for (int n = 0; n < nevents; ++n) {
            if (events[n].data.ptr)
                (*(void (*)(int))events[n].data.ptr)(events[n].events);
        }

        if (!nevents)
            periodic_chores();

        healthd_mode_ops->heartbeat();
    }

    return;
}

你可能感兴趣的:(LINUX,android)