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系统开发提供了更大的灵活性,使我们能够更容易地适应不同的硬件和配置需求。

相关文章
|
20天前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
45 15
Android 系统缓存扫描与清理方法分析
|
12天前
|
算法 JavaScript Android开发
|
14天前
|
安全 搜索推荐 Android开发
揭秘安卓与iOS系统的差异:技术深度对比
【10月更文挑战第27天】 本文深入探讨了安卓(Android)与iOS两大移动操作系统的技术特点和用户体验差异。通过对比两者的系统架构、应用生态、用户界面、安全性等方面,揭示了为何这两种系统能够在市场中各占一席之地,并为用户提供不同的选择。文章旨在为读者提供一个全面的视角,理解两种系统的优势与局限,从而更好地根据自己的需求做出选择。
36 2
|
22天前
|
安全 搜索推荐 Android开发
揭秘iOS与Android系统的差异:一场技术与哲学的较量
在当今数字化时代,智能手机操作系统的选择成为了用户个性化表达和技术偏好的重要标志。iOS和Android,作为市场上两大主流操作系统,它们之间的竞争不仅仅是技术的比拼,更是设计理念、用户体验和生态系统构建的全面较量。本文将深入探讨iOS与Android在系统架构、应用生态、用户界面及安全性等方面的本质区别,揭示这两种系统背后的哲学思想和市场策略,帮助读者更全面地理解两者的优劣,从而做出更适合自己的选择。
|
13天前
|
安全 搜索推荐 程序员
深入探索Android系统的碎片化问题及其解决方案
在移动操作系统的世界中,Android以其开放性和灵活性赢得了广泛的市场份额。然而,这种开放性也带来了一个众所周知的问题——系统碎片化。本文旨在探讨Android系统碎片化的现状、成因以及可能的解决方案,为开发者和用户提供一种全新的视角来理解这一现象。通过分析不同版本的Android系统分布、硬件多样性以及更新机制的影响,我们提出了一系列针对性的策略,旨在减少碎片化带来的影响,提升用户体验。
|
13天前
|
安全 Android开发 iOS开发
深入探索iOS与Android系统的差异性及优化策略
在当今数字化时代,移动操作系统的竞争尤为激烈,其中iOS和Android作为市场上的两大巨头,各自拥有庞大的用户基础和独特的技术特点。本文旨在通过对比分析iOS与Android的核心差异,探讨各自的优势与局限,并提出针对性的优化策略,以期为用户提供更优质的使用体验和为开发者提供有价值的参考。
|
15天前
|
安全 Android开发 iOS开发
安卓系统与iOS系统的比较####
【10月更文挑战第26天】 本文将深入探讨安卓(Android)和iOS这两大主流移动操作系统的各自特点、优势与不足。通过对比分析,帮助读者更好地理解两者在用户体验、应用生态、系统安全等方面的差异,从而为消费者在选择智能手机时提供参考依据。无论你是技术爱好者还是普通用户,这篇文章都将为你揭示两大系统背后的故事和技术细节。 ####
36 0
|
API Android开发
组件化系列(一)Android动态权限
历史版本权限组件使用的是AndPermission,长期无人维护,历史代码臃肿,不便拓展,考虑使用PermissionsDispatcher,但是PermissionsDispatcher APT插件会影响编译效率,easypermissions侵入性太强,会影响整个工程,RxPermissions 貌似是最佳选择,但是RxPermissions需要高度自定义符合自己项目特色的UI,所以干脆自己写个权限组件好了,希望大家喜欢
97 0
|
Android开发
Android动态权限(兼容6.0以下和魅族手机方案)
这里以照相机权限为例说明问题。实际开发过程中遇到了不少的坑。
|
XML Android开发 数据格式