Android 权限控制代码分析
前在文章介绍过android系统管理层次:http://blog.csdn.net/andyhuabing/article/details/7030212 ,这里就核心代码分析一下
android系统充分利用了linux的用户权限管理方法,所以如果需要移植到其它系统,这一块也是一个相当不小的工作量。那么android系统到底是如何使用这些的有利因素呢?
首先需要知道linux权限的两个基本知识: 1、 一个用户可以属于多个组. 2、 一个文件只能属于某个组。
这里主要是在AndroidManifest.xml中声明权限,主要是通过在AndroidManifest.xml中显示地声明应用程序需要的权限,防止应用程序错误的使用服务,不恰当访问资源。 Android中每种权限都用一个独立的标签表示.如: <uses-permission android:name="android.permission.WAKE_LOCK" /> 当在安装(Install) 应用程序时,Android就会给予一个UID。这个UID可连结到该应用程序的 AndroidManifest.xml档案的内容。所User在安装你的应用程序时,在屏幕上的窗口里可以检视这个 AndroidManifest.xml档案的内容。在检视时,用户会看到你对应用程序的目的、权限等说明。当你接受这支程序的意图、权限说明之后,Android就安装它,并给它一个UID。万一在你的应用程序执行期间有越轨(企图做出非权限范围)的行为时,用户将会得到Android的警告讯息。 下面是两个安装程序安装时的界面
这两个应用其实代码是一样的,唯一的不同就是它们的AndroidManifest.xml,图2的AndroidManifest.xml中多了如下内容: <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 即需要使用存储设备和录音设备,在安装的时候,就会提示用户它需要的权限。Android里面是怎么去控制的呢?
在安装apk的时候,会解析这个AndroidManifest.xml,把相应的信息保存起来。 代码路径:frameworks\base\core\java\android\content\pm\PackageParser.java 最终调用的是private Package parsePackage( Resources res, XmlResourceParser parser, int flags, String[] outError) 这个函数,在里面对AndroidManifest.xml进行了解析,其中就有 private Package parsePackage( ... String tagName = parser.getName(); ... }
这里对它使用的权限进行了解析。 这里保存的都是"android.permission.WRITE_EXTERNAL_STORAGE"这样的字符串,在解析完后,会调用grantPermissionsLP函数获取对应的group_id, 代码路径:frameworks\base\services\java\com\android\server\PackageManagerService.java private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {... if (allowed) { if (!gp.grantedPermissions.contains(perm)) { changedPermission = true; gp.grantedPermissions.add(perm); gp.gids = appendInts(gp.gids, bp.gids); } else if (!ps.haveGids) { gp.gids = appendInts(gp.gids, bp.gids); } } else { Slog.w(TAG, "Not granting permission " + perm + " to package " + pkg.packageName + " because it was previously installed without"); } ... } 这里把相应的组都保存到了gids中。 当应用程序启动的过程中会调用 private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) 代码路径:frameworks\base\services\java\com\android\server\am\ActivityManagerService.java private final void startProcessLocked(ProcessRecord app, 创建新进程利用jni最终调用 forkAndSpecializeCommon 函数 (路径:\dalvik\vm\native\dalvik_system_Zygote.c)
举个例子: 我们新建一Android工程,读取其应用的uid/gid值,贴入如下代码: try{ java.lang.Process process = Runtime.getRuntime().exec("id"); InputStream input = process.getInputStream(); byte[] bytes = new byte[1204]; int len; while((len = (input.read(bytes))) > 0) { System.out.print(new String(bytes, 0, len)); } input.close(); 这里运行运行linux的id命令的代码,id命令的功能是输出当前用户的uid,主要的group id和所在的group 在其AndroidManifest.xml添加如下权限: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 运行后看log里面有:
这里面就有groups=1015
再看下android_filesystem_config.h里面 代码路径: system\core\include\private 有如下代码 #define AID_ROOT 0 /* traditional unix root user */#define AID_SYSTEM 1000 /* system server */ #define AID_RADIO 1001 /* telephony subsystem, RIL */ #define AID_BLUETOOTH 1002 /* bluetooth subsystem */ #define AID_GRAPHICS 1003 /* graphics devices */ ... #define AID_WIFI 1010 /* wifi subsystem */
再看下platform.xml 路径:frameworks\base\data\etc 有如下配置 <permission name="android.permission.WRITE_EXTERNAL_STORAGE" > <group gid="sdcard_rw" /> </permission> 这样就把android.permission.WRITE_EXTERNAL_STORAGE 、"sdcard_rw"、以及 1015组关联起来了
我们再看下当sd卡挂载上去后目录的权限: ls -l drwxr-xr-x root system 1970-01-01 08:00 obb drwxr-xr-x root system 1970-01-01 08:00 asec drwx------ root root 1970-01-01 08:00 secure d---rwxr-x system sdcard_rw 2012-03-29 17:11 sdcard 可以看到对于sd卡,组用户具有读写权限,而我们的应用也加入了这个组,这样它就可以操作sdcard了。
当一个应用需要操作sdcard而没有在AndroidManifest.xml添加相应的权限时,就不能成功完成。 以下是同一个程序,一个有在AndroidManifest.xml添加WRITE_EXTERNAL_STORAGE权限,一个没有,它们的对比,可以看到由于没有权限程序运行异常了。
对于管理权限的xml文件补充说明一下: 源代码中权限文件位于: frameworks\base\data\etc 下面,镜像生成在 system\etc\permissions\platform.xml中 文件权限读取点: readPermissions @ PackageManagerService.java void readPermissions() {
platform.xml 的重要性在于: <!-- This file is used to define the mappings between lower-level system |
|
来自: techres > 《Android管理应用》