本文基于Android 5.1版本SDK。

客户需求:自定义sn,统一规则编号。

第一部分:背景知识

Android的sn由SystemProperties.get("ro.serialno", "");而来。

ro.serialno并不像常见的其他属性一样存在于build.prop等prop文件中,而是在/system/core/init/init.c里由ro.boot.serialno转换而来,转换的函数是export_kernel_boot_props,源码如下:

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);elseproperty_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");elseproperty_set("ro.factorytest", "0");
}

重点看for循环部分,可以明显看到,ro.serialno的值是由ro.boot.serialno而来。

export_kernel_boot_props在process_kernel_cmdline中调用

static void process_kernel_cmdline(void)
{/* don't expose the raw commandline to nonpriv processes */chmod("/proc/cmdline", 0440);/* first pass does the common stuff, and finds if we are in qemu.* second pass is only necessary for qemu to export all kernel params* as props.*/import_kernel_cmdline(0, import_kernel_nv);if (qemu[0])import_kernel_cmdline(1, import_kernel_nv);/* now propogate the info given on command line to internal variables* used by init as well as the current required properties*/export_kernel_boot_props();
}

process_kernel_cmdline中还调用了import_kernel_nv,import_kernel_nv的方法体如下:

static void import_kernel_nv(char *name, int for_emulator)
{char *value = strchr(name, '=');int name_len = strlen(name);if (value == 0) return;*value++ = 0;if (name_len == 0) return;if (for_emulator) {/* in the emulator, export any kernel option with the* ro.kernel. prefix */char buff[PROP_NAME_MAX];int len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name );if (len < (int)sizeof(buff))property_set( buff, value );return;}if (!strcmp(name,"qemu")) {strlcpy(qemu, value, sizeof(qemu));} else if (!strncmp(name, "androidboot.", 12) && name_len > 12) {const char *boot_prop_name = name + 12;char prop[PROP_NAME_MAX];int cnt;cnt = snprintf(prop, sizeof(prop), "ro.boot.%s", boot_prop_name);if (cnt < PROP_NAME_MAX)property_set(prop, value);}
}

代码很清晰,从cmdline中将androidboot.*的属性拿出来设置给了ro.boot.*的属性。在终端里面执行cat /proc/cmdline,如下:

shell@msm8909:/ # cat /proc/cmdline
sched_enable_hmp=1 console=ttyHSL0,115200,n8 androidboot.console=ttyHSL0 androidboot.hardware=qcom user_debug=31 msm_rtb.filter=0x3F ehci-hcd.pa
rk=3 androidboot.bootdevice=7824900.sdhci lpm_levels.sleep_disabled=1 earlyprintk androidboot.selinux=permissive androidboot.emmc=true androidbo
ot.serialno=c336a56 androidboot.baseband=msm mdss_mdp3.panel=1:dsi:0:qcom,mdss_dsi_jd9366_800p_video:1:none

可以看到androidboot.serialno=c336a56,说明sn是在bootloader中获得,通过cmdline传递到内核。

至此,sn的传递和赋值流程基本梳理清楚。

第二部分:实现重新对sn赋值

自定义sn的思路是在系统的persist分区(persist分区的内容不会因为恢复出厂设置而被清除,重新刷机会清除)里面预设一个文本文件,系统启动之后,从app里面向这个文本文件写入按规则编号的sn,然后重启系统,init进程重新读取文本里面的值来设置ro.serialno和ro.boot.serialno。

首先在init.c里面修改,屏蔽掉ro.boot.serialno赋值的逻辑,然后在export_kernel_boot_props的for循环里面,i=0的时候是对ro.serialno进行赋值,在这里增加需要的代码:fopen打开文本获取到文件指针fp->fgets从fp读取一行内容到buf里面->调用property_set将buf的值设置给ro.serialno和ro.boot.serialno。

修改之后,重新编译boot.img。

make bootimage -j8

然后重刷boot:

adb reboot bootloader
fastboot flash boot boot.img
fastboot reboot

重启进系统,dmesg | grep init查看打印,尴尬的问题来了,fp是null。看来在init进程启动的时候,persist分区还没挂载,因此访问不到persist分区。在init.c里读取文本这个路子行不通。

换个思路

init.rc里面on boot之后,以root权限执行脚本,脚本中读取文本内容,然后将内容设置给ro.serialno和ro.boot.serialno。

脚本内容和init.rc增加的代码都很简单:

on bootstart setsnservice setsn /sbin/busybox sh /system/etc/setsn.sh serviceoneshotdisableduser rootgroup root**********************************
**********************************
#!/system/bin/shSN_FILE_PATH=/persist/sn.txt
SN_FILE_VALUE=`cat $SN_FILE_PATH`
SN_BACKUP_VALUE=`getprop persist.serialno.backup`if [[ "$SN_FILE_VALUE" != "" ]];
thenSN=$SN_FILE_VALUE
elseSN=$SN_BACKUP_VALUE
fisetprop ro.serialno $SN
setprop ro.boot.serialno $SN

此方法实测有效。

PS:
在调试过程中发现,init进程中对ro.serialno和ro.boot.serialno只能设值一次,如果不屏蔽init.c里面设值的逻辑,那么执行脚本将不会改变sn。

Android rom开发:自定义序列号ro.serialno相关推荐

  1. Android ROM开发(三)——精简官方ROM并且内置ROOT权限,开启Romer之路

    Android ROM开发(三)--精简官方ROM并且内置ROOT权限,开启Romer之路 相信ROM的相关信息大家通过前几篇的学习都是有所了解了,这里就不在一一提示了,这里我们下载一个官方包,我们还 ...

  2. Android ROM开发(一)——Windows下Cygwin和Android_Kitchen厨房的安装

    Android ROM开发(一)--Windows下Cygwin和Android_Kitchen厨房的安装 很久没有碰到ROM开发了,在很久很久以前也是从ROM起步的,无奈还是一脚踏上了Android ...

  3. 怎么测试android rom,Android ROM开发(6) RUU刷机测试1

    Andrew Huang 转载请注明作者及网址 在刷机时,经常会听到几个名,OTA,RUU. RUU 是Rom Update Utility 的缩写,RUU是官方发布的的完整的升级包.HTC发包通常的 ...

  4. android+rom+bootloader+flash,Android ROM开发(4) bootloader 三种启动模式

    Andrew Huang 转载请注明作者及网址 HTC手机中用的bootloader称为HBoot,不知道是不是HTC Bootloader 之意,从官网的源码看这个bootloader不象是u-bo ...

  5. android go rom下载地址,一步一步学Android ROM开发(一)——修改现有ROM资源文件-Go语言中文社区...

    一,准备工作 1.一台开发手机. 我推荐最好用G7,也是就HTC Desire那款(是不是有些广告嫌疑...),这台机各种ROM都很全,资料也多些,很容易刷到root,android版本也是最新的2. ...

  6. android rom 工作,Android ROM开发(4) bootloader 三种启动模式

    Andrew Huang 转载请注明作者及网址 HTC手机中用的bootloader称为HBoot,不知道是不是HTC Bootloader 之意,从官网的源码看这个bootloader不象是u-bo ...

  7. 一步一步学Android ROM开发(一)——修改现有ROM资源文件

    一,准备工作 1.一台开发手机. 我推荐最好用G7,也是就HTC Desire那款(是不是有些广告嫌疑...),这台机各种ROM都很全,资料也多些,很容易刷到root,android版本也是最新的2. ...

  8. android 开发刷rom,Android ROM开发(7) TF卡(金卡)自引导刷机

    Andrew Huang 转载请注明作者及网址 官方的RUU对于刷机要求严格.必须使用PC通过USB在线刷机,检查也比较严格.如果想刷CID不一致的ROM,或者降版刷机.用这个方法不行. 因此如果你的 ...

  9. Android rom开发:mtk android9.0 开放预置app权限

    适用于mtk android 9.0 diff --git a/frameworks/base/services/core/java/com/android/server/pm/permission/ ...

最新文章

  1. 关于SUID、SGID、Sticky
  2. gophp解释器_对比平台--Go和PHP之间的区别
  3. oracle 11g 卸载  客户端卸载
  4. 使用Python编写简易定时器
  5. Mysql 数据库锁机制浅析
  6. NIK插件-托马斯教程1-color efex pro 4
  7. 如何说孩子才会听,怎么听孩子才肯说
  8. 重庆市企业数据名录爬取采集-信用中国(重庆)
  9. C++幕后故事(七)--一个对象的生与死
  10. Springboot整合JdbcTemplate实现分页查询
  11. 用百度地图进行搜索周边的建筑,医院,餐厅,学校等。
  12. android 执行bin文件是什么意思,将可执行文件复制到android中的system / bin
  13. 《我要飞,永远都不会累 》---伤感留言
  14. 模板匹配理论的优缺点,模板匹配和神经网络
  15. snmp在win10上安装使用
  16. javaweb mysql 连接池 c3p0 配置_javaWeb_JDBC_c3p0数据库连接池
  17. 为PDF扫描文件添加书签
  18. 使用ARCHPR明文攻击爆破压缩包
  19. Material Design icons图标的使用,npm下载及react+typescript引用方式import
  20. 用公司邮箱发错邮件怎么弄?邮件可以撤回吗?

热门文章

  1. 数据库周刊36丨2020年8月数据库排行;云厂商腾讯云增速第一;OceanBase集群安装;Oracle RAC调整网卡MTU值;不改代码解决sql性能问题;Mysql索引研究;TiDB电子书……
  2. Oracle Clob类型和Blob类型之间的转换
  3. 计算机硬件加网络俱乐部,[硬件维护]免费为大家提供电脑硬件方面的咨询,24小时在线服务!...
  4. TCP实现可靠传输的实现
  5. ByteBuffer使用揭秘
  6. 数据结构基本操作总结(C语言版)---链表、栈与队列
  7. 一分钟搞明白什么是维度,什么是事实,什么是度量,什么是粒度
  8. 响应式微服务_低风险整体式微服务演进第三部分
  9. 已知一个靶点,如何获取旗下相关的生物实验,临床试验,以及上市药物数据.
  10. Sql语句--日期函数用法