RK3568 Android system customized dynamic replacement of any ro attributes

In Android system development, we often encounter situations where system properties need to be dynamically modified. Especially for properties that are marked read-only, modifying them can be difficult. This article will take RK3568 Android11 ​​as an example to introduce how to dynamically replace arbitrary roattributes as well as the problems and solutions encountered in the process.

Demand background

In the Android system, properties are often used for configuration information, such as device model, hardware version, etc. Sometimes, in order to adapt to different hardware or software requirements, we may need to dynamically modify these properties while the system is running instead of recompiling the entire system.

Plan ideas

My solution is to load a custom properties file when the system starts. The properties in this file will overwrite the properties that already exist in the system. In this way, we can dynamically modify any attribute without modifying the system source code.

Property loading process of Android 11

  1. Start the init process : When the Android system starts, the process is started first init. This is the first process of the system and is responsible for initializing the system environment and starting other system services.

  2. Load default properties : initThe process first loads /system/etc/prop.defaultthe properties from the file. These properties typically include the hardware and basic configuration of the system.

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. Load other property files : In addition to the default property file, initthe process will also load multiple other property files, such as /system/build.prop, /vendor/build.propetc. Properties in these files can override properties in the default properties file.
load_properties_from_file("/system/build.prop", nullptr, &properties);
load_properties_from_file("/vendor/build.prop", nullptr, &properties);
  1. Loading device-specific properties : In order to support multiple hardware configurations, Android 11 introduces device-specific properties files, such as /odm/build.prop, /product/build.propetc. The properties in these files can be customized based on specific hardware configurations.
load_properties_from_file("/odm/build.prop", nullptr, &properties);
load_properties_from_file("/product/build.prop", nullptr, &properties);
  1. Property override : When loading properties, properties loaded later will overwrite properties loaded first. This means that if the same property is defined in multiple properties files, the property value from the last loaded file will be used.

Why can custom properties override default properties?

This is because Android's attribute loading mechanism is designed based on the principle that attributes loaded later overwrite attributes loaded first. This design allows developers and OEM manufacturers to customize the system configuration by adding or modifying property files without modifying the system source code.

For example, we can /product/customize.propdefine a property in ro.product.system.model=rk3568_custom. Since this file is loaded after other properties files, this property will overwrite the property with the same name defined in the previous file.

Implementation steps:

  1. Select the location of the custom properties file : Considering the system startup sequence and partition mounting, we choose to place the custom properties file in the /productpartition. Because this partition has been mounted in the early startup phase of the system, the initprocess can Access it on startup. We name our custom properties file customize.prop.

  2. Modify the attribute loading code : In system/core/init/property_service.cppthe file, find PropertyLoadBootDefaultsthe function. In this function, we added the code to load our custom properties file after loading the other properties files.

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();
}

How to test:

We customize.propset it in the file ro.product.system.model=rk3568_custom. After starting the system, we used getprop ro.product.system.modelthe command and indeed got it rk3568_custom, which proved that our modification was successful.

  1. Property verification : Use getpropthe command to verify that the property has been loaded correctly.

  2. System functional testing : Ensure that the modified system can start normally and run various applications.

  3. Log check : Use logcatthe command to check the system log to ensure there are no errors or warnings related to attribute loading.


Insert image description here

Problems encountered:

  1. Partition mounting issue : Initially, we tried placing custom properties files on /mnt/privatethe partition. However, in the early stages of system startup, the partition has not yet been mounted, making initthe process inaccessible. Therefore, we chose /productpartitioning.

  2. Property coverage problem : Due to the order in which properties are loaded, properties loaded later will overwrite properties loaded first. Therefore, we ensure that the custom properties file is loaded after other properties files.

in conclusion

Through the above method, we successfully realized the dynamic replacement of arbitrary roattributes in the RK3568 Android12 system. This provides greater flexibility for Android system development, allowing us to adapt to different hardware and configuration needs more easily.

Guess you like

Origin blog.csdn.net/SHH_1064994894/article/details/132477346