android property system

android property system

Property system is an important feature on android. It runs as a service and manages system configurations and status. All these configurations and status are properties. A property is a key/value pair, both of which are of string type.
From the sense of function, it's very similar to  windows registry. Many android applications and libraries directly or indirectly relies on this feature to determine their runtime behavior. For example, adbd process queries property service to check if it's running in emulator. Another example is the  java.io.File.pathSeparator returns the value stored in property service.

How property system works
The high level architecture of property system is shown as following.
android prop sys arch
In the figure, there are three processes, a group of persistent property files and a shared memory block. The shared memory block is the container of all property records. Only the property service process can write to the shared memory block. It'll load property records from persistent the save them in the shared memory.
The consumer process loads the shared memory in its own virtual space and access properties directly. The setter process also loads the shared memory in its virtual space, but it can't write to the memory directly. When the setter tries to add or update a property, it sends the property to property service via  unix domain socket. The property service will write the property to shared memory on behalf of the setter process, as well as to the persistent file.

Property service runs inside  init process. The init process first creates a shared memory region and stores a fd to the region. Then init process maps the region into its virtual space with  mmap with MAP_SHARED flag, as a result, any updates to this area can be seen by all processes. This fd and region size are saved in a environment variable named "ANDROID_PROPERTY_WORKSPACE". Any other processes like consumer and setter will use this environment variable to get the fd and size, so that they can mmap this region into its own virtual space. The layout of the shared memory is shown below.
androi prop mem layout
After that, init process will load properties from following files:
/default.prop
/system/build.prop
/system/default.prop
/data/local.prop

The next step is start property service. In this step, a unix domain socket server is created. This socket's pathname is "/dev/socket/property_service" which is well known to other client processes.
Finally, init process calls poll to wait for connect event on the socket.

On the consumer side, when it initializes libc(bionic/libc/bionic/libc_common.c __libc_init_common function). It will retrieve the fd and size from environment variable, and map the shared memory into its own space(bionic/libc/bionic/system_properties.c __system_properties_init function). After that, libcutils can read property just as normal memory for the consumer.

Currently, properties can't be removed. That's to say, once a property has been added, it can't be removed, neither can its key be changed.

How to get/set properties

There are three main means to get/set properies on android.

1. native code
When writing native applications, property_get and property_set APIs can be used to get/set properties. To use them, we need to include  cutils/properties.h and link against libcutils.

#define NX_LOGGER_DISABLED             "ro.nx.logger_disabled"
#define NX_LOGGER_SIZE                 "ro.nx.logger_size"
loggerDisabled = property_get_int32(NX_LOGGER_DISABLED, 0);
    if (property_get(NX_LOGGER_SIZE, loggerSize, "0") && loggerSize[0] != '0') {
        setenv("debug_log_size", loggerSize, 1);
    }

2. java code
Android also provides  System.getProperty and  System.setProperty functions in java library, our java application can use them to get/set properties.
But it's important to  note that although these java APIs are semantically equal to native version, java version store data in a totally different place. Actually, a hashtable is employed by dalvik VM to store properties. So, java properties are separated, it can't get or set native properties, and neither vice versa.

Update:  Andrew  mentioned that android.os.SystemProperties class can manipulate native properties, though it's intended for internal usage only. It calls through jni into native property library to get/set properties.

3. shell script
Android provides  getprop and  setprop command line tool to retrieve and update properties. They can be used in shell script. They are implemented on top of libcutils.

/default.prop
/system/build.prop
/system/default.prop
/data/local.prop 是怎么来的呢?
# A list of property assignments, like "key = value", with zero or more
# whitespace characters on either side of the '='.
PRODUCT_PROPERTY_OVERRIDES := \
    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PROPERTY_OVERRIDES))
.KATI_READONLY := PRODUCT_PROPERTY_OVERRIDES
PRODUCT_SHIPPING_API_LEVEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SHIPPING_API_LEVEL))
# A list of property assignments, like "key = value", with zero or more
# whitespace characters on either side of the '='.
# used for adding properties to default.prop
PRODUCT_DEFAULT_PROPERTY_OVERRIDES := \
    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
.KATI_READONLY := PRODUCT_DEFAULT_PROPERTY_OVERRIDES

PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
    ro.zygote=zygote32
PRODUCT_COPY_FILES += \
    system/core/rootdir/init.zygote32.rc:root/init.zygote32.rc

ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1
  ADDITIONAL_DEFAULT_PROPERTIES += security.perf_harden=1

ADDITIONAL_BUILD_PROPERTIES += $(PRODUCT_PROPERTY_OVERRIDES)

ro.hdmi.wake_on_hotplug=false \
   ro.zygote.disable_gl_preload=true \
   sys.display-size=1920x1080 \
   ro.nx.colordepth10b.force=1 \
   \
   ro.gfx.driver.0=gfxdriver-bcmstb \
   \
   ro.vendor.vndk.version=26.1.0

猜你喜欢

转载自blog.csdn.net/whuzm08/article/details/80495771