系统属性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.<服务名>“属性中 。客户端应用程序可以轮询那个属性值,以确定结果。  

如何编译属性信息

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  

设置和更改属性值的实现

客户端 — 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;
}