3.3.1 Android应用程序权限机制的源代码分析(2)
1)定义应用程序有照相功能权限CAMERA。
android:name="android.hardware.camera.autofocus"
android:required="false"/>
在以上的属性中,android:name表示权限名称为CAMERA。标签表示该应用程序运行所需使用的硬件或软件特性。属性中的android:required表示应用程序的正常运行是否必须依赖于硬件特性,比如autofocus。设定为false,表示不一定需要此硬件特性也能正常运行;反之,true表示该硬件特性是正常运行的必需条件。
2)定义应用程序自定义壁纸权限SET_WALLPAPER。需要说明的是,此权限属于Normal权限级别,定义一个新壁纸一般不会影响到敏感信息。
android:name="android.permission.SET_WALLPAPER"/>
3)定义应用程序具备读取短信权限READ_SMS。此权限属于Dangerous权限级别,因为应用程序一旦具备了读取短信的权限,就可以访问到短信中的敏感信息,具有一定的危险性。如果应用程序没有该权限,直接访问受保护的API,将抛出SecurityException。
android:name="android.permission.READ_SMS"/>
(2)Android应用程序权限的执行
AndroidManifest.xml中定义的权限是如何被执行的?这些申请的权限需要映射到底层的用户和组权限,才能够被执行,被应用程序启用。当Android系统启动时,SystemServer会首先启动PackageManagerService安装包服务,PackageManagerService是一个负责处理各种应用程序的安装、卸载、管理等工作的服务。PackageManagerService服务中的parsePackage函数将对AndroidManifest.xml文件进行解析,然后获取应用程序所申请的权限。系统根据所申请的这些权限,授予应用程序相应权限的组ID。同时应用程序在安装时系统已经赋予了它***的用户ID,这样一来,拥有用户ID和组ID的应用程序便可正常启动。下面对应用程序权限的执行进行代码层面的分析。
PackageManagerService源代码PackageManagerService.java文件位于frameworks/base/services/ java/com/android/server/目录下。负责对权限进行解析的parsePackage函数由Package ManagerService服务中的installPackageLI函数调用,它所属的PackageParser类的源代码PackageParser.java位于frameworks/base/core/java/android/content/pm/目录下。
parsePackage函数主要是对AndroidManifest.xml中标签进行解析。在进行解析时,parsePackage会保留“android.permission.***”定义,在解析完成后,会根据保留的权限定义调用grantPermissionsLP函数获取权限对应的组ID。parsePackage函数的代码实现如下:
private Package parsePackage(Resources res,XmlResourceParser parser, int flags, String[] outError)throwsXmlPullParserException, IOException
{
……
else if (tagName.equals("uses-permission"))
{
sa=res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestUsesPermission);
Stringname=sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
sa.recycle();
//检测是否已经保存了该请求权限信息,
//如果没有保存就将其保存至pkg.requestedPermissions
if (name != null &&!pkg.requestedPermissions.contains(name))
{
pkg.requestedPermissions.add(name.intern());
pkg.requestedPermissionsRequired.add(Boolean.TRUE);
}
XmlUtils.skipCurrentTag(parser);
}
解析完标签后,grantPermissionsLP函数将根据parsePackage保留的“android.permission.***”定义为应用程序分配具有相应权限的组ID。应用程序拥有此组ID,在启动之后,便具备了其申请的权限。相关代码片段如下:
private void grantPermissionsLP(PackageParser.Packagepkg, boolean replace)
{
……
if (allowed) {
if (!gp.grantedPermissions.contains(perm))
{
changedPermission=true;
gp.grantedPermissions.add(perm);
//这里把相应的组都保存到了gids中
gp.gids=appendInts(gp.gids, bp.gids);
} else if (!ps.haveGids)
gp.gids=appendInts(gp.gids, bp.gids);
}
……
}