Property Service的启动与初始化
init进程启动,分为两个阶段,阶段一主要是添加脚本执行环境,以及初始化必要的文件系统目录。接着通过execv来执行一个参数为--second-stage的新的init进程Image以取代之前的init进程Image。
阶段一请参考http://blog.csdn.net/nwpushuai/article/details/79346665
执行第二阶段的初始化时,开始初始化属性系统,主要分为以下几个步骤:
初始化属性共享内存;
加载系统默认属性值;
启动属性服务,监听属性修改请求命令;
从磁盘中加载所有属性值到内存;
代码路径:/system/core/init/init.cpp (http://androidxref.com/8.0.0_r4/xref/system/core/init/init.cpp)
948int main(int argc, char** argv) { 949 if (!strcmp(basename(argv[0]), "ueventd")) { 950 return ueventd_main(argc, argv); 951 } 952 953 if (!strcmp(basename(argv[0]), "watchdogd")) { 954 return watchdogd_main(argc, argv); 955 } 956 957 if (REBOOT_BOOTLOADER_ON_PANIC) { 958 install_reboot_signal_handlers(); 959 } 960 961 add_environment("PATH", _PATH_DEFPATH); 962 963 bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr); 964 965 if (is_first_stage) { 966 boot_clock::time_point start_time = boot_clock::now(); 967 968 // Clear the umask. 969 umask(0);//清除屏蔽字(file mode creation mask),保证新建的目录的访问权限不受屏蔽字影响 970 971 // Get the basic filesystem setup we need put together in the initramdisk 972 // on / and then we'll let the rc file figure out the rest. 973 mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); 974 mkdir("/dev/pts", 0755); 975 mkdir("/dev/socket", 0755); 976 mount("devpts", "/dev/pts", "devpts", 0, NULL); 977 #define MAKE_STR(x) __STRING(x) 978 mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)); 979 // Don't expose the raw commandline to unprivileged processes. 980 chmod("/proc/cmdline", 0440); 981 gid_t groups[] = { AID_READPROC }; 982 setgroups(arraysize(groups), groups); 983 mount("sysfs", "/sys", "sysfs", 0, NULL); 984 mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL); 985 mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11)); 986 mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)); 987 mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)); 988 989 // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually 990 // talk to the outside world... 991 InitKernelLogging(argv); 992 993 LOG(INFO) << "init first stage started!"; 994 995 if (!DoFirstStageMount()) { 996 LOG(ERROR) << "Failed to mount required partitions early ..."; 997 panic(); 998 } 999 1000 SetInitAvbVersionInRecovery(); 1001 1002 // Set up SELinux, loading the SELinux policy. 1003 selinux_initialize(true); 1004 1005 // We're in the kernel domain, so re-exec init to transition to the init domain now 1006 // that the SELinux policy has been loaded. 1007 if (restorecon("/init") == -1) { 1008 PLOG(ERROR) << "restorecon failed"; 1009 security_failure(); 1010 } 1011 1012 setenv("INIT_SECOND_STAGE", "true", 1); 1013 1014 static constexpr uint32_t kNanosecondsPerMillisecond = 1e6; 1015 uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond; 1016 setenv("INIT_STARTED_AT", StringPrintf("%" PRIu64, start_ms).c_str(), 1); 1017 1018 char* path = argv[0]; 1019 char* args[] = { path, nullptr }; 1020 execv(path, args); 1021 1022 // execv() only returns if an error happened, in which case we 1023 // panic and never fall through this conditional. 1024 PLOG(ERROR) << "execv(\"" << path << "\") failed"; 1025 security_failure(); 1026 } 1027 1028 // At this point we're in the second stage of init. 1029 InitKernelLogging(argv); 1030 LOG(INFO) << "init second stage started!"; 1031 1032 // Set up a session keyring that all processes will have access to. It 1033 // will hold things like FBE encryption keys. No process should override 1034 // its session keyring. 1035 keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_SESSION_KEYRING, 1); 1036 1037 // Indicate that booting is in progress to background fw loaders, etc. 1038 close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000)); 1039 1040 property_init();// 初始化属性系统,将/dev/__properties__映射到共享内存 1041 1042 // If arguments are passed both on the command line and in DT, 1043 // properties set in DT always have priority over the command-line ones. 1044 process_kernel_dt(); 1045 process_kernel_cmdline(); 1046 1047 // Propagate the kernel variables to internal variables 1048 // used by init as well as the current required properties. 1049 export_kernel_boot_props(); 1050 1051 // Make the time that init started available for bootstat to log. 1052 property_set("ro.boottime.init", getenv("INIT_STARTED_AT")); 1053 property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK")); 1054 1055 // Set libavb version for Framework-only OTA match in Treble build. 1056 const char* avb_version = getenv("INIT_AVB_VERSION"); 1057 if (avb_version) property_set("ro.boot.avb_version", avb_version); 1058 1059 // Clean up our environment. 1060 unsetenv("INIT_SECOND_STAGE"); 1061 unsetenv("INIT_STARTED_AT"); 1062 unsetenv("INIT_SELINUX_TOOK"); 1063 unsetenv("INIT_AVB_VERSION"); 1064 1065 // Now set up SELinux for second stage. 1066 selinux_initialize(false); 1067 selinux_restore_context(); 1068 1069 epoll_fd = epoll_create1(EPOLL_CLOEXEC); 1070 if (epoll_fd == -1) { 1071 PLOG(ERROR) << "epoll_create1 failed"; 1072 exit(1); 1073 } 1074 1075 signal_handler_init();//信号系统初始化 1076 1077 property_load_boot_defaults();// 加载系统默认属性值 1078 export_oem_lock_status(); 1079 start_property_service();// 启动属性服务 1080 set_usb_controller(); 1081 // 解析初始化脚本 1082 const BuiltinFunctionMap function_map; 1083 Action::set_function_map(&function_map); 1084 1085 Parser& parser = Parser::GetInstance(); 1086 parser.AddSectionParser("service",std::make_unique()); 1087 parser.AddSectionParser("on", std::make_unique ()); 1088 parser.AddSectionParser("import", std::make_unique ()); 1089 std::string bootscript = GetProperty("ro.boot.init_rc", ""); 1090 if (bootscript.empty()) { 1091 parser.ParseConfig("/init.rc"); 1092 parser.set_is_system_etc_init_loaded( 1093 parser.ParseConfig("/system/etc/init")); 1094 parser.set_is_vendor_etc_init_loaded( 1095 parser.ParseConfig("/vendor/etc/init")); 1096 parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init")); 1097 } else { 1098 parser.ParseConfig(bootscript); 1099 parser.set_is_system_etc_init_loaded(true); 1100 parser.set_is_vendor_etc_init_loaded(true); 1101 parser.set_is_odm_etc_init_loaded(true); 1102 } 1103 1104 // Turning this on and letting the INFO logging be discarded adds 0.2s to 1105 // Nexus 9 boot time, so it's disabled by default. 1106 if (false) parser.DumpState(); 1107 1108 ActionManager& am = ActionManager::GetInstance(); 1109 1110 am.QueueEventTrigger("early-init"); 1111 1112 // Queue an action that waits for coldboot done so we know ueventd has set up all of /dev... 1113 am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done"); 1114 // ... so that we can start queuing up actions that require stuff from /dev. 1115 am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); 1116 am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits"); 1117 am.QueueBuiltinAction(set_kptr_restrict_action, "set_kptr_restrict"); 1118 am.QueueBuiltinAction(keychord_init_action, "keychord_init"); 1119 am.QueueBuiltinAction(console_init_action, "console_init"); 1120 1121 // Trigger all the boot actions to get us started. 1122 am.QueueEventTrigger("init"); 1123 1124 // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random 1125 // wasn't ready immediately after wait_for_coldboot_done 1126 am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); 1127 1128 // Don't mount filesystems or start core system services in charger mode. 1129 std::string bootmode = GetProperty("ro.bootmode", ""); 1130 if (bootmode == "charger") { 1131 am.QueueEventTrigger("charger"); 1132 } else { 1133 am.QueueEventTrigger("late-init"); 1134 } 1135 1136 // Run all property triggers based on current state of the properties. 1137 am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers"); 1138 1139 while (true) { 1140 // By default, sleep until something happens. 1141 int epoll_timeout_ms = -1; 1142 1143 if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) { 1144 am.ExecuteOneCommand(); 1145 } 1146 if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) { 1147 restart_processes(); 1148 1149 // If there's a process that needs restarting, wake up in time for that. 1150 if (process_needs_restart_at != 0) { 1151 epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000; 1152 if (epoll_timeout_ms < 0) epoll_timeout_ms = 0; 1153 } 1154 1155 // If there's more work to do, wake up again immediately. 1156 if (am.HasMoreCommands()) epoll_timeout_ms = 0; 1157 } 1158 1159 epoll_event ev; 1160 int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms)); 1161 if (nr == -1) { 1162 PLOG(ERROR) << "epoll_wait failed"; 1163 } else if (nr == 1) { 1164 ((void (*)()) ev.data.ptr)(); 1165 } 1166 } 1167 1168 return 0; 1169}
初始化属性系统共享内存
property_init()
代码路径:/system/core/init/property_service.cpp
(http://androidxref.com/8.0.0_r4/xref/system/core/init/property_service.cpp)
68void property_init() { 69 if (__system_property_area_init()) { 70 LOG(ERROR) << "Failed to initialize property area"; 71 exit(1); 72 } 73}
判断属性系统共享内存区域是否成功创建。
__system_property_area_init
代码路径:/bionic/libc/bionic/system_properties.cpp
(http://androidxref.com/8.0.0_r4/xref/bionic/libc/bionic/system_properties.cpp)
1117int __system_property_area_init() { 1118 free_and_unmap_contexts(); 1119 mkdir(property_filename, S_IRWXU | S_IXGRP | S_IXOTH); 1120 if (!initialize_properties()) { 1121 return -1; 1122 } 1123 bool open_failed = false; 1124 bool fsetxattr_failed = false; 1125 list_foreach(contexts, [&fsetxattr_failed, &open_failed](context_node* l) { 1126 if (!l->open(true, &fsetxattr_failed)) { 1127 open_failed = true; 1128 } 1129 }); 1130 if (open_failed || !map_system_property_area(true, &fsetxattr_failed)) {//分配内存 1131 free_and_unmap_contexts(); 1132 return -1; 1133 } 1134 initialized = true; 1135 return fsetxattr_failed ? -2 : 0; 1136}
在1130调用函数map_system_property_area创建一个共享内存区域,将文件映射到该内存区域
map_system_property_area
代码路径:/bionic/libc/bionic/system_properties.cpp (http://androidxref.com/8.0.0_r4/xref/bionic/libc/bionic/system_properties.cpp)
864static bool map_system_property_area(bool access_rw, bool* fsetxattr_failed) { 865 char filename[PROP_FILENAME_MAX]; 866 int len = 867 __libc_format_buffer(filename, sizeof(filename), "%s/properties_serial", property_filename); 868 if (len < 0 || len > PROP_FILENAME_MAX) { 869 __system_property_area__ = nullptr; 870 return false; 871 } 872 873 if (access_rw) { 874 __system_property_area__ = 875 map_prop_area_rw(filename, "u:object_r:properties_serial:s0", fsetxattr_failed); 876 } else { 877 __system_property_area__ = map_prop_area(filename);//真正分配内存的地方 878 } 879 return __system_property_area__; 880}
(http://androidxref.com/8.0.0_r4/xref/system/core/init/init.cpp)
1077 property_load_boot_defaults();
完成了属性系统的内存初始化后,加载系统默认的属性值到内存区域
代码路径:/system/core/init/property_service.cpp
(http://androidxref.com/8.0.0_r4/xref/system/core/init/property_service.cpp)
595void property_load_boot_defaults() { 596 if (!load_properties_from_file("/system/etc/prop.default", NULL)) { 597 // Try recovery path 598 if (!load_properties_from_file("/prop.default", NULL)) { 599 // Try legacy path 600 load_properties_from_file("/default.prop", NULL); 601 } 602 } 603 load_properties_from_file("/odm/default.prop", NULL); 604 load_properties_from_file("/vendor/default.prop", NULL); 605 606 update_sys_usb_config(); 607}
加载属性默认的文件
代码路径:/system/core/init/property_service.cpp
(http://androidxref.com/8.0.0_r4/xref/system/core/init/property_service.cpp)
509// Filter is used to decide which properties to load: NULL loads all keys, 510// "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match. 511static bool load_properties_from_file(const char* filename, const char* filter) { 512 Timer t; 513 std::string data; 514 if (!read_file(filename, &data)) { 515 PLOG(WARNING) << "Couldn't load properties from " << filename; 516 return false; 517 } 518 data.push_back('\n'); 519 load_properties(&data[0], filter); 520 LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)"; 521 return true; 522}
解析默认属性文件
(http://androidxref.com/8.0.0_r4/xref/system/core/init/init.cpp)
1079 start_property_service();启动属性服务
代码路径:/system/core/init/property_service.cpp
(http://androidxref.com/8.0.0_r4/xref/system/core/init/property_service.cpp)
666void start_property_service() { 667 property_set("ro.property_service.version", "2"); 668 669 property_set_fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 670 0666, 0, 0, NULL);//创建socket 671 if (property_set_fd == -1) { 672 PLOG(ERROR) << "start_property_service socket creation failed"; 673 exit(1); 674 } 675 676 listen(property_set_fd, 8); 677 678 register_epoll_handler(property_set_fd, handle_property_set_fd);//注册处理函数 679}EPOLL一旦有收到来自进程的写属性请求,就调用handle_property_set_fd,该函数首先接受socket绑定请求,接着接收消息数据,最后调用property_set设置属性:
代码路径:/system/core/init/property_service.cpp
(http://androidxref.com/8.0.0_r4/xref/system/core/init/property_service.cpp)
382static void handle_property_set_fd() { 383 static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */ 384 385 int s = accept4(property_set_fd, nullptr, nullptr, SOCK_CLOEXEC);// 接受bind请求 386 if (s == -1) { 387 return; 388 } 389 390 struct ucred cr; 391 socklen_t cr_size = sizeof(cr); 392 if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {//取出客户端进程的权限等 393 close(s); 394 PLOG(ERROR) << "sys_prop: unable to get SO_PEERCRED"; 395 return; 396 } 397 398 SocketConnection socket(s, cr); 399 uint32_t timeout_ms = kDefaultSocketTimeout; 400 401 uint32_t cmd = 0; 402 if (!socket.RecvUint32(&cmd, &timeout_ms)) { 403 PLOG(ERROR) << "sys_prop: error while reading command from the socket"; 404 socket.SendUint32(PROP_ERROR_READ_CMD); 405 return; 406 } 407 408 switch (cmd) { 409 case PROP_MSG_SETPROP: { 410 char prop_name[PROP_NAME_MAX]; 411 char prop_value[PROP_VALUE_MAX]; 412 413 if (!socket.RecvChars(prop_name, PROP_NAME_MAX, &timeout_ms) || 414 !socket.RecvChars(prop_value, PROP_VALUE_MAX, &timeout_ms)) { 415 PLOG(ERROR) << "sys_prop(PROP_MSG_SETPROP): error while reading name/value from the socket"; 416 return; 417 } 418 419 prop_name[PROP_NAME_MAX-1] = 0; 420 prop_value[PROP_VALUE_MAX-1] = 0; 421 422 handle_property_set(socket, prop_value, prop_value, true); 423 break; 424 } 425 426 case PROP_MSG_SETPROP2: { 427 std::string name; 428 std::string value; 429 if (!socket.RecvString(&name, &timeout_ms) || 430 !socket.RecvString(&value, &timeout_ms)) { 431 PLOG(ERROR) << "sys_prop(PROP_MSG_SETPROP2): error while reading name/value from the socket"; 432 socket.SendUint32(PROP_ERROR_READ_DATA); 433 return; 434 } 435 436 handle_property_set(socket, name, value, false); 437 break; 438 } 439 440 default: 441 LOG(ERROR) << "sys_prop: invalid command " << cmd; 442 socket.SendUint32(PROP_ERROR_INVALID_CMD); 443 break; 444 } 445}
334static void handle_property_set(SocketConnection& socket, 335 const std::string& name, 336 const std::string& value, 337 bool legacy_protocol) { 338 const char* cmd_name = legacy_protocol ? "PROP_MSG_SETPROP" : "PROP_MSG_SETPROP2"; 339 if (!is_legal_property_name(name)) { 340 LOG(ERROR) << "sys_prop(" << cmd_name << "): illegal property name \"" << name << "\""; 341 socket.SendUint32(PROP_ERROR_INVALID_NAME); 342 return; 343 } 344 345 struct ucred cr = socket.cred(); 346 char* source_ctx = nullptr; 347 getpeercon(socket.socket(), &source_ctx); 348 349 if (android::base::StartsWith(name, "ctl.")) { 350 if (check_control_mac_perms(value.c_str(), source_ctx, &cr)) { 351 handle_control_message(name.c_str() + 4, value.c_str()); 352 if (!legacy_protocol) { 353 socket.SendUint32(PROP_SUCCESS); 354 } 355 } else { 356 LOG(ERROR) << "sys_prop(" << cmd_name << "): Unable to " << (name.c_str() + 4) 357 << " service ctl [" << value << "]" 358 << " uid:" << cr.uid 359 << " gid:" << cr.gid 360 << " pid:" << cr.pid; 361 if (!legacy_protocol) { 362 socket.SendUint32(PROP_ERROR_HANDLE_CONTROL_MESSAGE); 363 } 364 } 365 } else { 366 if (check_mac_perms(name, source_ctx, &cr)) { 367 uint32_t result = property_set(name, value); 368 if (!legacy_protocol) { 369 socket.SendUint32(result); 370 } 371 } else { 372 LOG(ERROR) << "sys_prop(" << cmd_name << "): permission denied uid:" << cr.uid << " name:" << name; 373 if (!legacy_protocol) { 374 socket.SendUint32(PROP_ERROR_PERMISSION_DENIED); 375 } 376 } 377 } 378 379 freecon(source_ctx); 380}
Android提供了两种访问系统属性的方法,一种是通过JAVA Framework层的代码SystemProperties.java中提供的接口,由于该类接口并没有放入到SDK中,因此APP开发并不能使用此接口;一个是通过C++来访问,在代码中包含/system/core/include/cutils/properties.h头文件即可使用property_get/property_set来获取或者设置系统属性值。
Java: /frameworks/base/core/java/android/os/SystemProperties.java
C++: /system/core/libcutils/include/cutils/properties.h
实质上,两种方法最后都是通过bionic的libc库中的API来访问系统属性
代码路径:/system/core/libcutils/properties.cpp
(http://androidxref.com/8.0.0_r4/xref/system/core/libcutils/properties.cpp)
调用libcutils中的property_get
114int property_get(const char *key, char *value, const char *default_value) { 115 int len = __system_property_get(key, value); 116 if (len > 0) { 117 return len; 118 } 119 if (default_value) { 120 len = strnlen(default_value, PROPERTY_VALUE_MAX - 1); 121 memcpy(value, default_value, len); 122 value[len] = '\0'; 123 } 124 return len; 125}
代码路径:/bionic/libc/bionic/system_properties.cpp
(http://androidxref.com/8.0.0_r4/xref/bionic/libc/bionic/system_properties.cpp)
在115行调用bionic中的__system_property_get:
1221int __system_property_get(const char* name, char* value) { 1222 const prop_info* pi = __system_property_find(name); 1223 1224 if (pi != 0) { 1225 return __system_property_read(pi, nullptr, value); 1226 } else { 1227 value[0] = 0; 1228 return 0; 1229 } 1230}
代码路径:/system/core/libcutils/properties.cpp
(http://androidxref.com/8.0.0_r4/xref/system/core/libcutils/properties.cpp)
写系统属性与读属性不一样的地方在于需要通过一个socket来发送写请求。首先是通过libcutils库中的property_set来设置属性
110int property_set(const char *key, const char *value) { 111 return __system_property_set(key, value); 112}
在111行调用bionic中的__system_property_set
1257int __system_property_set(const char* key, const char* value) { 1258 if (key == nullptr) return -1; 1259 if (value == nullptr) value = ""; 1260 if (strlen(value) >= PROP_VALUE_MAX) return -1; 1261 1262 if (g_propservice_protocol_version == 0) { 1263 detect_protocol_version(); 1264 } 1265 1266 if (g_propservice_protocol_version == kProtocolVersion1) { 1267 // Old protocol does not support long names 1268 if (strlen(key) >= PROP_NAME_MAX) return -1; 1269 1270 prop_msg msg; 1271 memset(&msg, 0, sizeof msg); 1272 msg.cmd = PROP_MSG_SETPROP; 1273 strlcpy(msg.name, key, sizeof msg.name); 1274 strlcpy(msg.value, value, sizeof msg.value); 1275 1276 return send_prop_msg(&msg); 1277 } else {
........................................... 1329 } 1330}
在1276行调用send_prop_msg(&msg)向系统属性服务的socket/dev/socket/property_service发送写属性请求
获取一个本地socket文件描述符,并与系统属性服务的socket进行连接;
连接成功后,向系统属性服务socket发送消息;
等待系统属性服务返回写属性结果;
608static int send_prop_msg(const prop_msg* msg) { 609 PropertyServiceConnection connection; 610 if (!connection.IsValid()) { 611 return connection.GetLastError(); 612 } 613 614 int result = -1; 615 int s = connection.socket();//获取一个本地socket文件描述符,并与系统属性服务的socket进行连接 616 617 const int num_bytes = TEMP_FAILURE_RETRY(send(s, msg, sizeof(prop_msg), 0));// 发送消息到socket 618 if (num_bytes == sizeof(prop_msg)) {//等待系统属性服务返回写属性结果 619 // We successfully wrote to the property server but now we 620 // wait for the property server to finish its work. It 621 // acknowledges its completion by closing the socket so we 622 // poll here (on nothing), waiting for the socket to close. 623 // If you 'adb shell setprop foo bar' you'll see the POLLHUP 624 // once the socket closes. Out of paranoia we cap our poll 625 // at 250 ms. 626 pollfd pollfds[1]; 627 pollfds[0].fd = s; 628 pollfds[0].events = 0; 629 const int poll_result = TEMP_FAILURE_RETRY(poll(pollfds, 1, 250 /* ms */)); 630 if (poll_result == 1 && (pollfds[0].revents & POLLHUP) != 0) { 631 result = 0; 632 } else { 633 // Ignore the timeout and treat it like a success anyway. 634 // The init process is single-threaded and its property 635 // service is sometimes slow to respond (perhaps it's off 636 // starting a child process or something) and thus this 637 // times out and the caller thinks it failed, even though 638 // it's still getting around to it. So we fake it here, 639 // mostly for ctl.* properties, but we do try and wait 250 640 // ms so callers who do read-after-write can reliably see 641 // what they've written. Most of the time. 642 // TODO: fix the system properties design. 643 __libc_format_log(ANDROID_LOG_WARN, "libc", 644 "Property service has timed out while trying to set \"%s\" to \"%s\"", 645 msg->name, msg->value); 646 result = 0; 647 } 648 } 649 650 return result; 651}
系统属性服务监听到有消息时,调用回调函数handle_property_set_fd进行属性的修改
调用property_set修改系统属性:
从属性数据结构prop_area中查找给定的属性,返回prop_info;
如果当前存在该属性值,则直接更新,否则需要新建该属性prop_info;
对于persist的属性值,需要保存到文件/data/property中;
166uint32_t property_set(const std::string& name, const std::string& value) { 167 size_t valuelen = value.size(); 168 169 if (!is_legal_property_name(name)) { 170 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: bad name"; 171 return PROP_ERROR_INVALID_NAME; 172 } 173 174 if (valuelen >= PROP_VALUE_MAX) { 175 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: " 176 << "value too long"; 177 return PROP_ERROR_INVALID_VALUE; 178 } 179 180 if (name == "selinux.restorecon_recursive" && valuelen > 0) { 181 if (restorecon(value.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) { 182 LOG(ERROR) << "Failed to restorecon_recursive " << value; 183 } 184 } 185 186 prop_info* pi = (prop_info*) __system_property_find(name.c_str());//从属性数据结构prop_area中查找给定的属性,返回prop_info 187 if (pi != nullptr) { 188 // ro.* properties are actually "write-once". 189 if (android::base::StartsWith(name, "ro.")) { 190 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: " 191 << "property already set"; 192 return PROP_ERROR_READ_ONLY_PROPERTY; 193 } 194 195 __system_property_update(pi, value.c_str(), valuelen);//如果当前存在该属性值,则直接更新,否则需要新建该属性prop_info 196 } else { 197 int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen); 198 if (rc < 0) { 199 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: " 200 << "__system_property_add failed"; 201 return PROP_ERROR_SET_FAILED; 202 } 203 } 204 205 // Don't write properties to disk until after we have read all default 206 // properties to prevent them from being overwritten by default values. 207 if (persistent_properties_loaded && android::base::StartsWith(name, "persist.")) { 208 write_persistent_property(name.c_str(), value.c_str()); 209 } 210 property_changed(name, value); 211 return PROP_SUCCESS; 212}
如果系统属性已经加载完,则将修改后的persist系统属性保存到文件/data/property
118static void write_persistent_property(const char *name, const char *value) 119{ 120 char tempPath[PATH_MAX]; 121 char path[PATH_MAX]; 122 int fd; 123 124 snprintf(tempPath, sizeof(tempPath), "%s/.temp.XXXXXX", PERSISTENT_PROPERTY_DIR); 125 fd = mkstemp(tempPath); 126 if (fd < 0) { 127 PLOG(ERROR) << "Unable to write persistent property to temp file " << tempPath; 128 return; 129 } 130 write(fd, value, strlen(value)); 131 fsync(fd); 132 close(fd); 133 134 snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name); 135 if (rename(tempPath, path)) { 136 PLOG(ERROR) << "Unable to rename persistent property file " << tempPath << " to " << path; 137 unlink(tempPath); 138 } 139}