赞
踩
这是一个介绍 Android 属性系统的系列文章:
本文基于 AOSP android-10.0.0_r41 版本讲解
在 Android 系统中,为统一管理系统的属性,设计了一个统一的属性系统,每个属性都是一个 key-value 对。 我们可以通过 shell 命令,Native 函数接口,Java 函数接口的方式来读写这些 key-vaule 对。
init 进程在启动会去加载后缀为 .prop 的属性文件, 将属性文件中的属性加载到共享内存中, 这样系统就有了默认的一些属性。
属性文件都在哪里呢?
属性文件的后缀绝大部分都是 prop,我们可以在 Android 模拟器的 shell 环境下搜索:
find . -name "*.prop"
/default.prop
/data/local.prop
/system/build.prop
/system/product/build.prop
/vendor/build.prop
/vendor/odm/etc/build.prop
/vendor/default.prop
我们看看 /default.prop
属性文件的内容:
cat /default.prop # # ADDITIONAL_DEFAULT_PROPERTIES # ro.actionable_compatible_property.enabled=true ro.postinstall.fstab.prefix=/system ro.secure=0 ro.allow.mock.location=1 ro.debuggable=1 debug.atrace.tags.enableflags=0 dalvik.vm.image-dex2oat-Xms=64m dalvik.vm.image-dex2oat-Xmx=64m dalvik.vm.dex2oat-Xms=64m dalvik.vm.dex2oat-Xmx=512m dalvik.vm.usejit=true dalvik.vm.usejitprofiles=true dalvik.vm.dexopt.secondary=true dalvik.vm.appimageformat=lz4 ro.dalvik.vm.native.bridge=0 pm.dexopt.first-boot=extract pm.dexopt.boot=extract pm.dexopt.install=speed-profile pm.dexopt.bg-dexopt=speed-profile pm.dexopt.ab-ota=speed-profile pm.dexopt.inactive=verify pm.dexopt.shared=speed dalvik.vm.dex2oat-resolve-startup-strings=true dalvik.vm.dex2oat-max-image-block-size=524288 dalvik.vm.minidebuginfo=true dalvik.vm.dex2oat-minidebuginfo=true ro.iorapd.enable=false tombstoned.max_tombstone_count=50 persist.traced.enable=1 ro.com.google.locationfeatures=1 ro.setupwizard.mode=DISABLED persist.sys.usb.config=adb
可以看出属性确实是一些 key-value 对。
init 进程会调用 property_load_boot_defaults
函数来加载属性文件:
void property_load_boot_defaults(bool load_debug_prop) { // 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("/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("/product_services/build.prop", nullptr, &properties); load_properties_from_file("/factory/factory.prop", "ro.*", &properties); if (load_debug_prop) { LOG(INFO) << "Loading " << kDebugRamdiskProp; load_properties_from_file(kDebugRamdiskProp, nullptr, &properties); } 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(); }
从源码中我们也可以看到 init 进程加载了哪些属性文件以及加载的顺序。
每一个属性是一个 key-value 对:
ro.actionable_compatible_property.enabled=true
ro.postinstall.fstab.prefix=/system
ro.secure=0
ro.allow.mock.location=1
ro.debuggable=1
debug.atrace.tags.enableflags=0
dalvik.vm.image-dex2oat-Xms=64m
dalvik.vm.image-dex2oat-Xmx=64m
等号左边是属性的名字,等号右边是属性的值
属性的分类:
ro
开头,那么这个属性被视为只读属性。一旦设置,属性值不能改变。net
开头的属性,顾名思义,就是与网络相关的属性,net
属性中有一个特殊的属性:net.change
,它记录了每一次最新设置和更新的 net
属性,也就是每次设置和更新 net
,属性时则会自动的更新 net.change
属性,net.change
属性的 value 就是这个被设置或者更新的 net
属性的 name。例如我们更新了属性 net.bt.name
的值,由于 net
有属性发生了变化,那么属性服务就会自动更新 net.change
,将其值设置为 net.bt.name
。persist
为开头的属性值,当在系统中通过 setprop 命令设置这个属性时,就会在 /data/property/
目录下会保存一个副本。这样在系统重启后,按照加载流程这些 persist
属性的值就不会消失了。ctrl.start
和 ctrl.stop
是用来启动和停止服务。这里的服务是指定义在 rc 后缀文件中的服务。当我们向 ctrl.start
属性写入一个值时,属性服务将使用该属性值作为服务名找到该服务,启动该服务。这项服务的启动结果将会放入 init.svc.<服务名>
属性中,可以通过查询这个属性值,以确定服务是否已经启动。命令行:
getprop "wlan.driver.status"
setprop "wlan.driver.status" "timeout"
Native 代码:
char buf[20]="qqqqqq";
char tempbuf[PROPERTY_VALUE_MAX];
property_set("type_value",buf);
property_get("type_value",tempbuf,"0");
Java 代码:
String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
SystemProperties.set("service.bootanim.exit", "0");
常见的属性文件的作用如下:
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓(文末还有ChatGPT机器人小福利哦,大家千万不要错过)
PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。