RK3568安卓11系统深度定制:从设备标识到时区配置的实战手册
每次接手一个新的RK3568项目,总免不了要重新折腾一遍设备信息的配置。明明上次在某个mk文件里改过设备名,这次却要花半小时翻遍整个device/rockchip目录;好不容易编译完系统,烧录到设备上发现时区还是不对,又得回头去查那几行晦涩的属性配置。这种重复性的查找和试错,消耗的不仅是时间,更是开发者的耐心。对于嵌入式开发者和系统定制工程师而言,RK3568这类主流平台的高效定制,是项目能否快速交付的关键。本文将抛开零散的笔记,为你系统性地梳理在Android 11系统上,如何精准、稳定地修改设备名、型号、时区等核心标识,并深入剖析背后原理与常见陷阱,让你下次定制时,能像调用一个熟悉的API那样得心应手。
1. 理解Android系统属性与构建系统
在动手修改任何配置之前,我们需要先搞清楚这些配置信息在Android系统中是如何被定义、传递和最终生效的。Android的构建系统(基于Soong和Blueprint)和属性系统(ro.*、persist.*等)是这一切的基石。
1.1 构建变量:PRODUCT_* 的来龙去脉
当你打开device/rockchip/rk356x/rk3568_r/rk3568_r.mk这类设备配置文件时,会看到一系列以PRODUCT_开头的变量。这些变量并非直接写入系统,而是构建过程中的“原材料”。
PRODUCT_NAME: 通常指代产品的内部代号,用于构建系统内部区分不同的产品变体。它不一定直接暴露给最终用户。PRODUCT_DEVICE: 指代设备的硬件设计名称,与TARGET_DEVICE紧密相关,用于定位设备专属的硬件配置、内核配置和驱动。PRODUCT_MODEL: 这是最终呈现给用户的、市场化的设备型号名称。例如,“小米12 Pro”、“Galaxy S23”等。这是我们最常需要修改的字段。
在构建过程中,这些PRODUCT_*变量会被处理,并最终写入到系统的只读属性(ro.product.*)中。你可以通过adb shell getprop命令来验证:
adb shell getprop ro.product.model adb shell getprop ro.product.name adb shell getprop ro.product.device理解这个映射关系至关重要。直接修改rk3568_r.mk中的PRODUCT_MODEL,本质上是在源头修改了ro.product.model属性的生成值。
1.2 系统属性:持久化的配置存储
Android系统使用属性服务来管理大量键值对配置。其中有两类属性与我们相关:
- 只读属性 (
ro.*):在系统启动早期(init阶段)被设置,之后不可更改。设备标识信息(如型号、制造商)通常属于此类。 - 持久化属性 (
persist.*):即使重启也会被保存的属性。时区、语言等用户偏好设置通常通过这类属性控制。
修改时区和语言,实际上就是设置persist.sys.timezone和persist.sys.language等属性。在rk3568_r.mk中通过PRODUCT_PROPERTY_OVERRIDES添加的配置,会在系统构建时被编译到/system/build.prop或/vendor/build.prop中,从而在首次开机时生效。
注意:
PRODUCT_PROPERTY_OVERRIDES的优先级很高,但它并不是设置属性的唯一途径。系统服务(如SettingsProvider)或init.rc脚本也可能在运行时覆盖这些初始值,这就是为什么有时“修改了但没效果”。
2. 设备标识信息定制实战
现在,我们进入实操环节。假设我们要将一台基于RK3568的开发板,定制为名为“SmartDisplay”的产品,型号为“SD-100”。
2.1 定位与修改核心配置文件
通常,设备专属的构建配置位于device/<制造商>/<平台>/<产品>/目录下。对于RK3568参考设计,路径正如输入信息所示。
步骤一:找到并编辑产品定义文件
打开你的AOSP源码目录,定位到设备配置文件:
cd /path/to/your/android11/source vim device/rockchip/rk356x/rk3568_r/rk3568_r.mk步骤二:修改设备标识变量
在文件中找到定义产品标识的部分,并进行修改。通常它们会集中出现:
# 原内容可能类似: PRODUCT_NAME := rk3568_r PRODUCT_DEVICE := rk3568_r PRODUCT_MODEL := RK3568 Development Board # 修改为: PRODUCT_NAME := smart_display PRODUCT_DEVICE := rk3568_r # 硬件设计名,若非必要可不改 PRODUCT_MODEL := SD-100 PRODUCT_BRAND := YourCompany # 品牌信息,如有需要也可在此添加 PRODUCT_MANUFACTURER := YourCompany # 制造商信息步骤三:处理可能的重叠定义
有时,相同的属性可能在多个地方被定义。一个更稳健的做法是使用搜索来确认:
# 在整个device目录下搜索PRODUCT_MODEL的定义 grep -r "PRODUCT_MODEL.*:=" device/rockchip/ # 在vendor目录下也可能存在覆盖 grep -r "ro.product.model" vendor/rockchip/如果发现多处定义,需要判断优先级。一般来说,AndroidProducts.mk中指定的产品mk文件具有最高优先级,其次是device.mk等通用文件。
2.2 验证修改结果
修改完成后,不能仅凭编译通过就认为万事大吉。
编译与烧录:
source build/envsetup.sh lunch rk3568_r-eng # 选择你的目标产品 make -j$(nproc) # 使用Rockchip工具或fastboot将系统烧录到设备开机后验证:设备启动后,通过ADB连接并检查属性:
adb shell getprop | grep ro.product预期输出应包含:
[ro.product.model]: [SD-100] [ro.product.name]: [smart_display] [ro.product.device]: [rk3568_r] [ro.product.brand]: [YourCompany] [ro.product.manufacturer]: [YourCompany]此外,你还需要检查系统设置中的应用是否识别了新名称:
- 进入“设置” -> “关于手机/平板电脑”,查看“型号”一栏。
- 第三方应用(如CPU-Z)读取的设备信息。
3. 时区、语言与区域设置深度配置
设备标识是“我是谁”,而时区语言则是“我在哪,说什么话”。这部分配置更复杂,因为它涉及系统服务、资源文件和多处配置的协同。
3.1 修改默认时区与语言
在rk3568_r.mk中添加PRODUCT_PROPERTY_OVERRIDES是最直接的方法:
PRODUCT_PROPERTY_OVERRIDES += \ persist.sys.language=zh \ persist.sys.country=CN \ persist.sys.timezone=Asia/Shanghai \ ro.product.locale=zh-CN关键参数解析:
| 属性键 | 含义 | 示例值 | 备注 |
|---|---|---|---|
persist.sys.language | 系统默认语言(ISO 639-1) | zh,en | 必须与res/values-<语言代码>/目录对应 |
persist.sys.country | 系统默认国家/地区(ISO 3166-1) | CN,US | 影响日期、数字格式等 |
persist.sys.timezone | 系统默认时区(IANA时区数据库) | Asia/Shanghai,America/New_York | 必须存在于system/timezone/数据中 |
ro.product.locale | 产品默认区域设置 | zh-CN,en-US | 语言和地区的组合,影响应用行为 |
3.2 为什么修改了“没效果”?—— 配置覆盖与优先级
很多开发者遇到过在mk文件里加了配置,但首次开机仍是英文或默认时区。这通常是由于配置被后续流程覆盖了。
原因分析与排查路径:
SettingsProvider的默认值:Android框架中的SettingsProvider会在数据库初始化时,如果检测到相关表项为空,会写入一套硬编码的默认值。这些默认值可能来自frameworks/base/packages/SettingsProvider/res/values/defaults.xml。init进程或rc脚本的覆盖:某些平台厂商的初始化脚本可能会在启动后期(late-init阶段)主动设置这些属性。- OTA或恢复出厂设置的影响:
persist.*属性虽然持久化,但在某些特定的恢复或升级场景下可能被重置。
解决方案:
- 方案A:确保在最早阶段设置。检查
device/rockchip/rk356x/目录下的init.rc或init.<硬件>.rc文件,看是否有设置时区/语言的命令。理论上,在PRODUCT_PROPERTY_OVERRIDES中设置应该足够早。 - 方案B:修改
SettingsProvider的默认值(不推荐)。这需要修改AOSP框架层代码,兼容性和维护性差。 - 方案C:使用
overlay覆盖默认资源。这是更优雅和标准的方式。在设备的overlay目录下创建文件:
添加或覆盖以下配置:device/rockchip/rk356x/rk3568_r/overlay/frameworks/base/core/res/res/values/config.xml
这种方式修改的是系统服务的默认配置,优先级通常高于属性设置,且更符合Android的设计规范。<!-- 设置默认时区 --> <string name="config_default_time_zone" translatable="false">Asia/Shanghai</string> <!-- 设置默认语言列表,第一个为默认 --> <string-array name="config_supportedLocales"> <item>zh-CN</item> <item>en-US</item> </string-array>
3.3 验证时区与语言生效
编译烧录后,首次开机无需进入设置向导,直接检查:
# 检查时区 adb shell date # 输出应显示CST(中国标准时间)或其他你设置的时区时间 # 检查语言和区域属性 adb shell getprop persist.sys.locale # 输出应为类似 "zh-CN" # 检查系统设置数据库(需要root权限或eng/userdebug版本) adb shell settings get system system_locales4. 进阶:固件版本号与构建信息的定制
除了基础标识,产品化过程中还需要定制版本号、构建ID等信息,用于OTA升级和问题追踪。
4.1 修改版本信息
版本信息通常在build/make/core/version_defaults.mk或设备特定的mk文件中被定义。我们可以在产品mk文件中覆盖它们:
# 在 rk3568_r.mk 中添加 PRODUCT_BUILD_PROP_OVERRIDES += \ BUILD_DISPLAY_ID="SD-100-$(shell date +%Y%m%d).$(BUILD_NUMBER)" \ ro.build.display.id=$(BUILD_DISPLAY_ID) # 设置自定义的版本号 ROCKCHIP_BUILD_VERSION := 1.0.0 PRODUCT_PROPERTY_OVERRIDES += \ ro.build.version.incremental=$(ROCKCHIP_BUILD_VERSION) \ ro.build.version.release=11 \ ro.build.version.sdk=304.2 生成唯一的构建指纹
构建指纹(ro.build.fingerprint)是用于唯一标识一个系统构建的字符串,格式通常为:$(BRAND)/$(PRODUCT)/$(DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER):$(TARGET_BUILD_TYPE)/$(BUILD_FINGERPRINT)。 为了避免与Google的认证冲突(如果涉及GMS),需要生成自己的指纹。这通常在build/make/tools/buildinfo.sh脚本中处理,但更安全的方式是在产品配置中设置:
# 定义构建指纹的各个部分 PRODUCT_BUILD_FINGERPRINT := "YourCompany/SD-100/rk3568_r:11/RQ3A.211001.001/$(shell date +%Y%m%d%H%M):userdebug/test-keys"5. 常见问题排查与解决思路
在实际操作中,你可能会遇到以下问题。这里提供一套排查思路。
问题一:修改PRODUCT_MODEL后,系统设置中显示的型号未变。
- 可能原因:系统设置应用(Settings)缓存了旧信息,或者读取的是另一个属性(如
ro.product.system.model)。 - 排查步骤:
- 使用
adb shell getprop | grep model查看所有与model相关的属性,确认ro.product.model是否已正确修改。 - 检查是否有其他属性被设置,例如
ro.product.system.model(对于system-as-root分区)或ro.product.vendor.model。 - 清除系统设置应用的数据:
adb shell pm clear com.android.settings,然后重启。 - 检查是否在
system.prop或vendor.prop中有硬编码的覆盖。
- 使用
问题二:首次开机,时区仍然是“GMT”或“UTC”,而不是Asia/Shanghai。
- 可能原因:时区数据库文件缺失,或
persist.sys.timezone属性在启动过程中被覆盖。 - 排查步骤:
- 确认时区值正确:
adb shell getprop persist.sys.timezone。 - 检查时区文件是否存在:
adb shell ls /system/usr/share/zoneinfo/Asia/Shanghai。 - 查看系统日志,搜索
timezone相关日志:adb logcat | grep -i timezone,看是否有错误信息。 - 尝试在
init.rc中添加一个确保执行的命令:setprop persist.sys.timezone Asia/Shanghai,并放在on early-init或on init阶段。
- 确认时区值正确:
问题三:默认语言设置为中文,但开机后部分系统界面仍是英文。
- 可能原因:语言资源包不完整,或者区域设置(Locale)未正确组合。
- 排查步骤:
- 确认语言代码正确。简体中文是
zh,但完整的区域设置是zh-CN。 - 检查设备是否编译了对应的语言资源。在
build/make/core/main.mk中,PRODUCT_LOCALES变量定义了哪些语言会被包含在镜像中。确保你的产品mk文件包含了zh_CN。 - 使用
adb shell dumpsys locale命令查看当前系统完整的区域设置信息。
- 确认语言代码正确。简体中文是
问题四:修改了多个mk文件,但不知道最终哪个生效。
- 解决方案:利用构建系统的调试功能。在编译时,查看生成的
build.prop文件,它位于out/target/product/rk3568_r/system/build.prop(或vendor/build.prop)。这个文件是所有属性配置最终合并的结果。用文本编辑器打开它,搜索你关心的属性(如ro.product.model),就能看到最终被赋予的值是什么,从而反推是哪个配置起了作用。
定制过程就像解一个层层嵌套的谜题,每一处修改都可能被更高优先级的规则覆盖。最有效的方法,永远是修改后立即验证——不是验证编译是否成功,而是验证烧录到设备上的实际属性值。养成在rk3568_r.mk文件旁放一个README.customization.md的习惯,记录下每次有效的修改路径和关键属性值,这比任何技术文章都更能提升你未来的开发效率。毕竟,最好的工具,是你为自己量身打造的那一套工作流。