Android设备硬件序列号(SN、串号)的序列号是怎么获取的,以全志A64平台来一步步跟代码分析:
在设置-》关于设备-》状态信息中,显示的信息来自android.os.Build.SERIAL,代码位于: frameworks/base/core/java/android/os/Build.java: public static final String SERIAL = getString(" ro.serialno ");
frameworks/base/core/java/android/os/Build.java: private static String getString(String property) { return SystemProperties.get(property, UNKNOWN); }
由此可见是通过key为"ro.serialno"的SystemProperties 获取到串号的,接下来看一下ro.serialno是如何赋值的: 先看init代码system/core/init/init.c int main(int argc, char **argv) { ....... property_init();
get_hardware_name(hardware, &revision);
process_kernel_cmdline (); ......
原来是从cmdline中获取的,import_kernel_cmdline把u-boot传给kernel的cmdline进行提取,然后回调import_kernel_nv进行处理 static void process_kernel_cmdline (void) { ...... import_kernel_cmdline (0, import_kernel_nv); if (qemu[0]) import_kernel_cmdline(1, import_kernel_nv); ...... export_kernel_boot_props (); }
import_kernel_nv将cmdline中androidboot.开头的全部转化为"ro.boot.%s"并设置到properties中,例如“androidboot.serialno”为“ro.boot.serialno”: static void import_kernel_nv(char *name, int for_emulator) { ...... } 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); } }
再来看export_kernel_boot_props函数,将ro.boot.serialno赋值给ro.serialno了 static void export_kernel_boot_props(void) { ...... } 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); }
再来看看u-boot是如何获取串号的: u-boot-2014.07/common/cmd_boota.c中有对androidboot.serialno的赋值: void update_bootargs(void) { ...... //serial info str = getenv(" sunxi_serial "); sprintf(tmpbuf," androidboot.serialno =%s",str); ...... }
其值来自于u-boot env sunxi_serial,sunxi_serial又是由DTS中的/soc/serial_feature定义的,由sys_config.fex转换的dts内容,sn.txt又是放在private分区中。 [serial_feature] sn_filename = "sn.txt"
int sunxi_set_serial_num(void) { char serial[128] = {0}; if( get_serial_num_from_file (serial)) { get_serial_num_from_chipid(serial); } printf("serial is: %s\n",serial); if(setenv(" sunxi_serial ", serial)) { printf("error:set variable [sunxi_serial] fail\n"); } return 0; }
就用private分区存放sn.txt这种方式来验证一下: busybox mkfs.vfat /dev/block/by-name/private busybox mount -t vfat /dev/block/by-name/private /private/ echo "XXXX2017030219360001">/private/sn.txt sync
重启系统,发现串号变成了我们sn.txt里面的内容,重新刷机验证序列号没有被清掉。
另外根据android兼容说明,串号必须满足以下要求(主要是 6~20长度的ASSCII编码字符A hardware serial number, which MUST be available and unique across devices with the same MODEL and MANUFACTURER. The value of this field MUST be encodable as 7-bit ASCII and match the regular expression “^([a-zA-Z0-9]{6,20})$”.

更多相关文章

  1. Android Studio中同步代码时报:Received status code 400 from se
  2. android java代码覆盖率
  3. Android对话框风格的Activity代码
  4. Android 删除指定文件代码
  5. Android摄像头视频帧数据测试代码
  6. 代码实现Layout android:layout_alignParentRight
  7. Android 震动 和 停止 代码
  8. android ril 代码逻辑分析

随机推荐

  1. Android(安卓)通过 AccessibilityService
  2. android 完美解决getview position多次调
  3. chromium for android Browser进程结构分
  4. NDK/Jni底层获取root权限的四种思路
  5. Android(安卓)4.2 Input 流程分析
  6. TabHost、TabWidgt、Tabcontent之间的关
  7. android 自定义dialog 带动画的
  8. 修改状态栏(StatusBar)图标(icon)(定制自
  9. Android实现双模(CDMA/GSM)手机短信监听
  10. ViewFlipper 左右滑动效果