adb devices`ro.boot.serialno` 的实现

🔍 ro.boot.serialno 属性传递链

ro.boot.serialno 的传递主要经过以下阶段,你可以循着这个路径在代码中跟踪:

Bootloader阶段
Kernel内核参数
Android Init进程
导入内核参数
属性系统初始化
属性映射
ro.serialno属性
设备特定服务
设置sys.serialno
触发属性变更
1. Bootloader阶段

Bootloader(如U-Boot)负责获取或定义初始序列号

  • 在一些平台(如Rockchip),U-Boot可能从特定存储位置(如IDBLOCK_SN偏移地址)读取序列号,然后将其设置到环境变量 fbt_sn#,再传递到 androidboot.serialno
  • 在高通平台,代码(如 update_cmdline 函数)会将 usb_sn_cmdline(即 “androidboot.serialno=”)与 sn_buf(序列号值)拼接至内核命令行 。
  • 序列号也可能由制造商烧录工具写入设备闪存的独立分区(如 sn.txt 文件),Bootloader再从中读取 。
2. Kernel内核参数
  • Bootloader将序列号作为 androidboot.serialno 参数附加到内核命令行。
  • 系统启动后,你可通过 cat /proc/cmdline 查看所有内核参数,其中应包含 androidboot.serialno=你设备的序列号
3. Android Init进程

Android系统初始化时,init 进程负责解析内核命令行并设置初始属性

  • 导入内核参数:在 system/core/init/init.cppmain() 函数中,会调用 process_kernel_cmdline() 函数 。该函数通过 import_kernel_cmdline 函数解析 /proc/cmdline,并回调 import_kernel_nv 函数来提取 androidboot.serialno 参数,然后将其设置到 ro.boot.serialno 系统属性
  • 属性系统初始化与映射:属性系统初始化后,init 进程会调用 export_kernel_boot_props() 函数。此函数包含一个属性映射表,将 ro.boot.serialno值映射到 ro.serialno 属性(如果 ro.boot.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", "" }, // 映射序列号
            // ... 其他属性映射
        };
        for (size_t i = 0; i < arraysize(prop_map); i++) {
            std::string value = GetProperty(prop_map[i].src_prop, "");
            property_set(prop_map[i].dst_prop, (!value.empty()) ? value : prop_map[i].default_value);
        }
    }
    
    此映射关系也在其他代码分析中得到确认 。
4. 属性映射与触发设置(备选路径)
  • 在某些情况下(如RK3368平台),若未通过内核命令行设置,序列号可能通过设备特定服务(如 drmservice)设置。该服务可能从ID块读取或根据Wi-Fi MAC地址等生成序列号,然后设置 sys.serialno 属性。init 进程的 .rc 脚本(如 init.rk30board.rc)可监听 sys.serialno 的变化,并据此设置 ro.serialno
    on property:sys.serialno=*
        setprop ro.serialno ${sys.serialno}
    
5. 应用层获取

应用层通过 android.os.Build.SERIAL 获取的序列号,最终来源于 ro.serialno 系统属性 。

// frameworks/base/core/java/android/os/Build.java
public static final String SERIAL = getString("ro.serialno");

🔬 代码跟踪与调试方法

关键代码文件
  • Bootloader (U-Boot):查找设置 androidboot.serialno 的命令行参数代码,通常在涉及序列号初始化或命令行构建的文件中(如 update_cmdline 函数 )。
  • Android Init 进程
    • system/core/init/init.cpp:关注 main() 函数,特别是 process_kernel_cmdline()export_kernel_boot_props() 的调用 。
    • system/core/init/property_service.cpp:包含属性设置相关逻辑。
  • 系统属性bionic/libc/include/sys/_system_properties.h 等文件包含系统属性API。
实用调试命令
  1. 检查内核命令行

    adb shell cat /proc/cmdline
    

    查找 androidboot.serialno= 条目 。

  2. 查看系统属性

    adb shell getprop | grep serialno
    

    重点关注 ro.boot.serialnoro.serialno 的值 。

  3. 查看系统属性设置调用栈(需系统权限或DEBUG版本):

    • property_set 函数(或在Android 8.0及更高版本中的相应函数)添加日志或设置断点。
    • 使用 adb logcat 查看 init 进程的详细日志输出(可能需要DEBUG版本)。
MTK平台的补充说明

在MTK平台(如Android R),ro.boot.serialno 同样从Uboot传递 。关键映射过程在 export_kernel_boot_props 中完成。MTK的 Settings 应用和 DeviceIdentifiersPolicyService 会读取 ro.serialnoro.boot.serialno

💎 核心步骤总结

跟踪 ro.boot.serialno 的实现,关键在于理解其传递链:

  1. 起始:序列号源于Bootloader(从存储或环境变量获取,或由工具写入)。
  2. 传递:通过内核命令行参数 androidboot.serialno 传递给内核 。
  3. 转换:Android init 进程解析该参数,将其设置为 ro.boot.serialno 属性,进而映射到 ro.serialno
  4. 应用:应用层通过 android.os.Build.SERIAL(即 ro.serialno)读取 。

希望这份详细的代码跟踪指南能帮助你深入理解 ro.boot.serialno 的实现。如果你在具体的代码跟踪过程中遇到问题,比如在某个环节找不到预期的代码,欢迎随时提出。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值