Android屬性:所設屬性值為何在重起後被清除

問題:發現adb sehll setProp所設屬性值在下次重起後被清除
adb shell setprop testing.mediascanner.skiplist /storage/sdcard1/test

結論:必須采用persist.開頭的屬性名才能永久保存。

On system initialization, Android will allocates a block of shared memory for storing the properties. This is done in “init” daemon whose sourcecode is at: device/system/init. The “init” daemon will start a PropertyService.
The Property Service is running in the process of “init”daemon. Every client that wants to SET property needs to connect to theProperty Service and send message to Property Service. Property Servicewill update/create the property in shared memory. Any client that wants to GET property can read the property from the shared memory directly.This promotes the read performance.
Java API:
import android.os.SystemProperties;
[javascript] view plaincopyprint?
public static String get(String key, String def) {} 
public static void set(String key, String val) {} 
The Native API:
[cpp] 
int property_get(const char *key, char *value, const char *default_value); 
 
int property_set(const char *key, const char *value); 

bionic/libc/include/sys/system_properties.h
[cpp] view plaincopyprint?
#define PROP_NAME_MAX   32 
#define PROP_VALUE_MAX  92 
以上定義可知屬性最大長度為32,屬性值最大長度92字節.

bionic/libc/include/sys/_system_properties.h
[cpp]
#define PROP_PATH_RAMDISK_DEFAULT  "/default.prop" 
#define PROP_PATH_SYSTEM_BUILD     "/system/build.prop" 
#define PROP_PATH_SYSTEM_DEFAULT   "/system/default.prop" 
#define PROP_PATH_LOCAL_OVERRIDE   "/data/local.prop" 

屬性服務啟動後會從系統文件中讀取默認的屬性,並寫入共享內存中,以下4個文件為按順序讀取:
 /default.prop
 /system/build.prop
 /system/default.prop
 /data/local.prop

後讀入的屬性將覆蓋前面讀取的相同的屬性。
system/core/init/property_service.c
[cpp] 
void start_property_service(void) 

    int fd; 
 
    load_properties_from_file(PROP_PATH_SYSTEM_BUILD); 
    load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT); 
#ifdef ALLOW_LOCAL_PROP_OVERRIDE 
    load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE); 
#endif /* ALLOW_LOCAL_PROP_OVERRIDE */ 
    /* Read persistent properties after all default values have been loaded. */ 
    load_persistent_properties(); 
 
    update_legacy_atvc_properties(); 

設置屬性,ro.開頭的屬性將不能被更改屬性值,persist.開頭的屬性會被永久紀錄,其他屬性值在重新開機後均將被丟棄:
[cpp] 
int property_set(const char *name, const char *value) 

    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; 
}  

當用戶設置屬性時,如果以屬性名字以persist.開頭,則會同時在/data/property目錄下創建以該屬性名字命名的文件,並寫入屬性值。

[cpp] 
#define PERSISTENT_PROPERTY_DIR  "/data/property" 
static void write_persistent_property(const char *name, const char *value) 

    const char *tempPath = PERSISTENT_PROPERTY_DIR "/.temp"; 
    char path[PATH_MAX]; 
    int fd, length; 
 
    snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name); 
 
    fd = open(tempPath, O_WRONLY|O_CREAT|O_TRUNC, 0600); 
    if (fd < 0) { 
        ERROR("Unable to write persistent property to temp file %s errno: %d\n", tempPath, errno); 
        return; 
    } 
    write(fd, value, strlen(value)); 
    close(fd); 
 
    if (rename(tempPath, path)) { 
        unlink(tempPath); 
        ERROR("Unable to rename persistent property file %s to %s\n", tempPath, path); 
    } 

加載永久屬性時,會讀入在目錄/data/property下所有名字以persist.開頭的文件內容,作為該名字對應的屬性值。

[cpp] 
static void load_persistent_properties() 

    DIR* dir = opendir(PERSISTENT_PROPERTY_DIR); 
… 
    if (dir) { www.aiwalls.com
        while ((entry = readdir(dir)) != NULL) { 
            if (strncmp("persist.", entry->d_name, strlen("persist."))) 
                continue; 

 

作者:cloudwu007

發佈留言