Android Dangerous权限的处理【设为默认】

Android Dangerous权限的处理【设为默认】

在日常的使用中,如果我们调用到某一个接口,该接口依赖于危险权限的声明,平时我们会去对权限进行检查,检查这个权限是否被赋予,如果没有被赋予,就需要进行动态申请,否则会报权限异常的Exception.

但如果我本人比较懒,不想手动动他,权限就给他算了。针对和由系统集成的apk而言,可以考虑两种方式。

android:sharedUserId = “android.uid.system” 加上这个后,对应的应用瞬间变得niubility,一般apk是运行在普通的user用户下,加上该标签后,就会运行在system用户下,同时系统级用户对于危险权限是默认授予的,同时用户无法进行操作的。

除了上面这种niubility方法,还有一种方法也可以让某个应用默认授予权限并且用户无法操作,这也是本次要将的重点,稍微结合源码来介绍下

接下来进行操作的实现:
1.创建对应的配置文件,别问,问就是有人要读
2.编写对应的集成文档,别问,问就是有人要从那里取

先说一下1吧,这里简单给个例子:
加入我们要继承的配置文件是 default_permission_xxx.xml

<?xml version="1.0" encoding="utf-8"?>
<exceptions>
  
  <!-- exception package 为要授予权限的app包名 -->
  <!-- permission name 为要授予权限的app默认授予的权限 -->
  <!-- permission的fixed表示授权后是否可以被非系统组件修改权限 -->
  <exception package="com.android.xxxtest">
      <permission name="android.permission.巴拉巴拉" fixed="false"/>
  
  </exception>
  
</exceptions>

这里简单说一下,首先package是要设置对应权限的包名,接着在权限中的name是要设置为默认授予的权限名称(这里针对dangerous权限而言,priv权限有自己的定义方式),最后的fixed标志位是用来设置是否可以被非系统组件修改的标志,从用户体验的角度来看就是用户能不能修改该权限。

这里要读的内容差不多按照这个格式来写,那该给它放到哪去呢?
接着就要想办法把这个配置文件集成到特定的位置去。

这里以bp文档为例,mk可以看参考文档中,写法都大差不大:

android_app {
    name : "balabala",
    ...

    required:["permission_balabala"],

}

prebuilt_etc {
    name: "permission_balabala",
    product_specific: true,
    sub_dir: "default-permissions",
    src: "default-permissions-xxxx.xml",
}

简单说明下:
对于android_app的name,就是我们应用的名,
required中包含了要继承的配置文件,
prebuilt_etc 是指要往某个etc/的路径下集成,
product_specific是指往product分区进行集成,除此之外还有vendor,system_ext,system,Oem等
sub_dir是指在对应的分区/etc/的子路径下,这里要是集成危险权限,所以必须是default-permissions的文件名,敲重点
最后的src就是对应的资源文件

这两步配置好了就能够实现对应应用的默认权限授予的配置。

接着简单看点源码:
DefaultPermissionGrantPolicy.java
看这个类名应该就直到是专门负责默认权限授予工作的。主要是pms来进行调用

public void grantDefaultPermissions(int userId) {
    DelayingPackageManagerCache pm = new DelayingPackageManagerCache();

    grantPermissionsToSysComponentsAndPrivApps(pm, userId);
    grantDefaultSystemHandlerPermissions(pm, userId);
    grantDefaultPermissionExceptions(pm, userId);

    // Apply delayed state
    pm.apply();
}

看一下中间的三巨头方法,第一个应该是授予默认的系统权限和priv权限
第二个是赋予一些系统级应用的默认权限,比如说语音助手,电话等等
第三个就是今天的重头戏,授予用户配置的危险权限

private void grantDefaultPermissionExceptions(PackageManagerWrapper pm, int userId) {
    mHandler.removeMessages(MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS);

    synchronized (mLock) {
        // readDefaultPermissionExceptionsLocked 这个方法会去对根目录,vendor,Odm,product,以及system_ext分区下etc/default-permissions/下的xml进行读取,读取后返回给mGrantExceptions
        if (mGrantExceptions == null) {
            mGrantExceptions = readDefaultPermissionExceptionsLocked(pm);
        }
    }

    Set<String> permissions = null;
    final int exceptionCount = mGrantExceptions.size();
    for (int i = 0; i < exceptionCount; i++) {
        String packageName = mGrantExceptions.keyAt(i);
        PackageInfo pkg = pm.getSystemPackageInfo(packageName);
        List<DefaultPermissionGrant> permissionGrants = mGrantExceptions.valueAt(i);
        final int permissionGrantCount = permissionGrants.size();
        for (int j = 0; j < permissionGrantCount; j++) {
            DefaultPermissionGrant permissionGrant = permissionGrants.get(j);
            if (!pm.isPermissionDangerous(permissionGrant.name)) {
                Log.w(TAG, "Ignoring permission " + permissionGrant.name
                        + " which isn't dangerous");
                continue;
            }
            if (permissions == null) {
                permissions = new ArraySet<>();
            } else {
                permissions.clear();
            }
            permissions.add(permissionGrant.name);

            // 注意看! 这个标志叫permissionGrant.fixed
            grantRuntimePermissions(pm, pkg, permissions, permissionGrant.fixed,
                    permissionGrant.whitelisted, true /*whitelistRestrictedPermissions*/,
                    userId);
        }
    }
}
private void grantRuntimePermissions(PackageManagerWrapper pm, PackageInfo pkg,
            Set<String> permissionsWithoutSplits, boolean systemFixed, boolean ignoreSystemPackage,
            boolean whitelistRestrictedPermissions, int userId) {
    UserHandle user = UserHandle.of(userId);
    if (pkg == null) {
        return;
    }

    String[] requestedPermissions = pkg.requestedPermissions;
    if (ArrayUtils.isEmpty(requestedPermissions)) {
        return;
    }

    // Intersect the requestedPermissions for a factory image with that of its current update
    // in case the latter one removed a <uses-permission>
    String[] requestedByNonSystemPackage = pm.getPackageInfo(pkg.packageName)
            .requestedPermissions;
    int size = requestedPermissions.length;
    for (int i = 0; i < size; i++) {
        if (!ArrayUtils.contains(requestedByNonSystemPackage, requestedPermissions[i])) {
            requestedPermissions[i] = null;
        }
    }
    requestedPermissions = ArrayUtils.filterNotNull(requestedPermissions, String[]::new);

    final ArraySet<String> permissions = new ArraySet<>(permissionsWithoutSplits);
    ApplicationInfo applicationInfo = pkg.applicationInfo;

    int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
    // 这个值就是在配置文件中的fixed标志位的值,如果是true,就把对应的权限标志位添加上PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
    if (systemFixed) {
        newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
    }
}

给上一个加上该标志位后的示例dumpsys结果:

User 13:
    ......
      runtime permissions:
        android.permission.BLUETOOTH_CONNECT: granted=true, flags=[ SYSTEM_FIXED|GRANTED_BY_DEFAULT|USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]

可以看到,对应的runtime权限的列表中,flags包含了SYSTEM_FIXED标签并且有GRANTED_BY_DEFAULT标签,说明该权限是默认授予,并且用户无法进行操作的。具体如何让其不进行操作,可以看Setting对于system_fixed的标志位的处理,会有一个disable的过程。

参考文档:
https://blog.csdn.net/qq_34250794/article/details/128284337
https://blog.csdn.net/qq_37580586/article/details/120132638

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值