在使用Android的属性系统(property system)时遇到了一些问题,结合此次经历,对属性系统的使用做以简单介绍。

一、Property系统简介

属性系统是android的一个重要特性。它作为一个服务运行,管理系统配置和状态。所有这些配置和状态都是属性。每个属性是一个键值对(key/value pair),其类型都是字符串。

从功能上看,属性与windows系统的注册表非常相似。许多android应用程序和库直接或者间接地依赖此特性,以决定它们的运行时行为。例如,adbd进程查询属性服务已确认当前是否运行在模拟器环境中。另一个例子是java.io.File.pathSpearator,其返回存储于属性服务中的值。

二、Property系统使用

使用property系统,首先需要包含头文件<cutils/properties.h>,同时需要在Android.mk文件中加入库libcutils。

具体的使用实例如下:

property_set("hw.jpeg.path", "/data/test.jpg");
    char propBuf[PROPERTY_VALUE_MAX];  
    property_get("hw.jpeg.path ", propBuf, ""); 
    LOGI("property_get: %s.", propBuf);

Property系统的使用很简单,这里需要说明的,只有一个问题,那就是属性名称。

三、Property系统的属性名称

Property系统中使用的属性名称有一定的命名规则。

如果属性名称以“ro.”开头,那么这个属性被视为只读属性。一旦设置,属性值不能改变。

如果属性名称以“persist.”开头,当设置这个属性时,其值也将写入/data/property。

如果属性名称以“net.”开头,当设置这个属性时,“net.change”属性将会自动设置,以加入到最后修改的属性名。(这是很巧妙的。 netresolve模块的使用这个属性来追踪在net.*属性上的任何变化。)

属性“ ctrl.start ”和“ ctrl.stop ”是用来启动和停止服务。每一项服务必须在/init.rc中定义.系统启动时,与init守护进程将解析init.rc和启动属性服务。一旦收到设置“ ctrl.start ”属性的请求,属性服务将使用该属性值作为服务名找到该服务,启动该服务。这项服务的启动结果将会放入“ init.svc.<服务名>“属性中 。客户端应用程序可以轮询那个属性值,以确定结果。

另外,还有其他的前缀;在介绍这些前缀之前,我们先来看点别的东西。

在文件system/core/init/property_service.h中,有如下两个函数定义:

extern void handle_property_set_fd(int fd);

extern int property_set(const char *name, const char *value);

它们的实现都位于system/core/init/property_service.c。

另外在system/core/init/init.c中,有如下code:

int main(int argc, char **argv)

{

……

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

}

……

}

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

sys_prop: permission denied uid:1013  name:hw.jpeg.path

这里得介绍一下函数handle_property_set_fd(),其实现为:

void handle_property_set_fd(int fd)

{

prop_msg msg;

……

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, cr.gid)) {

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, cr.gid)) {

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;

}

}

其中check_perms()的实现如下:

static int check_perms(const char *name, unsigned int uid, int gid)

{

int i;

if (uid == 0)

return 1;

if(!strncmp(name, "ro.", 3))

name +=3;

for (i = 0; property_perms[i].prefix; i++) {

int tmp;

if (strncmp(property_perms[i].prefix, name,

strlen(property_perms[i].prefix)) == 0) {

if ((uid && property_perms[i].uid == uid) ||

(gid && property_perms[i].gid == gid)) {

return 1;

}

}

}

return 0;

}

通过这两个函数,我们可以知道,我们所设置的属性名称hw.jpeg.path会与结构体property_perms中的前缀做比较,如果满足,则又会比较uid。

结构体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 }

};

此时,我们就知道hw.在property_perms中是存在的,那么uid是否能匹配呢?我们看到hw.对应的uid为AID_SYSTEM。

AID_SYSTEM的定义位于:

system/core/include/private/android_filesystem_config.h

#define AID_SYSTEM        1000  /* system server */

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

#define AID_DHCP          1014  /* dhcp client */

#define AID_VPN           1016  /* vpn system */

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

当我们使用属性名称为hw.jpeg.path时,那我们的应用程序的uid必须为1000,否则在函数handle_property_set_fd()中就会报出类似这样的错误:

sys_prop: permission denied uid:1013  name:hw.jpeg.path

四、使应用程序具有AID_SYSTEM的UID

那如何使应用程序的uid变为1000呢?

由于我可以在Android系统源码的环境下用make来编译,所以需要做如下几步:

l  在应用程序的AndroidManifest.xml文件中的manifest节点中加入属性:

android:sharedUserId="android.uid.system";

通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。那么把程序的UID配成android.uid.system,也就是要让程序运行在系统进程中,这样就有权限来设置前缀为hw.的属性了。

l  修改Android.mk文件,加入LOCAL_CERTIFICATE := platform;

加入UID还不够,如果这时候安装APK的话发现无法安装,提示签名不符,原因是程序想要运行在系统进程中还要有目标系统的platform. key,就是platform.pk8和platform.x509.pem两个文件。通过这样的设置,系统才可以拿到platform.pk8和platform.x509.pem两个文件。使用这两个key签名后apk才真正可以放入系统进程中。

然后使用mm命令来编译,生成的apk的uid就会成为1000。在去调用

property_set("hw.jpeg.path", "/data/test.jpg");就不会有问题了。

另外需要说明的是,property_get()函数的使用是没有这样的限制的。

如果需要深入地了解property系统,可以参考如下文章:

Android Property System | Android属性系统

http://blog.csdn.net/jackyu613/archive/2011/01/13/6136620.aspx

Android 的属性系统(翻译)

http://blog.csdn.net/tekkamanitachi/archive/2009/06/18/4280982.aspx

Android Property System | Android属性系统

http://www.bangchui.org/read.php?tid=13375

Android中如何修改系统时间(应用程序获得系统权限)

http://dev.10086.cn/blog/?uid-49302-action-viewspace-itemid-907

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

http://blog.csdn.net/netpirate/archive/2009/11/11/4799272.aspx

E-mail:wxiaozhe@163.com

QQ:1226062415
Date:2011/5/14
Blog:http://blog.csdn.net/wxzking

欢迎交流,欢迎转载,转载时请保留以上信息。

Android平台上使用属性系统(property system)相关推荐

  1. android 身份认证技术,Android平台上基于人脸识别的身份认证系统的设计与实现

    摘要: 随着移动互联网与人工智能技术的发展,基于个人特征的生物识别技术代替传统的身份验证方式已经是大势所趋.而人脸识别是生物识别技术的一个重要组成部分,拥有其他生物识别技术没有的独特优势.本文主要针对 ...

  2. 在 Android* 平台上设置原生 OpenGL ES*

    Setting up Native OpenGL ES* on Android* Platforms final.docx BSD2.0.txt ParticleSystemNDK.zip READM ...

  3. cocos2d js调用java_【cocos2d-js官方文档】二十四、如何在android平台上使用js直接调用Java方法...

    在cocos2d-js 3.0beta中加入了一个新特性,在android平台上我们可以通过反射直接在js中调用java的静态方法.它的使用方法很简单: var o = jsb.reflection. ...

  4. (转) Android平台上关于IM的实践总结

    前言 IM通信在互联网发展到现在已经是码农的世界里人尽皆知的技术,特别在当下移动互联网迅猛发展的时代这种技术的开发也更加火热,其中老牌的代表作就有QQ和MSN,和最近新崛起的微信,默默,易信,来往等眼 ...

  5. 在Android平台上发现新的恶意程序伪装成杀毒软件挟持设备

    Android平台恶意程序:不支付$100隐私就泄漏]6月25日消息,安全公司赛门铁克发布报告,在Android平台上发现新的恶意程序伪装成杀毒软件挟持设备,消费者支付$100才能让设备正常运作.这些 ...

  6. 基于Android的记账APP论文,基于Android平台的手机记账系统的设计与实现

    摘要: 在经济社会中,"理财"一词对于人们来说已不再陌生.人们的生活收入稳步上升,用于工作,住房,休闲娱乐的财务支出增多,做好详细的收支计划,将有利于对个人,家庭的经济收入,支出状 ...

  7. Rockchip Android平台内存优化及系统裁剪

    Rockchip Android平台内存优化及系统裁剪 文章目录 Rockchip Android平台内存优化及系统裁剪 编译32bit的Android系统 启用Android GO的配置 系统裁剪 ...

  8. cocos2dx在Android studio运行 以及在 Android 平台上使用 JavaScript 直接调用 Java 方法

    cocos2dx在Android studio运行 以及在 Android 平台上使用 JavaScript 直接调用 Java 方法 cocos2dx在Android studio运行 使用Andr ...

  9. Android平台上集成海康SDK(二)

    Android平台上集成海康SDK 以上是我之前写的一篇Android平台上集成海康SDK的文章,其中对于Android平台上集成海康SDK.基于海康SDK进行二次开发基本上进行了详细地介绍. 这篇文 ...

最新文章

  1. 潮州市云计算数据中心挂牌 粤东地区规模最大
  2. Oracle的使用和Oracle安装过程
  3. python和R数据类型查看、赋值、列表、for循环、函数用法对比示例
  4. 【Dual-Path-RNN-Pytorch源码分析】AudioReader
  5. SQL Server 2008创建数据库
  6. php yii没有数据库吗,php – YII活动记录未插入数据库但未给出错误
  7. 智能判断图片中是否存在某物体_智能家居组件漫谈——人体传感器
  8. Fiddler 抓包详细使用教程
  9. 晋中计算机专业对口大学,山西晋中计算机专业好就业吗?,计算机专业
  10. 第一节:别出心裁的HTML5简介
  11. java占32位存储空间时,java空间
  12. [导入]8.3赛车频道活动
  13. 大学生 计算机 毕业设计 xx管理系统 毕设(1)
  14. 数字图像处理之数字图像频率空间
  15. ScienceWord控件问题以及IE8对于base64编码图片长度限制的解决方案
  16. 摸索Detours 3:使用Detours 采用dll 方式进行Hook
  17. 自监督学习(Self-supervised Learning)的深刻理解
  18. (华为)802.1x认证点部署在汇聚交换机,接入交换机管理地址免认证配置
  19. 远程连接mscs下oracle,MSCS+FailSafe ORACLE数据库双机集群做HA小结
  20. python 以图搜图百度_基于opencv的图片检索(模仿百度的以图搜图功能)

热门文章

  1. 什么叫预判_什么才是真正的用户画像?
  2. android 定时查询,android – 如何检查计时器是否仍在运行?
  3. exsi vmfs 没了_它是“推粪机”,隔三差五吃一盘,口臭没了排出宿便,肠道变干净...
  4. Hive DDL操作
  5. springcloud @EnableDiscoveryClient注解作用
  6. 十四、中文词向量训练一
  7. java记事本技术参数_[源码和文档分享]基于JAVA的记事本
  8. linux suse 安装redis,在openSuse linux上Redis安装简单步骤
  9. bootstrap学习(三)表单
  10. [PHP] 近期接手現有的企邮前端框架业务所遇困难