Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57a740ec authored by Steven Laver's avatar Steven Laver
Browse files

Allow properties to be derived from partition-specific properties during init

If not present, ro.product.[brand|device|manufacturer|model|name] and
ro.build.fingerprint will be resolved during init from
partition-specific properties.

Test: booted system image, verified properties
Test: booted recovery image, verified properties
Bug: 120123525
Change-Id: I7fe2793a7d9eb65645d92ceb408f1f050acf9a81
parent bec58544
Loading
Loading
Loading
Loading
+108 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@

using namespace std::literals;

using android::base::GetProperty;
using android::base::ReadFileToString;
using android::base::Split;
using android::base::StartsWith;
@@ -728,6 +729,110 @@ void load_persist_props(void) {
    property_set("ro.persistent_properties.ready", "true");
}

// If the ro.product.[brand|device|manufacturer|model|name] properties have not been explicitly
// set, derive them from ro.product.${partition}.* properties
static void property_initialize_ro_product_props() {
    const char* RO_PRODUCT_PROPS_PREFIX = "ro.product.";
    const char* RO_PRODUCT_PROPS[] = {
            "brand", "device", "manufacturer", "model", "name",
    };
    const char* RO_PRODUCT_PROPS_ALLOWED_SOURCES[] = {
            "odm", "product", "product_services", "system", "vendor",
    };
    const char* RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER =
            "product,product_services,odm,vendor,system";
    const std::string EMPTY = "";

    std::string ro_product_props_source_order =
            GetProperty("ro.product.property_source_order", EMPTY);

    if (!ro_product_props_source_order.empty()) {
        // Verify that all specified sources are valid
        for (const auto& source : Split(ro_product_props_source_order, ",")) {
            // Verify that the specified source is valid
            bool is_allowed_source = false;
            for (const auto& allowed_source : RO_PRODUCT_PROPS_ALLOWED_SOURCES) {
                if (source == allowed_source) {
                    is_allowed_source = true;
                    break;
                }
            }
            if (!is_allowed_source) {
                LOG(ERROR) << "Found unexpected source in ro.product.property_source_order; "
                              "using the default property source order";
                ro_product_props_source_order = RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER;
                break;
            }
        }
    } else {
        ro_product_props_source_order = RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER;
    }

    for (const auto& ro_product_prop : RO_PRODUCT_PROPS) {
        std::string base_prop(RO_PRODUCT_PROPS_PREFIX);
        base_prop += ro_product_prop;

        std::string base_prop_val = GetProperty(base_prop, EMPTY);
        if (!base_prop_val.empty()) {
            continue;
        }

        for (const auto& source : Split(ro_product_props_source_order, ",")) {
            std::string target_prop(RO_PRODUCT_PROPS_PREFIX);
            target_prop += source;
            target_prop += '.';
            target_prop += ro_product_prop;

            std::string target_prop_val = GetProperty(target_prop, EMPTY);
            if (!target_prop_val.empty()) {
                LOG(INFO) << "Setting product property " << base_prop << " to '" << target_prop_val
                          << "' (from " << target_prop << ")";
                std::string error;
                uint32_t res = PropertySet(base_prop, target_prop_val, &error);
                if (res != PROP_SUCCESS) {
                    LOG(ERROR) << "Error setting product property " << base_prop << ": err=" << res
                               << " (" << error << ")";
                }
                break;
            }
        }
    }
}

// If the ro.build.fingerprint property has not been set, derive it from constituent pieces
static void property_derive_build_fingerprint() {
    std::string build_fingerprint = GetProperty("ro.build.fingerprint", "");
    if (!build_fingerprint.empty()) {
        return;
    }

    const std::string UNKNOWN = "unknown";
    build_fingerprint = GetProperty("ro.product.brand", UNKNOWN);
    build_fingerprint += '/';
    build_fingerprint += GetProperty("ro.product.name", UNKNOWN);
    build_fingerprint += '/';
    build_fingerprint += GetProperty("ro.product.device", UNKNOWN);
    build_fingerprint += ':';
    build_fingerprint += GetProperty("ro.build.version.release", UNKNOWN);
    build_fingerprint += '/';
    build_fingerprint += GetProperty("ro.build.id", UNKNOWN);
    build_fingerprint += '/';
    build_fingerprint += GetProperty("ro.build.version.incremental", UNKNOWN);
    build_fingerprint += ':';
    build_fingerprint += GetProperty("ro.build.type", UNKNOWN);
    build_fingerprint += '/';
    build_fingerprint += GetProperty("ro.build.tags", UNKNOWN);

    LOG(INFO) << "Setting property 'ro.build.fingerprint' to '" << build_fingerprint << "'";

    std::string error;
    uint32_t res = PropertySet("ro.build.fingerprint", build_fingerprint, &error);
    if (res != PROP_SUCCESS) {
        LOG(ERROR) << "Error setting property 'ro.build.fingerprint': err=" << res << " (" << error
                   << ")";
    }
}

void property_load_boot_defaults() {
    // TODO(b/117892318): merge prop.default and build.prop files into one
    // TODO(b/122864654): read the prop files from all partitions and then
@@ -749,6 +854,9 @@ void property_load_boot_defaults() {
    load_properties_from_file("/vendor/build.prop", NULL);
    load_properties_from_file("/factory/factory.prop", "ro.*");

    property_initialize_ro_product_props();
    property_derive_build_fingerprint();

    update_sys_usb_config();
}