android系统启动时属性初始化过程
2012-04-13 13:46
344 查看
所有属性可以通过getprop获取到,以下是属性初始化过程:
在init.c文件main函数中会调用start_property_service(),而它分别调用 load_properties_from_file函数读取PROP_PATH_SYSTEM_BUILD(/system/build.prop)、 PROP_PATH_SYSTEM_DEFAULT(/system/default.prop)和 PROP_PATH_LOCAL_OVERRIDE(/data/local.prop)存放系统属性的文件并设置到系统属性。
编译时由build/tool/buildinfo.sh文件写到文件build.prop,修改系统默认属性一般是改build/tool/buildinfo.sh文件
=======================================================================
修改Settings源码可修改系统设置项,Settings数据被存放于com.android.providers.settings/databases/settings.db 中,如果想修改系统启动后加载的默认值
一种方法是直接修改settings.db的值
另一种就是修改SettingsProvider默认值
Settings应用能够配置Android系统的各种设置,这些设置的默认值都是由frameworks中的SettingsProvider从数据库中读取的,那么第一次开机的时候这些数据都是从哪儿来的呢?
frameworks/base/packages/SettingsProvider/res/values/defaults.xml这个文件就是用来存储Android系统的默认设置
例如:
<integer name="def_screen_off_timeout">600000</integer>设置关屏超时时间的默认值
<integer name="def_screen_brightness">102</integer> 设置亮度的默认值
<bool name="def_install_non_market_apps">false</bool>设置是否允许安装非Market应用程序的默认值
如果想定义defaults.xml中没有的,在这里添加后,需修改frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java,加入自己的存储代码。
来电铃声:SD卡ringtones文件下, 支持音频文件(MP3、wav、ogg等格式)。
通知铃声:SD卡notifications,支持音频文件(MP3、wav、ogg等格式)。
闹钟铃声:SD卡alarms,支持音频文件(MP3、wav、ogg等格式)。
附:系统自带铃声文件位置
来电铃声:/system/media/audio/ringtones
通知铃声:/system/media/audio/notifications
闹钟铃声:/system/media/audio/alarms
界面操作事件音:/system/media/audio/ui
==============================================================================================
每条属性包含了名字和其对应的值,两者都用字符串来描述。Android系统中大量的使用了属性系统用于记录系统的设置(注:和windows系统里的注册表类似),以及进程间的 信息交互。属性系统对于整个系统来说是全局的,也就是说每一个进程都可以获取和设置每条属性。
当系统初始化的时候,Android系统会分配一块共享内存用于存储属 性信息。这些操作是在"init"这个守护进程里完成的,其对应的源 代码目录在:device/system/init。"init"守护进程同时也启动了属性服务。属性
服务运行在init进程中(注:是线程?)。客户端需 要设置属性时,需要连接到属性服务上,同时发送消息给属性服务。这样属性服务就可以更新保存在共享内存中的属性信息。当客户端需要读取属性信息时,可以直 接访问共享内存,这样做可以提高性能。
客户端程序可以通过调用libcutils库里的API函数实现对属性的设置和读取的操作。
libcutils库对应的源代码存放在: device/libs/cutils。
这些API函数包括:
int property_get(const char *key, char *value, const char *default_value);
int property_set(const char *key, const char *value);
libcutils库是通过调用libc库中的__system_property_xxx这一系列函数实现从共享内存中获取 属性的。对应的libc的源代码保存在:
device/system/bionic。
属性服务也会调用libc库中的函数__system_property_init来实现对共享内存的初始化。当启动 属性服务时会通过下面文件来加载默认的属性信息。
/default.prop
/system/build.prop
/system/default.prop
/data/local.prop
属性信息按照上面的顺序被加载。后加载的属性会覆盖前面的属性值(注:当属性名称相同的时候)。当上面加载完成后,最后加载的是驻留属性,保存在/data/property文件中。
特别的属性
如果属性是有”ro.”字符串开头,那么这条属性被看成 一个只读属性,一旦设置就不能被修改了。(注:初始化设置的时候是可写的)
如果属性是有“persist.”字符串开头,那么就认为是驻留属 性,当修改的时候同时也会被保存在/data/property文件中。
如果属性是有“net.”字符串开头,当设
4000
置这种属性的时 候,“net.change”这条属性也会被自动设置,其内容 设为最后更新过的属性名。
属性“ctrl.start”和“ctrl.stop”用于启动和停止服务。这些服务必须在文件/init.rc中被定义。在系统启动的时候,init守护进程会解析init.rc文件,然后启动属性服务。一旦收到
了“ctrl.start”这个属性的设置请求,属性服务会 根据该属性的值作为服务名,在列表中找到服务对象并启动。服务启动的结果会反映在“init.svc.<service name>”这个属性之中。客户端程序可以轮 询该属性值来判断服务的启动结果。
Android 工具箱
Android 工具箱提供了2个应用程序:setprop
和 getprop用于读取和设置属性项目。使用方法是:
getprop <property name>
setprop <property name> <property value>
Java
Java程序可以通过使用函数System.getProperty()
和 System.setProperty()获取和设置属性条目。
动作
默认情况下设置属性只会触发init进程对共享内存进行操作,并不会执 行任何脚本和程序。但是你可以修改文件init.rc,这样在属性值发生变化的时候来触 发你定义的动作。例如在默认的init.rc文件中你可以找到下面这部分:
# adbd on at boot in emulator
on property:ro.kernel.qemu=1
start adbd
on property:persist.service.adb.enable=1
start adbd
on property:persist.service.adb.enable=0
stop adbd
所以当属性条目persist.service.adb.enable被设置成1的时候,init守护进程知道他需要启动adbd服务。
另一篇:
Android 的系统属性包括两部分:文件保存的持久属性和每次开机导入的cache属性。前者主要保存在下面几个文件中:
bionic / libc / include / sys / _system_properties.h
后者则通过frameworks/base/core/java/android/os/SystemProperties.java的接口定义,
该接口类在初始化运行环境中注册对应的cpp接口android_os_SystemProperties.cpp,实际操作通过JNI调用的是cpp文件对应的接口:
frameworks/base/core/jni/AndroidRuntime.cpp
frameworks/base/core/jni/android_os_SystemProperties.cpp
设置key的value时,需要作鉴权,根据设置程序所在进程的fd获知uid值,比如system server进程可以设置net打头的key,不可以设置gsm打头的key,相关的定义如下:
system/core/include/private/android_filesystem_config.h
system/core/init/property_service.c
在开机启动后的init操作中,会执行一个loop循环,当检测到有新的设置时,进入设置流程,鉴权失败会提示相关的异常,如sys_prop: permission denied uid:1000 name:gsm.phone.id
system/core/init/init.c
OVER!
在init.c文件main函数中会调用start_property_service(),而它分别调用 load_properties_from_file函数读取PROP_PATH_SYSTEM_BUILD(/system/build.prop)、 PROP_PATH_SYSTEM_DEFAULT(/system/default.prop)和 PROP_PATH_LOCAL_OVERRIDE(/data/local.prop)存放系统属性的文件并设置到系统属性。
编译时由build/tool/buildinfo.sh文件写到文件build.prop,修改系统默认属性一般是改build/tool/buildinfo.sh文件
=======================================================================
修改Settings源码可修改系统设置项,Settings数据被存放于com.android.providers.settings/databases/settings.db 中,如果想修改系统启动后加载的默认值
一种方法是直接修改settings.db的值
另一种就是修改SettingsProvider默认值
Settings应用能够配置Android系统的各种设置,这些设置的默认值都是由frameworks中的SettingsProvider从数据库中读取的,那么第一次开机的时候这些数据都是从哪儿来的呢?
frameworks/base/packages/SettingsProvider/res/values/defaults.xml这个文件就是用来存储Android系统的默认设置
例如:
<integer name="def_screen_off_timeout">600000</integer>设置关屏超时时间的默认值
<integer name="def_screen_brightness">102</integer> 设置亮度的默认值
<bool name="def_install_non_market_apps">false</bool>设置是否允许安装非Market应用程序的默认值
如果想定义defaults.xml中没有的,在这里添加后,需修改frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java,加入自己的存储代码。
来电铃声:SD卡ringtones文件下, 支持音频文件(MP3、wav、ogg等格式)。
通知铃声:SD卡notifications,支持音频文件(MP3、wav、ogg等格式)。
闹钟铃声:SD卡alarms,支持音频文件(MP3、wav、ogg等格式)。
附:系统自带铃声文件位置
来电铃声:/system/media/audio/ringtones
通知铃声:/system/media/audio/notifications
闹钟铃声:/system/media/audio/alarms
界面操作事件音:/system/media/audio/ui
==============================================================================================
每条属性包含了名字和其对应的值,两者都用字符串来描述。Android系统中大量的使用了属性系统用于记录系统的设置(注:和windows系统里的注册表类似),以及进程间的 信息交互。属性系统对于整个系统来说是全局的,也就是说每一个进程都可以获取和设置每条属性。
当系统初始化的时候,Android系统会分配一块共享内存用于存储属 性信息。这些操作是在"init"这个守护进程里完成的,其对应的源 代码目录在:device/system/init。"init"守护进程同时也启动了属性服务。属性
服务运行在init进程中(注:是线程?)。客户端需 要设置属性时,需要连接到属性服务上,同时发送消息给属性服务。这样属性服务就可以更新保存在共享内存中的属性信息。当客户端需要读取属性信息时,可以直 接访问共享内存,这样做可以提高性能。
客户端程序可以通过调用libcutils库里的API函数实现对属性的设置和读取的操作。
libcutils库对应的源代码存放在: device/libs/cutils。
这些API函数包括:
int property_get(const char *key, char *value, const char *default_value);
int property_set(const char *key, const char *value);
libcutils库是通过调用libc库中的__system_property_xxx这一系列函数实现从共享内存中获取 属性的。对应的libc的源代码保存在:
device/system/bionic。
属性服务也会调用libc库中的函数__system_property_init来实现对共享内存的初始化。当启动 属性服务时会通过下面文件来加载默认的属性信息。
/default.prop
/system/build.prop
/system/default.prop
/data/local.prop
属性信息按照上面的顺序被加载。后加载的属性会覆盖前面的属性值(注:当属性名称相同的时候)。当上面加载完成后,最后加载的是驻留属性,保存在/data/property文件中。
特别的属性
如果属性是有”ro.”字符串开头,那么这条属性被看成 一个只读属性,一旦设置就不能被修改了。(注:初始化设置的时候是可写的)
如果属性是有“persist.”字符串开头,那么就认为是驻留属 性,当修改的时候同时也会被保存在/data/property文件中。
如果属性是有“net.”字符串开头,当设
4000
置这种属性的时 候,“net.change”这条属性也会被自动设置,其内容 设为最后更新过的属性名。
属性“ctrl.start”和“ctrl.stop”用于启动和停止服务。这些服务必须在文件/init.rc中被定义。在系统启动的时候,init守护进程会解析init.rc文件,然后启动属性服务。一旦收到
了“ctrl.start”这个属性的设置请求,属性服务会 根据该属性的值作为服务名,在列表中找到服务对象并启动。服务启动的结果会反映在“init.svc.<service name>”这个属性之中。客户端程序可以轮 询该属性值来判断服务的启动结果。
Android 工具箱
Android 工具箱提供了2个应用程序:setprop
和 getprop用于读取和设置属性项目。使用方法是:
getprop <property name>
setprop <property name> <property value>
Java
Java程序可以通过使用函数System.getProperty()
和 System.setProperty()获取和设置属性条目。
动作
默认情况下设置属性只会触发init进程对共享内存进行操作,并不会执 行任何脚本和程序。但是你可以修改文件init.rc,这样在属性值发生变化的时候来触 发你定义的动作。例如在默认的init.rc文件中你可以找到下面这部分:
# adbd on at boot in emulator
on property:ro.kernel.qemu=1
start adbd
on property:persist.service.adb.enable=1
start adbd
on property:persist.service.adb.enable=0
stop adbd
所以当属性条目persist.service.adb.enable被设置成1的时候,init守护进程知道他需要启动adbd服务。
另一篇:
Android 的系统属性包括两部分:文件保存的持久属性和每次开机导入的cache属性。前者主要保存在下面几个文件中:
bionic / libc / include / sys / _system_properties.h
1 2 3 4 5 | #define PROP_SERVICE_NAME "property_service" #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" |
1 2 3 4 56 | private static native String native_get(String key); private static native String native_get(String key, String def); private static native void native_set(String key, String def); public static void set(String key, String val) { if (key.length() > PROP_NAME_MAX) { throw new IllegalArgumentException( " key.length > " + PROP_NAME_MAX); } if (val != null && val.length() > PROP_VALUE_MAX) { throw new IllegalArgumentException( " val.length > " + PROP_VALUE_MAX); } native_set(key, val); } |
frameworks/base/core/jni/AndroidRuntime.cpp
1 2 3 | namespace android { extern int register_android_os_SystemProperties(JNIEnv * env); } |
1 2 3 4 56 | static void SystemProperties_set(JNIEnv * env, jobject clazz, jstring keyJ, jstring valJ) { int err; const char * key; const char * val; key = env -> GetStringUTFChars(keyJ, NULL); if (valJ == NULL) { val = "" ; /* NULL pointer not allowed here */ } else { val = env -> GetStringUTFChars(valJ, NULL); } err = property_set(key, val); env -> ReleaseStringUTFChars(keyJ, key); if (valJ != NULL) { env -> ReleaseStringUTFChars(valJ, val); } } |
system/core/include/private/android_filesystem_config.h
1 2 3 4 56 | #define AID_ROOT 0 /* traditional unix root user */ #define AID_SYSTEM 1000 /* system server */ #define AID_RADIO 1001 /* telephony subsystem, RIL */ #define AID_DHCP 1014 /* dhcp client */ #define AID_SHELL 2000 /* adb and debug shell user */ #define AID_CACHE 2001 /* cache access */ #define AID_APP 10000 /* first app user */ |
1 2 3 4 56 | #define PERSISTENT_PROPERTY_DIR "/data/property" struct { const char * prefix; unsigned int uid; } property_perms[] = { { " net.rmnet0. " , AID_RADIO }, { " net.gprs. " , AID_RADIO }, { " ril. " , AID_RADIO }, { " gsm. " , AID_RADIO }, { " net.dns " , AID_RADIO }, { " net.usb0 " , AID_RADIO }, { " net. " , AID_SYSTEM }, { " dev. " , AID_SYSTEM }, { " runtime. " , AID_SYSTEM }, { " hw. " , AID_SYSTEM }, { " sys. " , AID_SYSTEM }, { " service. " , AID_SYSTE da82 M }, { " wlan. " , AID_SYSTEM }, { " dhcp. " , AID_SYSTEM }, { " dhcp. " , AID_DHCP }, { " debug. " , AID_SHELL }, { " log. " , AID_SHELL }, { " service.adb.root " , AID_SHELL }, { " persist.sys. " , AID_SYSTEM }, { " persist.service. " , AID_SYSTEM }, { NULL, 0 } }; int property_set( const char * name, const char * value) { property_changed(name, value); return 0 ; } int start_property_service( void ) { int fd; load_properties_from_file(PROP_PATH_SYSTEM_BUILD); load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT); load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE); /* Read persistent properties after all default values have been loaded. */ load_persistent_properties(); fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666 , 0 , 0 ); if (fd < 0 ) return - 1 ; fcntl(fd, F_SETFD, FD_CLOEXEC); fcntl(fd, F_SETFL, O_NONBLOCK); listen(fd, 8 ); return fd; } void handle_property_set_fd( int fd) { switch (msg.cmd) { case PROP_MSG_SETPROP: msg.name[PROP_NAME_MAX - 1 ] = 0 ; msg.value[PROP_VALUE_MAX - 1 ] = 0 ; if (memcmp(msg.name, " ctl. " , 4 ) == 0 ) { if (check_control_perms(msg.value, cr.uid)) { handle_control_message(( char * ) msg.name + 4 , ( char * ) msg.value); } else { ERROR( " sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n " , msg.name + 4 , msg.value, cr.uid, cr.pid); } } else { if (check_perms(msg.name, cr.uid)) { property_set(( char * ) msg.name, ( char * ) msg.value); } else { ERROR( " sys_prop: permission denied uid:%d name:%s\n " , cr.uid, msg.name); } } break ; default : break ; } } |
system/core/init/init.c
1 2 3 4 56 | void property_changed( const char * name, const char * value) { if (property_triggers_enabled) { queue_property_triggers(name, value); drain_action_queue(); } } int main( int argc, char ** argv) { parse_config_file( " /init.rc " ); qemu_init(); device_fd = device_init(); property_init(); fd = open(console_name, O_RDWR); property_set_fd = start_property_service(); ufds[ 0 ].fd = device_fd; ufds[ 0 ].events = POLLIN; ufds[ 1 ].fd = property_set_fd; ufds[ 1 ].events = POLLIN; ufds[ 2 ].fd = signal_recv_fd; ufds[ 2 ].events = POLLIN; fd_count = 3 ; for (;;) { if (ufds[ 0 ].revents == POLLIN) handle_device_fd(device_fd); if (ufds[ 1 ].revents == POLLIN) handle_property_set_fd(property_set_fd); if (ufds[ 3 ].revents == POLLIN) handle_keychord(keychord_fd); } return 0 ; } |
相关文章推荐
- android系统启动时属性(getprop得到的属性)写入过程
- android系统启动时属性(getprop得到的属性)写入过程
- Android系统默认Home应用程序(Launcher)的启动过程源代码分析(5)
- Android系统Surface机制的SurfaceFlinger服务的启动过程分析 JellyBean
- Android系统启动过程---uboot,kernel,android
- [android源码分析]bluez启动过程中的各种plugin的初始化(一)--__bluetooth_builtin数组所耍的花样
- Android系统Recovery工作原理之使用update.zip升级过程分析(三)---Android系统的三种启动模式
- Android系统Home应用程序(Launcher)的启动过程源代码分析
- Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析
- Android编译系统之环境初始化过程分析
- android系统启动过程分析
- Android系统在新进程中启动自定义服务过程(startService)的原理分析
- linux 内核启动过程以及挂载android 根文件系统的过程
- Android开发——Android系统启动以及APK安装、启动过程
- Android编译系统环境初始化过程分析
- Android系统进程Zygote启动过程的源代码分析
- (转)Android系统启动过程
- Android系统启动流程(二)解析Zygote进程启动过程
- 学习Android系统(kitkat)进程Zygote启动过程
- Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析