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 有值)。部分代码示例如下:

    cpp 复制代码
    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

    rc 复制代码
    on property:sys.serialno=*
        setprop ro.serialno ${sys.serialno}
5. 应用层获取

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

java 复制代码
// 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. 检查内核命令行

    bash 复制代码
    adb shell cat /proc/cmdline

    查找 androidboot.serialno= 条目 。

  2. 查看系统属性

    bash 复制代码
    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 的实现。如果你在具体的代码跟踪过程中遇到问题,比如在某个环节找不到预期的代码,欢迎随时提出。

相关推荐
nono牛2 小时前
MTK平台详解`adb devices`输出的序列号组成
android·linux·adb·智能手机
wanhengidc6 小时前
云手机与云服务器之间的关系
服务器·游戏·智能手机·云计算·区块链
wanhengidc19 小时前
云手机搬砖 尤弥尔传奇自动化操作
运维·服务器·arm开发·安全·智能手机·自动化
mit6.82419 小时前
[手机AI开发sdk] Aid_code IDE | PC浏览器同步访问
ide·人工智能·智能手机
毕设源码-朱学姐1 天前
【开题答辩全过程】以 二手咸鱼手机交易平台为例,包含答辩的问题和答案
智能手机
工具人55552 天前
adb disable-verity
数据库·数据仓库·adb
双翌视觉2 天前
机器视觉在手机摄像头模组点胶中的应用
数码相机·智能手机
wanhengidc2 天前
云手机存在的意义是什么
运维·服务器·arm开发·安全·智能手机
任风雨2 天前
15.5.手机设备信息
智能手机·获取手机信息