现在的位置: 首页 > 综合 > 正文

Android 的系统属性(SystemProperties)设置分析

2012年12月04日 ⁄ 综合 ⁄ 共 6717字 ⁄ 字号 评论关闭

作者:徐建祥(netpirate@gmail.com)

日期:2009/11/11

网址:http://www.anymobile.org

Android 的系统属性包括两部分:文件保存的持久属性和每次开机导入的cache属性。前者主要保存在下面几个文件中:

bionic
/
libc
/
include
/
sys
/
_system_properties.h

1
   
#define
 PROP_SERVICE_NAME "property_service"


2
    
#define
 PROP_PATH_RAMDISK_DEFAULT  "/default.prop"


3
    
#define
 PROP_PATH_SYSTEM_BUILD     "/system/build.prop"


4
    
#define
 PROP_PATH_SYSTEM_DEFAULT   "/system/default.prop"


5
    
#define
 PROP_PATH_LOCAL_OVERRIDE   "/data/local.prop"


后者则通过frameworks/base/core/java/android/os/SystemProperties.java的接口定义,

 1
     
private
 
static
 
native
 String native_get(String key);

 2
     
private
 
static
 
native
 String native_get(String key, String def);

 3
     
private
 
static
 
native
 
void
 native_set(String key, String def);

 4
     
public
 
static
 
void
 set(String key, String val) {

 5
         
if
 (key.length() 
>
 PROP_NAME_MAX) {

 6
             
throw
 
new
 IllegalArgumentException(
"
key.length > 
"
 
+
 PROP_NAME_MAX);

 7
         }

 8
         
if
 (val 
!=
 
null
 
&&
 val.length() 
>
 PROP_VALUE_MAX) {

 9
             
throw
 
new
 IllegalArgumentException(
"
val.length > 
"
 
+


10
                 PROP_VALUE_MAX);

11
         }

12
         native_set(key, val);

13
     }


该接口类在初始化运行环境中注册对应的cpp接口android_os_SystemProperties.cpp,实际操作通过JNI调用的是cpp文件对应的接口:

frameworks/base/core/jni/AndroidRuntime.cpp

1
     
namespace
 android {

2
     
extern
 
int
 register_android_os_SystemProperties(JNIEnv 
*
env);

3
     }


frameworks/base/core/jni/android_os_SystemProperties.cpp

 1
     
static
 
void
 SystemProperties_set(JNIEnv 
*
env, jobject clazz, jstring keyJ, jstring valJ)

 2
     {

 3
         
int
 err;

 4
         
const
 
char
*
 key;

 5
         
const
 
char
*
 val;

 6
         key 
=
 env
->
GetStringUTFChars(keyJ, NULL);

 7
         
if
 (valJ 
==
 NULL) {

 8
             val 
=
 
""
;       
/*
 NULL pointer not allowed here 
*/


 9
         } 
else
 {

10
             val 
=
 env
->
GetStringUTFChars(valJ, NULL);

11
         }

12
         err 
=
 property_set(key, val);

13
         env
->
ReleaseStringUTFChars(keyJ, key);        

14
         
if
 (valJ 
!=
 NULL) {

15
             env
->
ReleaseStringUTFChars(valJ, val);

16
         }

17
     }


设置key的value时,需要作鉴权,根据设置程序所在进程的fd获知uid值,比如system server进程可以设置net打头的key,不可以设置gsm打头的key,相关的定义如下:

system/core/include/private/android_filesystem_config.h

1
     
#define
 AID_ROOT             0  /* traditional unix root user */


2
     
#define
 AID_SYSTEM        1000  /* system server */


3
     
#define
 AID_RADIO         1001  /* telephony subsystem, RIL */


4
     
#define
 AID_DHCP          1014  /* dhcp client */


5
     
#define
 AID_SHELL         2000  /* adb and debug shell user */


6
     
#define
 AID_CACHE         2001  /* cache access */


7
     
#define
 AID_APP          10000 /* first app user */


system/core/init/property_service.c

 1
     
#define
 PERSISTENT_PROPERTY_DIR  "/data/property"


 2
     
struct
 {

 3
         
const
 
char
 
*
prefix;

 4
         unsigned 
int
 uid;

 5
     } property_perms[] 
=
 {

 6
         { 
"
net.rmnet0.
"
,    AID_RADIO },

 7
         { 
"
net.gprs.
"
,      AID_RADIO },

 8
         { 
"
ril.
"
,           AID_RADIO },

 9
         { 
"
gsm.
"
,           AID_RADIO },

10
         { 
"
net.dns
"
,        AID_RADIO },

11
         { 
"
net.usb0
"
,       AID_RADIO },

12
         { 
"
net.
"
,           AID_SYSTEM },

13
         { 
"
dev.
"
,           AID_SYSTEM },

14
         { 
"
runtime.
"
,       AID_SYSTEM },

15
         { 
"
hw.
"
,            AID_SYSTEM },

16
         { 
"
sys.
"
,        AID_SYSTEM },

17
         { 
"
service.
"
,    AID_SYSTEM },

18
         { 
"
wlan.
"
,        AID_SYSTEM },

19
         { 
"
dhcp.
"
,        AID_SYSTEM },

20
         { 
"
dhcp.
"
,        AID_DHCP },

21
         { 
"
debug.
"
,        AID_SHELL },

22
         { 
"
log.
"
,        AID_SHELL },

23
         { 
"
service.adb.root
"
,    AID_SHELL },

24
         { 
"
persist.sys.
"
,    AID_SYSTEM },

25
         { 
"
persist.service.
"
,   AID_SYSTEM },

26
         { NULL, 
0
 }

27
     };

28
     
int
 property_set(
const
 
char
 
*
name, 
const
 
char
 
*
value)

29
     {

30
         property_changed(name, value);

31
         
return
 
0
;

32
     }

33
     
int
 start_property_service(
void
)

34
     {

35
         
int
 fd;

36
 

37
         load_properties_from_file(PROP_PATH_SYSTEM_BUILD);

38
         load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT);

39
         load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE);

40
         
/*
 Read persistent properties after all default values have been loaded. 
*/


41
         load_persistent_properties();

42
 

43
         fd 
=
 create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 
0666

0

0
);

44
         
if
(fd 
<
 
0

return
 
-
1
;

45
         fcntl(fd, F_SETFD, FD_CLOEXEC);

46
         fcntl(fd, F_SETFL, O_NONBLOCK);

47
 

48
         listen(fd, 
8
);

49
         
return
 fd;

50
     }

51
     
void
 handle_property_set_fd(
int
 fd)

52
     {

53
         
switch
(msg.cmd) {

54
         
case
 PROP_MSG_SETPROP:

55
             msg.name[PROP_NAME_MAX
-
1

=
 
0
;

56
             msg.value[PROP_VALUE_MAX
-
1

=
 
0
;

57
 

58
             
if
(memcmp(msg.name,
"
ctl.
"
,
4

==
 
0
) {

59
                 
if
 (check_control_perms(msg.value, cr.uid)) {

60
                     handle_control_message((
char
*
) msg.name 
+
 
4
, (
char
*
) msg.value);

61
                 } 
else
 {

62
                     ERROR(
"
sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d/n
"
,

63
                             msg.name 
+
 
4
, msg.value, cr.uid, cr.pid);

64
                 }

65
             } 
else
 {

66
                 
if
 (check_perms(msg.name, cr.uid)) {

67
                     property_set((
char
*
) msg.name, (
char
*
) msg.value);

68
                 } 
else
 {

69
                     ERROR(
"
sys_prop: permission denied uid:%d  name:%s/n
"
,

70
                           cr.uid, msg.name);

71
                 }

72
             }

73
             
break
;

74
 

75
         
default
:

76
             
break
;

77
         }

78
     }


在开机启动后的init操作中,会执行一个loop循环,当检测到有新的设置时,进入设置流程,鉴权失败会提示相关的异常,如sys_prop: permission denied uid:1000  name:gsm.phone.id

system/core/init/init.c

 1
     
void
 property_changed(
const
 
char
 
*
name, 
const
 
char
 
*
value)

 2
     {

 3
         
if
 (property_triggers_enabled) {

 4
             queue_property_triggers(name, value);

 5
             drain_action_queue();

 6
         }

 7
     }

 8
     
int
 main(
int
 argc, 
char
 
**
argv)

 9
     {

10
         parse_config_file(
"
/init.rc
"
);

11
         qemu_init();

12
         device_fd 
=
 device_init();

13
         property_init();

14
         fd 
=
 open(console_name, O_RDWR);

15
         property_set_fd 
=
 start_property_service();

16
         ufds[
0
].fd 
=
 device_fd;

17
         ufds[
0
].events 
=
 POLLIN;

18
         ufds[
1
].fd 
=
 property_set_fd;

19
         ufds[
1
].events 
=
 POLLIN;

20
         ufds[
2
].fd 
=
 signal_recv_fd;

21
         ufds[
2
].events 
=
 POLLIN;

22
         fd_count 
=
 
3
;

23
         
for
(;;) {

24
             
if
 (ufds[
0
].revents 
==
 POLLIN)

25
                 handle_device_fd(device_fd);

26
 

27
             
if
 (ufds[
1
].revents 
==
 POLLIN)

28
                 handle_property_set_fd(property_set_fd);

29
             
if
 (ufds[
3
].revents 
==
 POLLIN)

30
                 handle_keychord(keychord_fd);

31
         }

32
         
return
 
0
;

33
     }


OVER!

抱歉!评论已关闭.