diff --git a/README.md b/README.md index 55becf26952c4198e62dfe9dcb0ef75c23b6df91..12827fa31656fb64c53cf310db05574697f2ee3b 100644 --- a/README.md +++ b/README.md @@ -493,3 +493,54 @@ PRODUCT_PACKAGES += \ su \ ``` + +##### 13. 自定义属性文件使用说明 + +若用户有需要在云手机预置属性,可新建device.prop文件,推送到路径/data/local/custom/下,重启手机系统后生效。 ++ 文件位置 +/data/local/custom/device.prop ++ 格式 +key=value键值对,如以下示例 +``` +customer.property.disable=false +customer.property.name=cloudphone +``` ++ 生效规则 +默认遵循AOSP原生属性配置规则,非ro属性用户配置值覆盖系统原生值,ro属性不可写。 +如需支持ro属性定制,可参考以下方式修改源码文件 + +aosp/system/core/init/property_service.cpp 修改PropertySet函数 +``` + prop_info* pi = (prop_info*)__system_property_find(name.c_str()); + if (pi != nullptr) { + // 注释以下代码,去除对ro属性的写入限制 + // ro.* properties are actually "write-once". + //if (StartsWith(name, "ro.")) { + // *error = "Read-only property was already set"; + // return {PROP_ERROR_READ_ONLY_PROPERTY}; + //} + + __system_property_update(pi, value.c_str(), valuelen); + } else { +``` + ++ AOSP原生属性设置API ro可写定制 +通过adb shell登入手机使用命令setprop设置属性,或第三方应用调用原生接口设置属性,默认AOSP原生规则ro属性不可写,若用户有需求支持ro可写,可参考以下方法修改源码: +aosp/system/core/libcutils/properties.cpp修改__system_property_set接口 +``` +int __system_property_set(const char* key, const char* value) { + if (key == nullptr || *key == '\0') return -1; + if (value == nullptr) value = ""; + + // 注释以下拦截ro属性修改的代码 + // bool read_only = !strncmp(key, "ro.", 3); + // if (read_only) { + // const auto [it, success] = g_properties.insert({key, value}); + // return success ? 0 : -1; + // } + + if (strlen(value) >= 92) return -1; + g_properties[key] = value; + return 0; +} +``` diff --git a/aosp/system/core/libcutils/properties.cpp b/aosp/system/core/libcutils/properties.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03f04961cd1ce005384a8366757d23371daa6fd2 --- /dev/null +++ b/aosp/system/core/libcutils/properties.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +int8_t property_get_bool(const char* key, int8_t default_value) { + if (!key) return default_value; + + int8_t result = default_value; + char buf[PROPERTY_VALUE_MAX] = {}; + + int len = property_get(key, buf, ""); + if (len == 1) { + char ch = buf[0]; + if (ch == '0' || ch == 'n') { + result = false; + } else if (ch == '1' || ch == 'y') { + result = true; + } + } else if (len > 1) { + if (!strcmp(buf, "no") || !strcmp(buf, "false") || !strcmp(buf, "off")) { + result = false; + } else if (!strcmp(buf, "yes") || !strcmp(buf, "true") || !strcmp(buf, "on")) { + result = true; + } + } + + return result; +} + +template +static T property_get_int(const char* key, T default_value) { + if (!key) return default_value; + + char value[PROPERTY_VALUE_MAX] = {}; + if (property_get(key, value, "") < 1) return default_value; + + // libcutils unwisely allows octal, which libbase doesn't. + T result = default_value; + int saved_errno = errno; + errno = 0; + char* end = nullptr; + intmax_t v = strtoimax(value, &end, 0); + if (errno != ERANGE && end != value && v >= std::numeric_limits::min() && + v <= std::numeric_limits::max()) { + result = v; + } + errno = saved_errno; + return result; +} + +int64_t property_get_int64(const char* key, int64_t default_value) { + return property_get_int(key, default_value); +} + +int32_t property_get_int32(const char* key, int32_t default_value) { + return property_get_int(key, default_value); +} + +int property_set(const char* key, const char* value) { + return __system_property_set(key, value); +} + +int property_get(const char* key, char* value, const char* default_value) { + int len = __system_property_get(key, value); + if (len < 1 && default_value) { + snprintf(value, PROPERTY_VALUE_MAX, "%s", default_value); + return strlen(value); + } + return len; +} + +#if __has_include() + +#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ +#include + +struct callback_data { + void (*callback)(const char* name, const char* value, void* cookie); + void* cookie; +}; + +static void trampoline(void* raw_data, const char* name, const char* value, unsigned /*serial*/) { + callback_data* data = reinterpret_cast(raw_data); + data->callback(name, value, data->cookie); +} + +static void property_list_callback(const prop_info* pi, void* data) { + __system_property_read_callback(pi, trampoline, data); +} + +int property_list(void (*fn)(const char* name, const char* value, void* cookie), void* cookie) { + callback_data data = {fn, cookie}; + return __system_property_foreach(property_list_callback, &data); +} + +#endif