当前位置:首页 > IT技术 > 移动平台 > 正文

Android原生Property移植记录
2021-11-16 11:38:04


Android原生Property移植记录_客户端



简介

属性系统是Android的一个重要特性,属性由属性名称和键值组成的一段字符串,又称键值对,用于记录系统设置或进程信息交换。属性在整个系统全局可见,每个进程可通过property_get/property_set获取和设置属性。本篇主要介绍移植版本的Property大致流程。

Property机制主要由服务端进程与客户端进程组成。property服务端进程用于初始化存储属性的共享空间、监听客户端请求、增加属性键值对和更新属性对应键值等功能。客户端为使用Property的应用进程,主要通过调用poperty_set和property_get集来实现设置和获取属性键值。

移植版本Property与Android原生Property使用方法有一些区别:

(1) Android是在init进程初始化Property服务端。移植版本则将Property服务端设计为独立进程,在开机启动时启用Property服务。如此设计的优点在于,将Property服务设计为独立的模块,便于各个应用移植和使用。

(2) Android在使用Property机制时会核对使用进程Selinux权限,在进程使用property_set/property_get时,会先审核使用进程是否拥有访问该属性权限。移植版本Property则省去Selinux权限。

(3) 移植版本Property是在Android KitKat4.4基础上移植而来,其内部实现细节可能与4.4版本之后有所出入。

API介绍

服务端:

本部分代码接口无需特殊关注,只需将编译的bin文件(Property_service)放入起始服务后台运行即可。Property服务端代码执行顺序需优先于客户端。

客户端:

客户端代码主要功能为设置和获取Property键值,以下为对外开放的接口。

设置Property

/*
* @description: 设置或增加属性键值
* @param - key: 需设置的属性名。
* @param - value: 属性名对应的键值。
* @return: 0 on success,< 0 on failure
*/int property_set(const char *key, const char *value)


获取Property

/*
* @description: 获取属性键值字符串
* @param - key: 需获取的属性名。
* @param - value: 属性名对应的键值。
* @param - default_value: 若获取失败,则使用此默认键值
* @return: 成功返回属性值长度,获取错误返回0
*/int property_get(const char *key, char *value, const char *default_value)
/*
* @description:用于获取bool类型的属性,失败返回默认值default_value
*/int8_t property_get_bool(const char *key, int8_t default_value)
/*
* @description:用于获取64位类型的属性,失败返回默认值default_value
*/int64_t property_get_int64(const char *key, int64_t default_value)
/*
* @description:用于获取32位类型的属性,失败返回默认值default_value
*/int32_t property_get_int32(const char *key, int32_t default_value)


注:系统中存在的key字符长度最大为32,value字符长度最大为92。如有越过,会导致异常情况。

特殊类型属性:

“ro.”前缀: “ro.”前缀,只读属性。仅会被设置一次,即当设置此属性发现其属性名已经存在,则此次设置不会生效,返回-1。

“persist.”前缀: “persist.”前缀,保留属性。当服务端接收到persist属性设置请求时,会在/data/property目录下建立对应的属性文件,并将键值存储到此文件中。如此一来即可实现键值掉电存储功能。

实现机制

流程:简单的介绍,Property机制运作流程可以简单的概括为以下几步:

  • PropertyService服务启动,初始化共享内存,加载若干属性脚本中默认属性内容;
  • 将系统中所有属性内容(key/value)存入系统共享内存,创建socket,并持续监听客户端socket请求;
  • 系统中各个客户进程将共享内存(只读权限)映射到自己的内存空间,可直接读取属性内容;
  • 系统仅有Property Service (属性服务)可修改和增加属性值;
  • 各个客户进程仅有读取属性权限,如需修改属性,需通过socket方式向Property Service发出修改请求,由Property Service统一修改;
  • 属性键值内容以字典树的形式存储于共享内存中(二叉树)。

Property机制示意图:Android原生Property移植记录_android_02

代码分析:

  • Property Service:Property服务端实现内容主要包括两部分:存储属性值共享内存(mmap + 二叉树)和建立通信(socket)。 共享机制:将文件映射两次到内存,第一次为可读可写权限,句柄为property service服务;第二次为只读权限,句柄为client服务。 通信机制:服务端建立socket通信,持续监听并处理客户端请求。Android原生Property移植记录_android_03
  • Property Client:
    客户端功能主要为设置属性和获取属性。其中获取属性可直接读取共享内存即可;设置属性则需要向服务端发送申请,由服务端将属性键值对设置到共享内存。property_set流程:
    Android原生Property移植记录_服务端_04

property_get流程:

Android原生Property移植记录_键值_05

使用示例

在使用之前先在后台执行服务端程序property_service(可放到开机启动脚本)。

Android原生Property移植记录_共享内存_06image.png

注:在一次开机中只允许执行一次property_service。若希望在property_service出现异常,手动重新执行,需先删除共享文件"dev/__properties__"。

显示系统设置的属性:Android原生Property移植记录_客户端_07

手动设置属性:Android原生Property移植记录_服务端_08

总结
  • 本篇主要记录移植Android Property机制过程以及对其原理的简要分析,Property可实现多进程之间的数据交互功能。
  • Property机制主要使用了socket、mmap和二叉树的技巧,学习其整体的设计可为后续工作开发增加知识储备。




最后

用心感悟,认真记录,写好每一篇文章,分享每一框干货。愿每一篇文章不负自己,不负看客!文章所有实现代码,均可在后台发送关键字获取。


 猜你喜欢

    详解 | Linux系统是如何实现存储并读写文件的?

    ​​C++打怪 之 vector​

Linux进程间通信 信号


更多文章内容包括但不限于C/C++、Linux、开发常用神器等,可进入开源519公众号聊天界面回复“文章目录” 或者 菜单栏选择“文章目录”查看。



本文摘自 :https://blog.51cto.com/u

开通会员,享受整站包年服务立即开通 >