Android Framework权限篇之RuntimePermission数据结构解析

本文详细解释了Android应用中的权限控制数据结构,包括权限状态的层次结构和持久化存储方式。同时介绍了安装应用时权限授权的流程,以及不同SDK版本下的权限处理策略。最后提到了关键组件如PermissionManagerService和AndroidFramework源码的剖析,强调了深入学习框架对于开发者的重要性。
摘要由CSDN通过智能技术生成

数据结构

在上篇文章中提到的权限授权、撤销授权、判断是否授权等都会通过如下数据结构读取写入;这里画了个图帮助大家阅读源码理解,因为嵌套比较深;

在这里插入图片描述

这里两张图结合起来看下,

  1. 第一个ArrayMap键是包名,值是Package类;Package类中有对应的PermissionsState类。
  2. PermissionsState类中是一个ArrayMap<String, PermissionData>,键是权限名,值是PermissionData类;
  3. PermissionData类中是一个SparaseArray<PermissionState>,键是整型userId,值是PermissionState(注意细节少了个s);
  4. PermissionState类则是对应权限具体的名称、是否授权、和对应flag; 整体数据结构对应下图:

在这里插入图片描述

理解了以上之后,再回过头去看源码里关于PermissionsState类的相关方法去进行授权和判断是否授权等就容易看了

持久化存储

运行时权限会持久化存储在/data/system/users/0/runtime-permissions.xml 这里表示userid对应是0,如果有多用户则对应在其他users目录下;xml文件存储内容如下,对应上面数据结构的name、granted、flag等属性

在这里插入图片描述

安装应用授权流程

如果在应用声明了以下权限,安装应用时权限是如何授权的?如下几种权限级别都是上篇文章有提到的,第一种是默认授权的,第二种是签名权限,第三种是运行时权限

在这里插入图片描述

这里涉及到应用安装流程,可以看下如下流程图:

在这里插入图片描述

这里主要看下PermissionManagerService.restorePermissionState()(ard10上,ard9上方法名称为grantPermissions());如下代码是ard9上的源码摘录;这里源码会判断targetsdkVersion是否大于等于23,安装完应用权限授权结果也有所不一样:

  1. >= 23 则只有一个install权限即INTERNET权限得到授权,runtime权限需要运行时申请,signature权限无法获得授权;
  2. <23 则会将runtime权限和siganture权限认为是install权限所以7个权限都得到授权

private void grantPermissions(PackageParser.Package pkg, boolean replace,String packageOfInterest, PermissionCallback callback) {
...
//取出应用在AndroidManifest.xml中声明的权限,进行遍历判断是否允许安装时授权
final int N = pkg.requestedPermissions.size();
for (int i = 0; i < N; i++) {
    final String permName = pkg.requestedPermissions.get(i);
    //判断sdk版本号是否大于等于23;
    final boolean appSupportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M;

...
    //1. install权限默认直接授权   
    if (bp.isNormal()) {
        // For all apps normal permissions are install time ones.
        grant = GRANT_INSTALL;
    } else if (bp.isRuntime()) {
        //这里targetsdkversion小于23的runtime权限会设置为GRANT_INSTALL,直接授权
        if (!appSupportsRuntimePermissions && !mSettings.mPermissionReviewRequired) {
            // For legacy apps dangerous permissions are install time ones.
            grant = GRANT_INSTALL;
        } else if (origPermissions.hasInstallPermission(bp.getName())) {
            //2. runtime权限:如果之前的权限是install,现在升级为runtime权限,则为GRANT_UPGRADE
            // For legacy apps that became modern, install becomes runtime.
            grant = GRANT_UPGRADE;
        } else if (isLegacySystemApp) {
            // For legacy system apps, install becomes runtime.
            // We cannot check hasInstallPermission() for system apps since those
            // permissions were granted implicitly and not persisted pre-M.
            grant = GRANT_UPGRADE;
        } else {
            //3. 其余情况则为GRANT_RUNTIME
            // For modern apps keep runtime permissions unchanged.
            grant = GRANT_RUNTIME;
        }
    } else if (bp.isSignature()) {
        // For all apps signature permissions are install time ones.
        //4. signature权限:这里会判断是否满足签名条件(如targetSdkVersion小于23返回true),为true才会设置为GRANT_INSTALL并默认授权,否则为GRANT_DENIED
        //见下5返回true
        allowedSig = grantSignaturePermission(perm, pkg, bp, origPermissions);
        if (allowedSig) {
            grant = GRANT_INSTALL;
        }
    }    
...
   //上面赋值完这里根据grant结果进行操作
   switch (grant) {
       case GRANT_INSTALL: {
           ...
           // Grant an install permission.
           //这里是install权限进行授权
           if (permissionsState.grantInstallPermission(bp) !=
                   PERMISSION_OPERATION_FAILURE) {
               changedInstallPermission = true;
           }
       } break;
       case GRANT_RUNTIME: {
       ...
       case GRANT_UPGRADE: {
       ...
}


private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
              BasePermission bp, PermissionsState origPermissions) {
...
 if (!allowed) {
    //5.signature权限判断targetSdkVersion<23则返回true
    if (!allowed
            && bp.isPre23()
            && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
        // If this was a previously normal/dangerous permission that got moved
        // to a system permission as part of the runtime permission redesign, then
        // we still want to blindly grant it to old apps.
        allowed = true;
    }
    ...

adb命令

这里提供一个排查的adb命令可以看应用当前的权限状态

adb shell dumpsys package 应用包名

  • requested permissions ——应用在AndroidManifest.xml中声明的权限
  • install permissions —— normal权限授权情况,包括signature权限
  • runtime permissions —— 危险权限授权情况

在这里插入图片描述

如何学习Framework?

由于许多Android开发者日常工作主要集中在业务层面,大量时间用于编写基础代码、应用现成框架,导致对底层技术如Framework、Handler源码、Binder机制等了解不足,仅停留在表面认知阶段。

为此,为了帮助广大开发者弥补这一短板,特此准备了一份详尽的Android Framework内核源码知识体系图解,以及配套的《Android Framework源码开发解析》学习笔记,旨在引导大家系统性地攻克Android Framework领域的核心技术,从而提升自身的竞争力,从容应对金三银四的求职挑战。

【有需要的朋友,扫描下方二维码即可领取!!】👇👇

在这里插入图片描述

《Android Framework源码开发揭秘》

第一章 系统启动流程分析
  • 第一节 Android启动概括
  • 第二节 init.rc解析
  • 第三节 Zygote
  • 第四节 面试题
    在这里插入图片描述
第二章 跨进程通信IPC解析
  • 第一节 Service还可以这么理解
  • 第二节 Binder基础
  • 第三节 Binder应用
  • 第四节 AIDL应用(上)
  • 第五节 AIDL应用(下)
  • 第六节 Messenger原理及应用
  • 第七节 服务端回调
  • 第八节 获取服务(IBinder)
  • 第九节 Binder面试题全解析
    在这里插入图片描述
第三章 Handler源码解析
  • 第一节 源码分析
  • 第二节 难点问题
  • 第三节 Handler常问面试题在这里插入图片描述
第四章 AMS源码解析
  • 第一节 引言
  • 第二节 Android架构
  • 第三节 通信方式
  • 第四节 系统启动系列
  • 第五节 AMS
  • 第六节 AMS面试题解析在这里插入图片描述
第五章 WMS源码解析
  • 第一节 WMS与activity启动流程
  • 第二节 WMS绘制原理
  • 第三节 WMS角色与实例化过程
  • 第四节 WMS工作原理在这里插入图片描述
第六章 Surface源码解析
  • 第一节 创建流程及软硬件绘制
  • 第二节 双缓冲及Surface View解析
  • 第三节 Android图形系统综述在这里插入图片描述
第七章 基于Android12.0的SurfaceFlinger源码解析
  • 第一节 应用建立和SurfaceFlinger的沟通桥梁
  • 第二节 SurfaceFlinger的启动和消息队列处理机制
  • 第三节 SurfaceFlinger之VSyns(上)
  • 第四节 SurfaceFlinger之VSyns(中)
  • 第五节 SurfaceFlinger之VSyns(下)在这里插入图片描述
第八章 PKMS源码解析
  • 第一节 PKMS调用方式
  • 第二节 PKMS启动过程分析
  • 第三节 APK的扫描
  • 第四节 APK的安装
  • 第五节 PKMS之权限扫描
  • 第六节 静默安装
  • 第七节 requestPermissions源码流程解析
  • 第八节 PKMS面试题在这里插入图片描述
第九章 InputManagerService源码解析
  • 第一节 Android Input输入事件处理流程(1)
  • 第二节 Android Input输入事件处理流程(2)
  • 第三节 Android Input输入事件处理流程(3)在这里插入图片描述
第十章 DisplayManagerService源码解析
  • 第一节 DisplayManagerService启动
  • 第二节 DisplayAdepter和DisplayDevice的创建
  • 第三节 DMS部分亮灭屏流程
  • 第四节 亮度调节
  • 第五节 Proximity Sensor灭屏原理
  • 第六节 Logical Display和Physical Display配置的更新在这里插入图片描述
【有需要的朋友,扫描下方二维码即可领取!!】👇👇

最后 在Android开发市场饱和的大背景下,初级开发者只有通过对Android Framework进行全面而深入的学习与实践,才能有效提高自身的专业素养和技术能力,从而在职场竞争中找准定位,实现从量到质的飞跃,成为行业内的佼佼者。

在Java中,自定义权限掩码(Custom Permission Masks)通常是在使用Java安全模型(Java Security Model)时,为特定操作或权限分配的一种抽象表示。这个模型用于控制代码运行时对系统资源(如文件、网络连接等)的访问权限。 在Java中,权限是由一组位(bits)组成的掩码,每个位代表一种特定的权限级别。例如,`java.lang.RuntimePermission` 类提供了一组预定义的权限,比如 `accessClassInPackage` 和 `setContextClassLoader`,它们都有自己的二进制掩码。 如果你需要自定义权限,你可以创建一个新的权限类,继承自 `java.security.Permission` 或其子类,比如 `BasicPermission` 或 `RuntimePermission`。然后,你需要为这个新权限定义一个名称和一个掩码字符串,该字符串通常是一个以`"permissionName=mask"`格式表示的字符串,其中`permissionName`是权限的类别名,`mask`是你自定义的二进制掩码。 例如: ```java public class MyCustomPermission extends BasicPermission { public MyCustomPermission(String name) { super(name); } private static final String MASK = "00000001"; // 假设这是一个自定义的四位掩码,表示四种不同的权限级别 } // 使用自定义权限 MyCustomPermission permission = new MyCustomPermission("myCustomAction"); System.out.println(permission.getName()); // 输出 "myCustomAction" System.out.println(permission.getActions()); // 输出 "myCustomAction" ``` 在实际应用中,可能需要在`Policy`或`PolicyProvider`中注册这些自定义权限,并在`SecurityManager`的检查方法中处理这些权限的验证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值