8.2.5 解析系统permission和feature信息

通过调用readPermissions()方法解析设备上/system/etc/permissions目录下的所有XML文件。这些XML文件包括platform.xml和系统支持的各种软硬件特性(feature)配置文件,其对应于源码目录/frameworks/base/data/etc下的同名文件。除platform.xml文件外,其余feature文件原则上可以任意命名,但Android Market会解析应用程序中声明的feature,以此过滤掉那些不支持某种feature的应用程序,所以feature的命名最好遵守现有规则。

各XML文件的作用如下。

1.platform.xml

该文件用于定义底层进程的UID(User ID)和GID(Group ID)与Android定义的权限名之间的映射关系。在platform.xml中使用四种标签表示这种映射关系:1)<permission>,2)<group>,3)<assign-permission>,4)<library>。

<group>是<permission>的子标签,用于为指定的组ID分配指定的Android权限。

<assign-permission>用于为指定的用户ID分配指定的Android权限。

<library>指定系统扩展库,又名共享库。

platform. xml的内容如下:


<permissions>

<!—给指定的Group ID分配指定的permission—>

<permission name="android.permission.INTERNET">

<group gid="inet"/>

</permission>

……

<permission name="android.permission.ACCESS_CACHE_FILESYSTEM">

<group gid="cache"/>

</permission>

<!—给指定的User ID分配指定的permission—>

<assign-permission name="android.permission.SEND_SMS"uid="shell"/>

<assign-permission name="android.permission.CALL_PHONE"uid="shell"/>

……

<assign-permission name="android.permission.ACCESS_DRM"uid="media"/>

……

<!—指定系统共享库,扩展系统功能—>

<library name="android.test.runner"

file="/system/framework/android.test.runner.jar"/>

<library name="javax.obex"

file="/system/framework/javax.obex.jar"/>

</permissions>


2.feature配置文件

该文件用于定义设备支持的各种软硬件特性。Feature配置文件分为Hardware feature配置文件和Software feature配置文件。

1)Hardware feature:指定当前设备支持的硬件特性。

Hardware feature主要用于配置以下硬件的特性:Audio、Bluetooth、Camera、Location、Microphone、NFC、Sensors、Screen、Telephony、Touchscreen、USB、Wi-Fi。各个配置文件的文件名以android.hardware.为前缀。

android. hardware.camera.flash-autofocus.xml是Camera的feature文件,内容如下:


<permissions>

<feature name="android.hardware.camera"/>

<feature name="android.hardware.camera.autofocus"/>

<feature name="android.hardware.camera.flash"/>

</permissions>


以上配置说明当前设备支持camera、自动对焦和闪光灯三种特性。

Harware feature配置文件包括核心硬件feature配置文件,用于指定手持设备应该支持的核心硬件特性。默认情况下,核心硬件特性配置文件以_core_hardware为后缀,如handheld_core_hardware.xml和tablet_core_hardware.xml。

2)Software feature:指定当前设备支持的软件特性。

默认情况下支持SIP和VOIP两种软件特性,分别定义在android.software.sip.xml和android.software.sip.voip.xml中。软件特性均以android.software.为前缀,其内容如下:


<permissions>

<feature name="android.software.sip"/>

<feature name="android.software.sip.voip"/>

</permissions>


以上配置文件表明设备支持SIP和基于SIP的VOIP软件特性。

特定厂商会针对自己设备的软硬件特性,定义专有的XML文件。这部分XML文件通常以厂商名命名。

通过PackageManager的hasSystemFeature或getSystemAvailableFeatures方法,可以确定当前设备是否支持某个特性,然后决定是否使用相应特性的功能和API。

在源码/frameworks/base/data/etc目录下的Android.mk文件中,指定将这些XML文件编译输出到设备的哪个目录。配置模块输出路径为LOCAL_MODULE_PATH:=$(TARGET_OUT_ETC)/permissions,编译后将这部分XML文件复制到out/target/product/generic/system/etc/permission/system/etc/permissions目录中,该目录对应设备上的system/etc/permissions目录。熟悉了readPermissions()方法要解析的文件后,具体分析该方法的流程,代码如下:


void readPermissions(){

File libraryDir=new File(Environment.getRootDirectory(),"etc/permissions");

……

for(File f:libraryDir.listFiles()){

if(f.getPath().endsWith("etc/permissions/platform.xml")){

continue;//跳过platform.xml文件

}

……

readPermissionsFromXml(f);

}

final File permFile=new File(Environment.getRootDirectory(),

"etc/permissions/platform.xml");

readPermissionsFromXml(permFile);

}


readPermissions()进入for循环,遍历system/etc/permissions目录下的所有文件,在遍历的过程中先跳过platform.xml、非XML文件和不可读文件,对余下文件调用readPermissions FromXml方法进行解析。解析完成后,退出循环,并再次调用readPermissionsFromXml方法单独解析platform.xml。


在readPermissionsFromXml方法内部解析XML文件的步骤如下:


步骤1 解析<group>标签,将其gid属性的值存入PackageManagerService.mGlobalGids中。该标签指定所有包共有的全局Group ID。mGlobalGids为int型数组,该标签默认未使用。

步骤2 解析<permission>标签,该标签的name属性代表Android定义的权限名。在解析过程中,首先检查mSettings.mPermissions中是否有该权限名对应的权限信息(以BasePermission对象表示权限信息),如果没有则创建该权限信息,创建后以该权限名为键将权限信息存入mSettings.mPermissions中。创建过程的代码如下:


BasePermission bp=mSettings.mPermissions.get(name);

if(bp==null){

bp=new BasePermission(name, null, BasePermission.TYPE_BUILTIN);

mSettings.mPermissions.put(name, bp);

}


<permission>有一个子标签<group>,<group>子标签的gid属性表示一个属性组的名字,需要通过Process.getGidForName方法得到该属性组对应的组ID,然后将该组ID存入Base Permission.gids中。

步骤3 解析<assign-permission>标签,将其name和uid属性值存入PackageManager Service.mSystemPermissions中。其中uid为键,name的集合为值。

步骤4 解析<library>标签,将其name和file属性值存入PackageManagerService.mShared Libraries中。该变量类型是HashMap<String, String>,键为name,值为file。

步骤5 解析<feature>标签,并将其内容存入PackageManagerService.mAvailableFeatures中。该变量类型是HashMap<String, FeatureInfo>,其中HashMap的键是该feature的name属性值,HashMap的值是一个FeatureInfo类型的变量fi,代表一个可以被应用程序请求使用的特性。

这些XML文件解析后存入了PackageManagerService和mSettings的成员变量中,通过PackageManager中提供的API接口可以查询这些信息,因此分析该部分的赋值过程有利于理解PackageManager提供的API。

需要读者注意的是,<permission>标签的内容存入mSettings中,而<assign-permission>标签的内容存入PackageManagerService.mSystemPermissions中。