系统属性prop文件设置
相关文件
// 读写属性的c代码
system/core/init/init.c
system/core/init/property_service.c
system/core/libcutils/properties.c
bionic/libc/bionic/system_properties.c
// 编译环境脚本和mk
build/core/Makefile
build/tools/buildinfo.sh
什么是Android的属性
每个属性都有一个名称和值,它们都是字符串格式。属性被大量使用在Android系统中,用来记录系统设置或进程之间的信息交换。
属性是在整个系统中全局可见的。每个进程可以get/set属性。在系统初始化时,Android将分配一个共享内存区来存储的属性。这些是
由“init”守护进程完成的,其源代码位于:system/core/init。“init”守护进程将启动一个属性服务。属性服务在“init”守护进程中运行。
每一个客户端想要设置属性时,必须连接属性服务,再向其发送信息。属性服务将会在共享内存区中修改和创建属性。任何客户端想获得
属性信息,可以从共享内存直接读取。这提高了读取性能。
属性文件的位置
当启动属性服务时,将从以下文件中加载默认属性:
/default.prop
/system/build.prop
/system/default.prop
/data/local.prop
属性将会以上述顺序加载,后加载的属性将覆盖原先的值。这些属性加载之后,最后加载的属性会被保持在/data/property中。
查看和修改系统属性
# 查看属性
# 打开adb模式,输入以下命令
$ adb shell getprop
# 修改属性
$ adb shell setprop key value
属性分类
|
前缀
|
功能
|
备注
|
|
ro.*
|
该属性被视为只读属性。一旦设置,属性值不能改变。
|
|
|
persist.*
|
当设置这个属性时,其值也将写入/data/property。
|
|
|
net.*
|
当设置这个属性时,“net.change”属性将会自动设置,以加入到最后修改的属性名。
|
|
|
ctrl.start和ctrl.stop
|
用来启动和停止服务。每一项服务必须在/init.rc中定义。系统启动时,与init守护进程将解析init.rc和启动属性服务。一旦收到设置“ ctrl.start ”属性的请求,属性服务将使用该属性值作为服务名找到该服务,启动该服务。这项服务的启动结果将会放入“ init.svc.<服务名>“属性中 。客户端应用程序可以轮询那个属性值,以确定结果。
|
|
如何编译属性信息
-
build/core/Makefile中会调用
build/tools/buildinfo.sh脚本来设置属性值
-
自定义属性可通过
PRODUCT_PROPERTY_OVERRIDES变量设置。(参见Build环境变量)
buildinfo.sh
#!/bin/bash
echo "# begin build properties"
echo "# autogenerated by buildinfo.sh"
echo "ro.build.id=$BUILD_ID"
echo "ro.build.display.id=$BUILD_DISPLAY_ID"
echo "ro.build.version.incremental=$BUILD_NUMBER"
echo "ro.build.version.sdk=$PLATFORM_SDK_VERSION"
echo "ro.build.version.codename=$PLATFORM_VERSION_CODENAME"
echo "ro.build.version.release=$PLATFORM_VERSION"
echo "ro.build.date=`date`"
echo "ro.build.date.utc=`date +%s`"
echo "ro.build.type=$TARGET_BUILD_TYPE"
echo "ro.build.user=$USER"
echo "ro.build.host=`hostname`"
echo "ro.build.tags=$BUILD_VERSION_TAGS"
echo "ro.product.model=$PRODUCT_MODEL"
echo "ro.product.brand=$PRODUCT_BRAND"
echo "ro.product.name=$PRODUCT_NAME"
echo "ro.product.device=$TARGET_DEVICE"
echo "ro.product.board=$TARGET_BOOTLOADER_BOARD_NAME"
echo "ro.product.cpu.abi=$TARGET_CPU_ABI"
if [ -n "$TARGET_CPU_ABI2" ] ; then
echo "ro.product.cpu.abi2=$TARGET_CPU_ABI2"
fi
echo "ro.product.manufacturer=$PRODUCT_MANUFACTURER"
echo "ro.product.locale.language=$PRODUCT_DEFAULT_LANGUAGE"
echo "ro.product.locale.region=$PRODUCT_DEFAULT_REGION"
echo "ro.wifi.channels=$PRODUCT_DEFAULT_WIFI_CHANNELS"
echo "ro.board.platform=$TARGET_BOARD_PLATFORM"
echo "# ro.build.product is obsolete; use ro.product.device"
echo "ro.build.product=$TARGET_DEVICE"
echo "# Do not try to parse ro.build.description or .fingerprint"
echo "ro.build.description=$PRIVATE_BUILD_DESC"
echo "ro.build.fingerprint=$BUILD_FINGERPRINT"
echo "# end build properties"
build/core/Makefile
default.prop部分
# 生成/default.prop
INSTALLED_DEFAULT_PROP_TARGET := $(TARGET_ROOT_OUT)/default.prop
ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_DEFAULT_PROP_TARGET)
ADDITIONAL_DEFAULT_PROPERTIES := \
$(call collapse-pairs, $(ADDITIONAL_DEFAULT_PROPERTIES))
$(INSTALLED_DEFAULT_PROP_TARGET):
@echo Target buildinfo: $@
@mkdir -p $(dir $@)
$(hide) echo "#" > $@; \
echo "# ADDITIONAL_DEFAULT_PROPERTIES" >> $@; \
echo "#" >> $@;
$(hide) $(foreach line,$(ADDITIONAL_DEFAULT_PROPERTIES), \
echo "$(line)" >> $@;)
build.prop部分
# 生成/system/build.prop
INSTALLED_BUILD_PROP_TARGET := $(TARGET_OUT)/build.prop
ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_BUILD_PROP_TARGET)
ADDITIONAL_BUILD_PROPERTIES := \
$(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES))
# 预置的tags描述
BUILD_VERSION_TAGS := $(BUILD_VERSION_TAGS)
ifeq ($(TARGET_BUILD_TYPE),debug)
BUILD_VERSION_TAGS += debug
endif
# 为app预设test-keys的tags
BUILD_VERSION_TAGS += test-keys
BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
# 可读的字符串描述
build_desc := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) $(PLATFORM_VERSION) $(BUILD_ID) $(BUILD_NUMBER) $(BUILD_VERSION_TAGS)
$(INSTALLED_BUILD_PROP_TARGET): PRIVATE_BUILD_DESC := $(build_desc)
# 用于OTA服务器的字符串识别信息
ifeq (,$(strip $(BUILD_FINGERPRINT)))
BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE)/$(TARGET_BOOTLOADER_BOARD_NAME):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
endif
ifneq ($(words $(BUILD_FINGERPRINT)),1)
$(error BUILD_FINGERPRINT cannot contain spaces: "$(BUILD_FINGERPRINT)")
endif
# Display parameters shown under Settings -> About Phone
ifeq ($(TARGET_BUILD_VARIANT),user)
# User builds should show:
# release build number or branch.buld_number non-release builds
# Dev. branches should have DISPLAY_BUILD_NUMBER set
ifeq "true" "$(DISPLAY_BUILD_NUMBER)"
BUILD_DISPLAY_ID := $(BUILD_ID).$(BUILD_NUMBER)
else
BUILD_DISPLAY_ID := $(BUILD_ID)
endif
else
# Non-user builds should show detailed build information
BUILD_DISPLAY_ID := $(build_desc)
endif
# 默认的locale设置
define default-locale
$(subst _, , $(firstword $(1)))
endef
# 默认语言和区域设置
define default-locale-language
$(word 2, 2, $(call default-locale, $(1)))
endef
define default-locale-region
$(word 3, 3, $(call default-locale, $(1)))
endef
# 使用buildinfo.sh脚本设置默认的变量
BUILDINFO_SH := build/tools/buildinfo.sh
$(INSTALLED_BUILD_PROP_TARGET): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE)
@echo Target buildinfo: $@
@mkdir -p $(dir $@)
$(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
TARGET_DEVICE="$(TARGET_DEVICE)" \
PRODUCT_NAME="$(TARGET_PRODUCT)" \
PRODUCT_BRAND="$(PRODUCT_BRAND)" \
PRODUCT_DEFAULT_LANGUAGE="$(call default-locale-language,$(PRODUCT_LOCALES))" \
PRODUCT_DEFAULT_REGION="$(call default-locale-region,$(PRODUCT_LOCALES))" \
PRODUCT_DEFAULT_WIFI_CHANNELS="$(PRODUCT_DEFAULT_WIFI_CHANNELS)" \
PRODUCT_MODEL="$(PRODUCT_MODEL)" \
PRODUCT_MANUFACTURER="$(PRODUCT_MANUFACTURER)" \
PRIVATE_BUILD_DESC="$(PRIVATE_BUILD_DESC)" \
BUILD_ID="$(BUILD_ID)" \
BUILD_DISPLAY_ID="$(BUILD_DISPLAY_ID)" \
BUILD_NUMBER="$(BUILD_NUMBER)" \
PLATFORM_VERSION="$(PLATFORM_VERSION)" \
PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \
PLATFORM_VERSION_CODENAME="$(PLATFORM_VERSION_CODENAME)" \
BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \
TARGET_BOOTLOADER_BOARD_NAME="$(TARGET_BOOTLOADER_BOARD_NAME)" \
BUILD_FINGERPRINT="$(BUILD_FINGERPRINT)" \
TARGET_BOARD_PLATFORM="$(TARGET_BOARD_PLATFORM)" \
TARGET_CPU_ABI="$(TARGET_CPU_ABI)" \
TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)" \
bash $(BUILDINFO_SH) > $@
$(hide) if [ -f $(TARGET_DEVICE_DIR)/system.prop ]; then \
cat $(TARGET_DEVICE_DIR)/system.prop >> $@; \
fi
$(if $(ADDITIONAL_BUILD_PROPERTIES), \
$(hide) echo >> $@; \
echo "#" >> $@; \
echo "# ADDITIONAL_BUILD_PROPERTIES" >> $@; \
echo "#" >> $@; )
$(hide) $(foreach line,$(ADDITIONAL_BUILD_PROPERTIES), \
echo "$(line)" >> $@;)
build_desc :=
sdk-build.prop部分
# sdk-build.prop
#
# There are certain things in build.prop that we don't want to
# ship with the sdk; remove them.
# This must be a list of entire property keys followed by
# "=" characters, without any internal spaces.
sdk_build_prop_remove := \
ro.build.user= \
ro.build.host= \
ro.product.brand= \
ro.product.manufacturer= \
ro.product.device=
# TODO: Remove this soon-to-be obsolete property
sdk_build_prop_remove += ro.build.product=
INSTALLED_SDK_BUILD_PROP_TARGET := $(PRODUCT_OUT)/sdk/sdk-build.prop
$(INSTALLED_SDK_BUILD_PROP_TARGET): $(INSTALLED_BUILD_PROP_TARGET)
@echo SDK buildinfo: $@
@mkdir -p $(dir $@)
$(hide) grep -v "$(subst $(space),\|,$(strip \
$(sdk_build_prop_remove)))" $< > $@.tmp
$(hide) for x in $(sdk_build_prop_remove); do \
echo "$$x"generic >> $@.tmp; done
$(hide) mv $@.tmp $@
属性标识列表
|
标识字符串
|
值
|
描述
|
|
ro.secure
|
0
|
adbd是否运行在root模式
|
|
ro.allow.mock.location
|
1
|
允许模拟地点
|
|
ro.debuggable
|
1
|
是否是可调试模式
|
|
persist.service.adb.enable
|
1
|
adb是否可用
|
|
ro.kernel.qemu
|
1
|
|
|
ro.kernel.console
|
ttyS0
|
|
|
ro.kernel.android.checkjni
|
1
|
|
|
ro.kernel.android.qemud
|
ttyS1
|
|
|
ro.factorytest
|
0
|
是否是工厂测试
|
|
ro.serialno
|
|
手机序列号
|
|
ro.bootmode
|
unknown
|
启动模式
|
|
ro.baseband
|
unknown
|
基带信息
|
|
ro.carrier
|
unknown
|
机器的CID
|
|
ro.bootloader
|
unknown
|
引导程序的版本
|
|
ro.hardware
|
goldfish
|
CPU信息
|
|
ro.revision
|
0
|
硬件修订版本号
|
|
ro.build.id
|
CUPCAKE
|
|
|
ro.build.display.id
|
sdk-eng 1.5 CUPCAKE 148875 test-keys
|
|
|
ro.build.version.incremental
|
148875
|
|
|
ro.build.version.sdk
|
3
|
|
|
ro.build.version.release
|
1.5
|
|
|
ro.build.date
|
Thu May 14 17:29:49 PDT 2009
|
|
|
ro.build.date.utc
|
1242347389
|
|
|
ro.build.type
|
eng
|
|
|
ro.build.user
|
android-build
|
|
|
ro.build.host
|
e-honda.mtv.corp.google.com
|
|
|
ro.build.tags
|
test-keys
|
|
|
ro.product.model
|
sdk
|
|
|
ro.product.brand
|
generic
|
|
|
ro.product.name
|
sdk
|
|
|
ro.product.device
|
generic
|
|
|
ro.product.board
|
|
|
|
ro.product.manufacturer
|
unknown
|
|
|
ro.product.locale.language
|
en
|
|
|
ro.product.locale.region
|
US
|
|
|
ro.board.platform
|
|
|
|
ro.build.product
|
generic
|
|
|
ro.build.description
|
sdk-eng 1.5 CUPCAKE 148875 test-keys
|
|
|
ro.build.fingerprint
|
generic/sdk/generic/:1.5/CUPCAKE/148875:eng/test-keys
|
|
|
ro.sf.hwrotation
|
ro.sf.hwrotation=270
|
设置屏幕旋转度数
|
|
rild.libpath
|
/system/lib/libreference-ril.so
|
|
|
rild.libargs
|
-d /dev/ttyS0
|
|
|
ro.config.notification_sound
|
F1_New_SMS.ogg
|
|
|
xmpp.auto-presence
|
true
|
|
|
ro.config.nocheckin
|
yes
|
|
|
net.bt.name
|
Android
|
|
|
net.change
|
net.gprs.local-ip
|
|
|
dalvik.vm.stack-trace-file
|
/data/anr/traces.txt
|
|
|
persist.sys.timezone
|
GMT
|
|
|
persist.sys.language
|
en
|
|
|
persist.sys.country
|
US
|
|
|
persist.sys.localevar
|
|
|
|
ro.FOREGROUND_APP_ADJ
|
0
|
|
|
ro.VISIBLE_APP_ADJ
|
1
|
|
|
ro.SECONDARY_SERVER_ADJ
|
2
|
|
|
ro.HOME_APP_ADJ
|
4
|
|
|
ro.HIDDEN_APP_MIN_ADJ
|
7
|
|
|
ro.CONTENT_PROVIDER_ADJ
|
14
|
|
|
ro.EMPTY_APP_ADJ
|
15
|
|
|
ro.FOREGROUND_APP_MEM
|
1536
|
|
|
ro.VISIBLE_APP_MEM
|
2048
|
|
|
ro.SECONDARY_SERVER_MEM
|
4096
|
|
|
ro.HOME_APP_MEM
|
4096
|
|
|
ro.HIDDEN_APP_MEM
|
5120
|
|
|
ro.CONTENT_PROVIDER_MEM
|
5632
|
|
|
ro.EMPTY_APP_MEM
|
6144
|
|
|
net.tcp.buffersize.default
|
4096,87380,110208,4096,16384,110208
|
|
|
net.tcp.buffersize.wifi
|
4095,87380,110208,4096,16384,110208
|
|
|
net.tcp.buffersize.umts
|
4094,87380,110208,4096,16384,110208
|
|
|
net.tcp.buffersize.edge
|
4093,26280,35040,4096,16384,35040
|
|
|
net.tcp.buffersize.gprs
|
4092,8760,11680,4096,8760,11680
|
|
|
init.svc.console
|
running
|
|
|
init.svc.servicemanager
|
running
|
|
|
init.svc.vold
|
running
|
|
|
init.svc.debuggerd
|
running
|
|
|
init.svc.ril-daemon
|
running
|
|
|
init.svc.zygote
|
running
|
|
|
init.svc.media
|
running
|
|
|
init.svc.installd
|
running
|
|
|
init.svc.flash_recovery
|
stopped
|
|
|
init.svc.goldfish-setup
|
stopped
|
|
|
init.svc.qemud
|
stopped
|
|
|
init.svc.goldfish-logcat
|
stopped
|
|
|
ARGH
|
ARGH
|
|
|
net.eth0.dns1
|
10.0.2.3
|
|
|
net.gprs.local-ip
|
10.0.2.15
|
|
|
ro.radio.use-ppp
|
no
|
|
|
status.battery.state
|
slow
|
|
|
status.battery.level
|
5
|
|
|
status.battery.level_raw
|
50
|
|
|
status.battery.level_scale
|
9
|
|
|
ro.setupwizard.mode
|
EMULATOR、ENABLED
|
|
|
ro.com.google.locationfeatures
|
1
|
|
|
ro.com.google.gmsversion
|
2.3_r7
|
|
|
init.svc.adbd,value
|
running
|
|
|
ro.qemu.init.completed
|
1
|
|
|
hw.keyboards.65536.devname
|
qwerty2
|
|
|
sys.settings_secure_version
|
2
|
|
|
dev.bootcomplete
|
1
|
|
|
sys.settings_system_version
|
6
|
|
|
gsm.sim.operator.numeric
|
|
|
|
gsm.sim.operator.alpha
|
|
|
|
gsm.sim.operator.iso-country
|
|
|
|
gsm.sim.state
|
UNKNOWN
|
|
|
adb.connected
|
1
|
|
设置和更改属性值的实现
-
Android系统在启动时加载根目录下的
init.rc,该脚本提供了setprop和getprop来设置和获取属性值的命令语法(参见Android Init Language)。
-
Android系统的init进程会开启property的服务,其他进程需要连接到该服务来改变属性值,而属性的读取可以由其他进程直接获取。这种方法采用典型的C/S模式,可参考以下代码。其中一些共用的库函数在system_properties.c中实现。
客户端 — properties.c
property_set
int property_set(const char *key, const char *value)
{
prop_msg msg;
unsigned resp;
if(key == 0) return -1;
if(value == 0) value = "";
if(strlen(key) >= PROP_NAME_MAX) return -1;
if(strlen(value) >= PROP_VALUE_MAX) return -1;
msg.cmd = PROP_MSG_SETPROP;
strcpy((char*) msg.name, key);
strcpy((char*) msg.value, value);
return send_prop_msg(&msg);
}
property_get
int property_get(const char *key, char *value, const char *default_value)
{
int len;
len = __system_property_get(key, value);
if(len > 0) {
return len;
}
if(default_value) {
len = strlen(default_value);
memcpy(value, default_value, len + 1);
}
return len;
}
服务端 — property_service.c
property_perms
// 可修改属性值的白名单列表
struct {
const char *prefix;
unsigned int uid;
unsigned int gid;
} property_perms[] = {
{ "net.rmnet0.", AID_RADIO, 0 },
{ "net.gprs.", AID_RADIO, 0 },
{ "net.ppp", AID_RADIO, 0 },
{ "ril.", AID_RADIO, 0 },
{ "gsm.", AID_RADIO, 0 },
{ "persist.radio", AID_RADIO, 0 },
{ "net.dns", AID_RADIO, 0 },
{ "net.", AID_SYSTEM, 0 },
{ "dev.", AID_SYSTEM, 0 },
{ "runtime.", AID_SYSTEM, 0 },
{ "hw.", AID_SYSTEM, 0 },
{ "sys.", AID_SYSTEM, 0 },
{ "service.", AID_SYSTEM, 0 },
{ "wlan.", AID_SYSTEM, 0 },
{ "dhcp.", AID_SYSTEM, 0 },
{ "dhcp.", AID_DHCP, 0 },
{ "vpn.", AID_SYSTEM, 0 },
{ "vpn.", AID_VPN, 0 },
{ "debug.", AID_SHELL, 0 },
{ "log.", AID_SHELL, 0 },
{ "service.adb.root", AID_SHELL, 0 },
{ "persist.sys.", AID_SYSTEM, 0 },
{ "persist.service.", AID_SYSTEM, 0 },
{ "persist.security.", AID_SYSTEM, 0 },
{ NULL, 0, 0 }
};
property_get
const char* property_get(const char *name)
{
prop_info *pi;
if(strlen(name) >= PROP_NAME_MAX) return 0;
pi = (prop_info*) __system_property_find(name);
if(pi != 0) {
return pi->value;
} else {
return 0;
}
}
property_set
int property_set(const char *name, const char *value)
{
prop_area *pa;
prop_info *pi;
int namelen = strlen(name);
int valuelen = strlen(value);
if(namelen >= PROP_NAME_MAX) return -1;
if(valuelen >= PROP_VALUE_MAX) return -1;
if(namelen < 1) return -1;
pi = (prop_info*) __system_property_find(name);
if(pi != 0) {
/* ro.* properties may NEVER be modified once set */
if(!strncmp(name, "ro.", 3)) return -1;
pa = __system_property_area__;
update_prop_info(pi, value, valuelen);
pa->serial++;
__futex_wake(&pa->serial, INT32_MAX);
} else {
pa = __system_property_area__;
if(pa->count == PA_COUNT_MAX) return -1;
pi = pa_info_array + pa->count;
pi->serial = (valuelen << 24);
memcpy(pi->name, name, namelen + 1);
memcpy(pi->value, value, valuelen + 1);
pa->toc[pa->count] =
(namelen << 24) | (((unsigned) pi) - ((unsigned) pa));
pa->count++;
pa->serial++;
__futex_wake(&pa->serial, INT32_MAX);
}
/* If name starts with "net." treat as a DNS property. */
if (strncmp("net.", name, strlen("net.")) == 0) {
if (strcmp("net.change", name) == 0) {
return 0;
}
/*
* The 'net.change' property is a special property used track when any
* 'net.*' property name is updated. It is _ONLY_ updated here. Its value
* contains the last updated 'net.*' property.
*/
property_set("net.change", name);
} else if (persistent_properties_loaded &&
strncmp("persist.", name, strlen("persist.")) == 0) {
/*
* Don't write properties to disk until after we have read all default properties
* to prevent them from being overwritten by default values.
*/
write_persistent_property(name, value);
}
property_changed(name, value);
return 0;
}
共用库 — system_properties.c
__system_properties_init
int __system_properties_init(void)
{
prop_area *pa;
int s, fd;
unsigned sz;
char *env;
if(__system_property_area__ != ((void*) &dummy_props)) {
return 0;
}
env = getenv("ANDROID_PROPERTY_WORKSPACE");
if (!env) {
return -1;
}
fd = atoi(env);
env = strchr(env, ',');
if (!env) {
return -1;
}
sz = atoi(env + 1);
pa = mmap(0, sz, PROT_READ, MAP_SHARED, fd, 0);
if(pa == MAP_FAILED) {
return -1;
}
if((pa->magic != PROP_AREA_MAGIC) || (pa->version != PROP_AREA_VERSION)) {
munmap(pa, sz);
return -1;
}
__system_property_area__ = pa;
return 0;
}
__system_property_find_nth
const prop_info *__system_property_find_nth(unsigned n)
{
prop_area *pa = __system_property_area__;
if(n >= pa->count) {
return 0;
} else {
return TOC_TO_INFO(pa, pa->toc[n]);
}
}
__system_property_find
const prop_info *__system_property_find(const char *name)
{
prop_area *pa = __system_property_area__;
unsigned count = pa->count;
unsigned *toc = pa->toc;
unsigned len = strlen(name);
prop_info *pi;
while(count--) {
unsigned entry = *toc++;
if(TOC_NAME_LEN(entry) != len) continue;
pi = TOC_TO_INFO(pa, entry);
if(memcmp(name, pi->name, len)) continue;
return pi;
}
return 0;
}
__system_property_read
int __system_property_read(const prop_info *pi, char *name, char *value)
{
unsigned serial, len;
for(;;) {
serial = pi->serial;
while(SERIAL_DIRTY(serial)) {
__futex_wait(&pi->serial, serial, 0);
serial = pi->serial;
}
len = SERIAL_VALUE_LEN(serial);
memcpy(value, pi->value, len + 1);
if(serial == pi->serial) {
if(name != 0) {
strcpy(name, pi->name);
}
return len;
}
}
}
__system_property_get
int __system_property_get(const char *name, char *value)
{
const prop_info *pi = __system_property_find(name);
if(pi != 0) {
return __system_property_read(pi, 0, value);
} else {
value[0] = 0;
return 0;
}
}
__system_property_wait
int __system_property_wait(const prop_info *pi)
{
unsigned n;
if(pi == 0) {
prop_area *pa = __system_property_area__;
n = pa->serial;
do {
__futex_wait(&pa->serial, n, 0);
} while(n == pa->serial);
} else {
n = pi->serial;
do {
__futex_wait(&pi->serial, n, 0);
} while(n == pi->serial);
}
return 0;
}