在android5.1的init进程中加入读取手机序列码

在and4.4上之前在init进程中读取amt/sn.txt中的内容,设置到"ro.serialno"的系统属性中。而Settings会去读取这个属性的值,从而将手机的序列码显示出来。

    if (!is_charger) {
        action_for_each_trigger("early-fs", action_add_queue_tail);
        action_for_each_trigger("fs", action_add_queue_tail);
        action_for_each_trigger("post-fs", action_add_queue_tail);
        action_for_each_trigger("post-fs-data", action_add_queue_tail);
    }

    /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
     * wasn't ready immediately after wait_for_coldboot_done
     */
    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");

    queue_builtin_action(property_service_init_action, "property_service_init");
    queue_builtin_action(signal_init_action, "signal_init");
    queue_builtin_action(check_startup_action, "check_startup");
    queue_builtin_action(set_usb_serial_action, "set_usb_serial_action");    

set_usb_serial_action函数就是读取sn.txt的内容,如果没有这个文件再从/amt/nvram_amt_data.bin读取,这里就不再详细展开这个函数。

直接看代码吧:

static int set_usb_serial_action(int nargs,char **args) {
    FILE *fp;
    char serial_no[LINE_SIZE] = {0};
    int len = 0;
    bool isSNExist = true;

    fp = fopen(SN_FILE, "r");
    if (fp == NULL) {
        isSNExist = false;
        ERROR("file %s is not exist in AMT\n", SN_FILE);
        fp = fopen(NVRAM_AMT_DATA_FILE, "r");
        if (fp == NULL) {
            property_set("ro.serialno", "");
            ERROR("both %s and %s is not exist in AMT\n", SN_FILE, NVRAM_AMT_DATA_FILE);
            goto fail_exit;
        }
        int result = fseek(fp, 0x560, SEEK_SET);
        if (result) {
            property_set("ro.serialno","");
            ERROR("seek file %s error", NVRAM_AMT_DATA_FILE);
            goto fail_exit;
        }
    }

    if (fgets(serial_no, LINE_SIZE, fp) == NULL) {
        ERROR("read file error");
        property_set("ro.serialno","");
        goto fail_exit;
    }

    for (len = 0; len < LINE_SIZE; len++) {
        if(serial_no[len] == 0)
            break;
    }

    if (len == 0) {
        property_set("ro.serialno","0123456789ABCDEF");
        goto fail_exit;
    }

    property_set("ro.serialno", serial_no);
    fclose(fp);
    if (!isSNExist) {
        fp = fopen(SN_FILE, "w");
        if (fp) {
            fwrite(serial_no, sizeof(char), len, fp);
            fclose(fp);
            chown(SN_FILE, AID_ROOT, AID_RADIO);
            chmod(SN_FILE, S_IRUSR | S_IWUSR);
        }
    }
    return 0;
fail_exit:
    if (fp)
        fclose(fp);
    return -1;
}

然后把这个函数移植到5.1,同样放在执行队列的最后,确没有成功。log显示读取文件失败。

先是怀疑5.1上开启了selinux,于是在init.te中加入了对/amt目录的读取权限,但还是不行,将selinux的CR回退结果还是一样。于是就排除了selinux的问题。


排序selinux的问题后,基本上确定是amt分区还没有加载的原因。

于是先去搜4.1的init.rc,将amt分区挂载是在fs触发器中,在4.4的init是将fs这个触发器单独放在执行列表中,而我们的函数放在其后面,所以是没有问题的。

fs触发器的内容如下,其中就有挂载amt分区

on fs
    # mount partitions
    mount_all /fstab.leadcoreinnopower
    # enable swap
    swapon_all /fstab.leadcoreinnopower
    write /proc/sys/vm/page-cluster 0
    # If no amt file, to prevent the failure of mount_all
    mount ext4 /dev/block/platform/comip-mmc.1/by-name/amt /amt wait rw
    copy /amt/vbatt /proc/driver/comip_battery
    setprop ro.crypto.fuse_sdcard true

然而5.1上是将fs这个触发器放在:

on late-init
    trigger early-fs
    trigger fs
    trigger post-fs
    trigger post-fs-data
因此,在代码里放进执行队列的只是late-init,执行到late-init后再把fs等再加入执行队列。而这一步骤是在解析执行队列的时候,所以我们在之前加入队列,是肯定在fs之前了,也就是在amt分区还没有挂载的时候就去读取其中的文件,所以就出错了。

    if (is_charger) {
        action_for_each_trigger("charger", action_add_queue_tail);
    } else {
        action_for_each_trigger("late-init", action_add_queue_tail);
    }
解决的方法,是在解析到fs这个触发器的时候,再把我们这个函数加入执行队列中,这样就把这个问题解决了:

void execute_one_command(void)
{
    int ret, i;
    char cmd_str[256] = "";

    if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) {
        cur_action = action_remove_queue_head();
        cur_command = NULL;
        if (!cur_action)
            return;
        INFO("processing action %p (%s)\n", cur_action, cur_action->name);
        if (!strcmp(cur_action->name, "fs")) {
            queue_builtin_action(set_usb_serial_action, "set_usb_serial_action");// 解析到fs后,再把我们的函数加入到执行队列尾
        }
        cur_command = get_first_command(cur_action);
    } else {
        cur_command = get_next_command(cur_action, cur_command);
    }








你可能感兴趣的:(在android5.1的init进程中加入读取手机序列码)