博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android权限
阅读量:4207 次
发布时间:2019-05-26

本文共 4895 字,大约阅读时间需要 16 分钟。

两点基本知识:

1、  一个用户可以属于多个组.

2、  一个文件只能属于某个组。

这里主要是在AndroidManifest.xml中声明权限,主要是通过在AndroidManifest.xml中显示地声明应用程序需要的权限,防止应用程序错误的使用服务,不恰当访问资源。

Android中每种权限都用一个独立的标签表示.如:

android.permission.BLUETOOTH

当在安装(Install) 应用程序时,Android就会给予一个UID。这个UID可连结到该应用程序的 AndroidManifest.xml档案的内容。所以User在安装你的应用程序时,在屏幕上的窗口里可以检视这个 AndroidManifest.xml档案的内容。在检视时,用户会看到你对应用程序的目的、权限等说明。当你接受这支程序的意图、权限说明之后,Android就安装它,并给它一个UID。万一在你的应用程序执行期间有越轨(企图做出非权限范围)的行为时,用户将会得到Android的警告讯息。

下面是两个安装程序安装时的界面

这两个应用其实代码是一样的,唯一的不同就是它们的AndroidManifest.xml,图2的AndroidManifest.xml中多了如下内容:

<uses-permissionandroid:name="android.permission.RECORD_AUDIO"/>

<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

即需要使用存储设备和录音设备,在安装的时候,就会提示用户它需要的权限。Android里面是怎么去控制的呢?

在安装apk的时候,会解析这个AndroidManifest.xml,把相应的信息保存起来。

[cpp] 
  1. private Package parsePackage(  
  2.         Resources res, XmlResourceParser parser, int flags, String[] outError)  
  3.         throws XmlPullParserException, IOException {  
  4.    ...  
  5.    } else if (tagName.equals("uses-permission")) {  
  6.                 sa = res.obtainAttributes(attrs,  
  7.                         com.android.internal.R.styleable.AndroidManifestUsesPermission);  
  8.   
  9.                 // Note: don't allow this value to be a reference to a resource  
  10.                 // that may change.  
  11.                 String name = sa.getNonResourceString(  
  12.                         com.android.internal.R.styleable.AndroidManifestUsesPermission_name);  
  13.   
  14.                 sa.recycle();  
  15.   
  16.                 if (name != null && !pkg.requestedPermissions.contains(name)) {  
  17.                     pkg.requestedPermissions.add(name.intern());  
  18.                 }  
  19.   
  20.                 XmlUtils.skipCurrentTag(parser);  
  21.   
  22.             }  
  23. }  

这里对它使用的权限进行了解析。

这里保存的都是"android.permission.WRITE_EXTERNAL_STORAGE"这样的字符串,在解析完后,会调用grantPermissionsLP函数获取对应的group_id,

[cpp] 
  1. private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {  
  2.    ...   
  3. if (allowed) {  
  4.                         if (!gp.grantedPermissions.contains(perm)) {  
  5.                             changedPermission = true;  
  6.                             gp.grantedPermissions.add(perm);  
  7.                             gp.gids = appendInts(gp.gids, bp.gids);  
  8.                         } else if (!ps.haveGids) {  
  9.                             gp.gids = appendInts(gp.gids, bp.gids);  
  10.                         }  
  11.                     }  
  12.    ...  
  13. }  

这里把相应的组都保存到了gids中。

当应用程序起来的过程中会调用

[cpp] 
  1. private final void startProcessLocked(ProcessRecord app,  
  2.             String hostingType, String hostingNameStr) {  
  3.    ...  
  4.    try {  
  5.             int uid = app.info.uid;  
  6.             int[] gids = null;  
  7.             try {  
  8.                 gids = mContext.getPackageManager().getPackageGids(  
  9.                         app.info.packageName);  
  10.             } catch (PackageManager.NameNotFoundException e) {  
  11.                 Slog.w(TAG, "Unable to retrieve gids", e);  
  12.             }  
  13.    ...  
  14.     int pid = Process.start("android.app.ActivityThread",  
  15.                     mSimpleProcessManagement ? app.processName : null, uid, uid,  
  16.                     gids, debugFlags, null);  
  17. }  

创建了一个新的线程,这里传的参数就有gids

这里创建新进程最终调用forkAndSpecializeCommon

[cpp] 
  1. static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)  
  2. {  
  3.    ...  
  4.    pid = fork();  
  5.   
  6.     if (pid == 0) {  
  7.         int err;  
  8.         /* The child process */  
  9.   
  10. #ifdef HAVE_ANDROID_OS  
  11.         extern int gMallocLeakZygoteChild;  
  12.         gMallocLeakZygoteChild = 1;  
  13.   
  14.         /* keep caps across UID change, unless we're staying root */  
  15.         if (uid != 0) {  
  16.             err = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);  
  17.   
  18.             if (err < 0) {  
  19.                 LOGE("cannot PR_SET_KEEPCAPS: %s", strerror(errno));  
  20.                 dvmAbort();  
  21.             }  
  22.         }  
  23.   
  24. #endif /* HAVE_ANDROID_OS */  
  25.   
  26.         err = setgroupsIntarray(gids);  
  27.   
  28.         if (err < 0) {  
  29.             LOGE("cannot setgroups(): %s", strerror(errno));  
  30.             dvmAbort();  
  31.         }  
  32.        ...  
  33.       err = setgid(gid);  
  34.         if (err < 0) {  
  35.             LOGE("cannot setgid(%d): %s", gid, strerror(errno));  
  36.             dvmAbort();  
  37.         }  
  38.   
  39.         err = setuid(uid);  
  40.         if (err < 0) {  
  41.             LOGE("cannot setuid(%d): %s", uid, strerror(errno));  
  42.             dvmAbort();  
  43.         }  
  44. }  

我们看到在子进程里调用setgroupsIntarray设置该进程所属的组,这样它就拥有了该组的权限。

举个例子:

我们新建一Android工程,贴入如下代码:

[cpp] 
  1. try{  
  2.             java.lang.Process process = Runtime.getRuntime().exec("id");  
  3.             InputStream input = process.getInputStream();  
  4.             byte[] bytes = new byte[1204];  
  5.             int len;  
  6.             while((len = (input.read(bytes))) > 0)  
  7.             {  
  8.                 System.out.print(new String(bytes, 0, len));  
  9.             }  
  10.             input.close();  

这里运行运行linux的id命令的代码,id命令的功能是输出当前用户的uid,主要的group id和所在的group

在其AndroidManifest.xml添加如下权限:

    <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

运行后看log里面有:


这里面就有groups=1015

再看下android_filesystem_config.h里面

代码路径:

system\core\include\private

有如下代码

[cpp] 
  1. #define AID_MEDIA         1013  /* mediaserver process */  
  2. #define AID_DHCP          1014  /* dhcp client */  
  3. #define AID_SDCARD_RW     1015  /* external storage write access */  
  4. #define AID_VPN           1016  /* vpn system */  
  5.     ......  
  6.     { "cache",     AID_CACHE, },  
  7.     { "diag",      AID_DIAG, },  
  8.     { "net_bt_admin", AID_NET_BT_ADMIN, },  
  9.     { "net_bt",    AID_NET_BT, },  
  10.     { "sdcard_rw", AID_SDCARD_RW, },  
  11.     { "vpn",       AID_VPN, },  

再看下platform.xml

路径:frameworks\base\data\etc

有如下配置

[plain] 
  1. <permission name="android.permission.WRITE_EXTERNAL_STORAGE" >  
  2.         <group gid="sdcard_rw" />  
  3. </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-xsystem   sdcard_rw          2012-03-29 17:11sdcard

可以看到对于sd卡,组用户具有读写权限,而我们的应用也加入了这个组,这样它就可以操作sdcard了。

当一个应用需要操作sdcard而没有在AndroidManifest.xml添加相应的权限时,就不能成功完成。

以下是同一个程序,一个有在AndroidManifest.xml添加
WRITE_EXTERNAL_STORAGE
权限,一个没有,它们的对比,可以看到由于没有权限程序运行异常了.

这里的权限只是android里面涉及的一小部分,其实还有很多其它的权限。

参考:

转载地址:http://ptlli.baihongyu.com/

你可能感兴趣的文章
INCREMENTAL AGGREGATION IN INFORMATICA
查看>>
INFORMATICA1
查看>>
INFORMATICA2
查看>>
GENERATE DATE / TIME DIMENSION IN INFORMATICA
查看>>
日期维表数据生成方法(Oracle方式)
查看>>
2013年中国城市及省份GDP排名
查看>>
2013年欧洲穆斯林人口达5638万(转载)
查看>>
中国将在2014年成为十万亿级的超级大国
查看>>
月球可能曾是火星卫星
查看>>
华为u8818如何刷机
查看>>
少不读水浒——揭秘水浒传
查看>>
华为——让华盛顿感到恐慌的中国公司(转载)
查看>>
VMware虚拟机磁盘分区图文教程
查看>>
从CSV文件转换为Excel的多个Sheet
查看>>
ThinkPad E40如何安装W7Ghost
查看>>
Win7旗舰版 安装步骤
查看>>
Windows 7 SP1相关资源下载
查看>>
win7下直接安装win10
查看>>
本地硬盘安装win7/XP系统详细[图解教程]
查看>>
俄罗斯----中国人对它的颠覆性---不正确的神话
查看>>