Android权限控制代码分析
Android 权限控制代码分析
前在文章介绍过android系统管理层次:http://www.zzzyk.com/kf/201204/127682.html ,这里就核心代码分析一下
android系统充分利用了linux的用户权限管理方法,所以如果需要移植到其它系统,这一块也是一个相当不小的工作量。那么android系统到底是如何使用这些的有利因素呢?
首先需要知道linux权限的两个基本知识:
1、 一个用户可以属于多个组.
2、 一个文件只能属于某个组。
这里主要是在AndroidManifest.xml中声明权限,主要是通过在AndroidManifest.xml中显示地声明应用程序需要的权限,防止应用程序错误的使用服务,不恰当访问资源。
Android中每种权限都用一个独立的标签表示.如:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
当在安装(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(
Resources res, XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
...
String tagName = parser.getName();
if (tagName.equals("application")) {
...
} else if (tagName.equals("permission-group")) {
if (parsePermissionGroup(pkg, res, parser, attrs, outError) == null) {
return null;
}
} else if (tagName.equals("permission")) {
if (parsePermission(pkg, res, parser, attrs, outError) == null) {
return null;
}
} else if (tagName.equals("permission-tree")) {
if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
return null;
}
} else if (tagName.equals("uses-permission")) {
sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestUsesPermission);
// Note: don't allow this value to be a reference to a resource
// that may change.
String name = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
sa.recycle();
if (name != null && !pkg.requestedPermissions.contains(name)) {
pkg.requestedPermissions.add(name.intern());
}
XmlUtils.skipCurrentTag(parser);
}
...
}
这里对它使用的权限进行了解析。
这里保存的都是"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,
String hostingType, String hostingNameStr) {
...
&
补充:移动开发 , Android ,