项目需要,需要写入ro.serialno属性。借鉴了网上的文档,现把这个知识点做个备忘小结。
1.原理:ro.serialno是init从bootcmdline读取androidboot.serialno,设置成系统属性ro.boot.serialno和ro.serialno。bootcmdline是从mboot中android_image_get_kernel设置的。
2.代码相关具体位置:
a.mboot中 cmd_bootm.c android_image_get_kernel将需要设置为serialno属性的环境变量,以“androidboot.serialno=xxxxx”的形式设置到cmdline中。注意在开始这么设置的时候,ro.boot.serialno是固定值,这里传的参数无法写入,原因是这个是ro属性的变量,在刚开始时,有一个初始化值,这个初始化值需要清空掉:
system/core/init/init.cpp:
static void process_kernel_dt() {
static const char android_dir[] = "/proc/device-tree/firmware/android";
...
while ((dp = readdir(dir.get())) != NULL) {
if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible") || !strcmp(dp->d_name, "name")) {
continue;
}
file_name = android::base::StringPrintf("%s/%s", android_dir, dp->d_name);
android::base::ReadFileToString(file_name, &dt_file);
std::replace(dt_file.begin(), dt_file.end(), ',', '.');
std::string property_name = android::base::StringPrintf("ro.boot.%s", dp->d_name);
property_set(property_name.c_str(), dt_file.c_str());
}
}
b.android系统从cmdline读取key value值转为系统属性。ro.boot.serialno这个属性是通过字符串拼接形成的,所以在源码中是搜索不到的。
cat /proc/cmdline vmalloc=512M console=ttyS0 androidboot.hardware=fbiboard androidboot.console=ttyS0 board.ap_has_alsa=0 init=/init mtdparts=fbixxnand:0x00002000@0x00002000(uboot),0x00002000@0x00004000(misc),0x00008000@0x00006000(resource),0x00008000@0x0000e000(kernel),0x00010000@0x00016000(boot),0x00010000@0x00026000(recovery),0x0001a000@0x00036000(backup),0x00040000@0x00050000(cache),0x00002000@0x00090000(kpanic),0x00100000@0x00092000(system),0x00002000@0x00192000(metadata),0x00600000@0x00194000(userdata),0x00020000@0x00794000(radical_update),-@0x007B4000(user) storagemedia=emmc androidboot.serialno=1234567890 androidboot.mode=emmc
system/core/init/init.cpp:
static void import_kernel_nv(const std::string& key, const std::string& value, bool for_emulator) {
if (key.empty()) return;
if (for_emulator) {
// In the emulator, export any kernel option with the "ro.kernel." prefix.
property_set(android::base::StringPrintf("ro.kernel.%s", key.c_str()).c_str(), value.c_str());
return;
}
if (key == "qemu") {
strlcpy(qemu, value.c_str(), sizeof(qemu));
} else if (android::base::StartsWith(key, "androidboot.")) {
property_set(android::base::StringPrintf("ro.boot.%s", key.c_str() + 12).c_str(),
value.c_str());
NOTICE("lucky key:[%s]--value[%s].\n",key.c_str(),value.c_str());
}
}
c.ro.boot.serialno怎么变为ro.serialno的呢?
static void export_kernel_boot_props() {
struct {
const char *src_prop;
const char *dst_prop;
const char *default_value;
} 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", },
{ "ro.boot.hardware", "ro.hardware", "unknown", },
{ "ro.boot.revision", "ro.revision", "0", },
};
for (size_t i = 0; i < ARRAY_SIZE(prop_map); i++) {
std::string value = property_get(prop_map[i].src_prop);
property_set(prop_map[i].dst_prop, (!value.empty()) ? value.c_str() : prop_map[i].default_value);
}
}
3.验证:
#getprop|grep serial
[ro.boot.serialno]: [123456789]
[ro.serialno]: [123456789]