RK3568 Android系统客制化动态替换ro任意属性

简介: RK3568 Android系统客制化动态替换ro任意属性

在Android系统开发中,经常会遇到需要动态修改系统属性的情况。尤其是对于那些标记为只读的属性,修改它们可能会比较困难。本文将以RK3568 Android11为例,介绍如何动态替换任意的ro属性以及在此过程中遇到的问题和解决方案。

需求背景

在Android系统中,属性经常用于配置信息,例如设备型号、硬件版本等。有时,为了适应不同的硬件或软件需求,我们可能需要在系统运行时动态修改这些属性,而不是重新编译整个系统。

方案思路

我的解决方案是在系统启动时,加载一个自定义的属性文件,该文件中的属性将覆盖系统中已存在的属性。这样,我们就可以在不修改系统源代码的情况下,动态地修改任意属性。

Android 11的Property加载流程

  1. 启动init进程:Android系统启动时,首先启动的是init进程。这是系统的第一个进程,负责初始化系统环境和启动其他系统服务。
  2. 加载默认属性init进程首先加载/system/etc/prop.default文件中的属性。这些属性通常包括硬件和系统的基本配置。
if (!load_properties_from_file("/system/etc/prop.default", nullptr, &properties)) {
    // Try recovery path
    if (!load_properties_from_file("/prop.default", nullptr, &properties)) {
        // Try legacy path
        load_properties_from_file("/default.prop", nullptr, &properties);
    }
}
  1. 加载其他属性文件:除了默认属性文件,init进程还会加载其他多个属性文件,如/system/build.prop/vendor/build.prop等。这些文件中的属性可以覆盖默认属性文件中的属性。
load_properties_from_file("/system/build.prop", nullptr, &properties);
load_properties_from_file("/vendor/build.prop", nullptr, &properties);
  1. 加载设备特定属性:为了支持多种硬件配置,Android 11引入了设备特定的属性文件,如/odm/build.prop/product/build.prop等。这些文件中的属性可以根据具体的硬件配置进行定制。
load_properties_from_file("/odm/build.prop", nullptr, &properties);
load_properties_from_file("/product/build.prop", nullptr, &properties);
  1. 属性覆盖:在加载属性时,后加载的属性会覆盖先加载的属性。这意味着,如果多个属性文件中都定义了同一个属性,那么最后加载的文件中的属性值将被使用。

为什么自定义属性可以覆盖默认属性?

这是因为Android的属性加载机制是基于后加载的属性覆盖先加载的属性的原则设计的。这种设计允许开发者和OEM厂商在不修改系统源代码的情况下,通过添加或修改属性文件来定制系统配置。

例如,我们可以在/product/customize.prop中定义一个属性ro.product.system.model=rk3568_custom。由于这个文件是在其他属性文件之后加载的,所以这个属性会覆盖在之前的文件中定义的同名属性。

实现步骤:

  1. 选择自定义属性文件的位置:考虑到系统的启动顺序和分区挂载情况,我们选择将自定义属性文件放在/product分区,因为这个分区在系统的早期启动阶段就已经被挂载,所以init进程可以在启动时访问它。我们将自定义属性文件命名为customize.prop
  2. 修改属性加载代码:在system/core/init/property_service.cpp文件中,找到PropertyLoadBootDefaults函数。在该函数中,我们在加载其他属性文件之后,添加了加载我们的自定义属性文件的代码。
void PropertyLoadBootDefaults() {
    // TODO(b/117892318): merge prop.default and build.prop files into one
    // We read the properties and their values into a map, in order to always allow properties
    // loaded in the later property files to override the properties in loaded in the earlier
    // property files, regardless of if they are "ro." properties or not.
    std::map<std::string, std::string> properties;
    if (!load_properties_from_file("/system/etc/prop.default", nullptr, &properties)) {
        // Try recovery path
        if (!load_properties_from_file("/prop.default", nullptr, &properties)) {
            // Try legacy path
            load_properties_from_file("/default.prop", nullptr, &properties);
        }
    }
    load_properties_from_file("/system/build.prop", nullptr, &properties);
    load_properties_from_file("/system_ext/build.prop", nullptr, &properties);
    load_properties_from_file("/vendor/default.prop", nullptr, &properties);
    load_properties_from_file("/vendor/build.prop", nullptr, &properties);
    if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_Q__) {
        load_properties_from_file("/odm/etc/build.prop", nullptr, &properties);
    } else {
        load_properties_from_file("/odm/default.prop", nullptr, &properties);
        load_properties_from_file("/odm/build.prop", nullptr, &properties);
    }
    load_properties_from_file("/product/build.prop", nullptr, &properties);
    load_properties_from_file("/factory/factory.prop", "ro.*", &properties);
    if (access(kDebugRamdiskProp, R_OK) == 0) {
        LOG(INFO) << "Loading " << kDebugRamdiskProp;
        load_properties_from_file(kDebugRamdiskProp, nullptr, &properties);
    }
    // 加载自定义的prop文件 start
    //const char* customPropPath = "/mnt/private/customize.prop";
    const char* customPropPath = "/product/customize.prop";
    if (access(customPropPath, R_OK) == 0) {
        LOG(INFO) << "[custom_prop] Loading " << customPropPath;
        load_properties_from_file(customPropPath, nullptr, &properties);
    } else {
        LOG(INFO) << customPropPath << " not found, skipping.[custom_prop]";
    }
    // 加载自定义的prop文件  end
    for (const auto& [name, value] : properties) {
        std::string error;
        if (PropertySet(name, value, &error) != PROP_SUCCESS) {
            LOG(ERROR) << "Could not set '" << name << "' to '" << value
                       << "' while loading .prop files" << error;
        }
    }
    property_initialize_ro_product_props();
    property_derive_build_fingerprint();
    update_sys_usb_config();
}

如何测试:

我们在customize.prop文件中设置了ro.product.system.model=rk3568_custom。启动系统后,我们使用getprop ro.product.system.model命令,确实得到了rk3568_custom,这证明我们的修改是成功的。

  1. 属性验证:使用getprop命令验证属性是否已被正确加载。
  2. 系统功能测试:确保修改后的系统可以正常启动,并运行各种应用程序。
  3. 日志检查:通过logcat命令,检查系统日志,确保没有与属性加载相关的错误或警告。

遇到的问题:

  1. 分区挂载问题:最初,我们尝试将自定义属性文件放在/mnt/private分区。但在系统启动早期,该分区尚未挂载,导致init进程无法访问。因此,我们选择了/product分区。
  2. 属性覆盖问题:由于属性加载的顺序,后加载的属性会覆盖先加载的属性。因此,我们确保自定义属性文件是在其他属性文件之后加载的。

结论

通过上述方法,我们成功地实现了在RK3568 Android12系统中动态替换任意的ro属性。这为Android系统开发提供了更大的灵活性,使我们能够更容易地适应不同的硬件和配置需求。

相关文章
|
4天前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
28 15
Android 系统缓存扫描与清理方法分析
|
6天前
|
安全 搜索推荐 Android开发
深入探索安卓与iOS系统的差异及其对用户体验的影响
在当今的智能手机市场中,安卓和iOS是两大主流操作系统。它们各自拥有独特的特性和优势,为用户提供了不同的使用体验。本文将深入探讨安卓与iOS系统之间的主要差异,包括它们的设计理念、用户界面、应用生态以及安全性等方面,并分析这些差异如何影响用户的使用体验。
|
5天前
|
安全 搜索推荐 Android开发
揭秘iOS与Android系统的差异:一场技术与哲学的较量
在当今数字化时代,智能手机操作系统的选择成为了用户个性化表达和技术偏好的重要标志。iOS和Android,作为市场上两大主流操作系统,它们之间的竞争不仅仅是技术的比拼,更是设计理念、用户体验和生态系统构建的全面较量。本文将深入探讨iOS与Android在系统架构、应用生态、用户界面及安全性等方面的本质区别,揭示这两种系统背后的哲学思想和市场策略,帮助读者更全面地理解两者的优劣,从而做出更适合自己的选择。
|
23天前
|
IDE Android开发 iOS开发
探索安卓与iOS系统的技术差异:开发者的视角
本文深入分析了安卓(Android)与苹果iOS两大移动操作系统在技术架构、开发环境、用户体验和市场策略方面的主要差异。通过对比这两种系统的不同特点,旨在为移动应用开发者提供有价值的见解,帮助他们在不同平台上做出更明智的开发决策。
|
23天前
|
Ubuntu Shell API
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
|
2月前
|
监控 Android开发 iOS开发
深入探索安卓与iOS的系统架构差异:理解两大移动平台的技术根基在移动技术日新月异的今天,安卓和iOS作为市场上最为流行的两个操作系统,各自拥有独特的技术特性和庞大的用户基础。本文将深入探讨这两个平台的系统架构差异,揭示它们如何支撑起各自的生态系统,并影响着全球数亿用户的使用体验。
本文通过对比分析安卓和iOS的系统架构,揭示了这两个平台在设计理念、安全性、用户体验和技术生态上的根本区别。不同于常规的技术综述,本文以深入浅出的方式,带领读者理解这些差异是如何影响应用开发、用户选择和市场趋势的。通过梳理历史脉络和未来展望,本文旨在为开发者、用户以及行业分析师提供有价值的见解,帮助大家更好地把握移动技术发展的脉络。
66 6
|
2月前
|
Dart 开发工具 Android开发
在 Android 系统上搭建 Flutter 环境的具体步骤是什么?
在 Android 系统上搭建 Flutter 环境的具体步骤是什么?
|
XML Android开发 数据格式
Android中利用shape属性自定义设置Button按钮
Android中利用shape属性自定义设置Button按钮
231 0
|
Android开发
Android 获取include标签中的控件属性并设置事件
Android 获取include标签中的控件属性并设置事件
183 0

相关实验场景

更多