AppOps简介

AppOps全称是 Application Operations,类似我们平时常说的应用程序的操作(权限)管理。用控制蓝牙开关,摄像头,Wi-Fi等功能的操作权限。比如,我们安装了一个第三方蓝牙应用,在该应用要打开蓝牙开关时就会弹出如下对话框让用户确认:

至于为什么在系统自带的Settings里操作蓝牙开关没弹对话框,之后会讲到。

AppOps总体概览

核心服务:AppOpsService

系统启动时该服务会启动运行。

参考以下ActivityManagerService.java,ActivityManagerService启动过程中:

配置文件:appops.xml appops_policy.xml

appops.xml位于 /data/system/目录下,存储各个app的权限设置和操作信息。

appops_policy.xml位于 /system/etc/目录下,里面存有对特定App的权限配置。

API接口:AppOpsManagerAppOpsService实现了大部分的核心功能逻辑,但它不能被其他模块直接调用访问,而是通过AppOpsManager提供访问接口。

AppOps使用逻辑举例以蓝牙开关为例,来讲一下AppOps的使用和基本逻辑。

如上图,在开始之前,我们需先在/system/build.prop里添加配置:

persist.sys.strict_op_enable=true

用于使能AppOps机制。

1、App在打开蓝牙开关时,需调用到BluetoothManagerService.enable(String callingPackage),具体流程不表;

在BluetoothManagerService.enable(String callingPackage)里:

java 复制代码
AppOpsManager appOps = (AppOpsManager) mContext
     .getSystemService(Context.APP_OPS_SERVICE);
int callingUid = Binder.getCallingUid();
if (appOps.noteOp(AppOpsManager.OP_BLUETOOTH_CHANGE, callingUid,
     callingPackage) != AppOpsManager.MODE_ALLOWED)
      return false;

a.首先获取APP_OPS_SERVICE(即AppOpsService)服务的代理对象appops,用于调用AppOpsService提供的功能。

b.appOps.noteOp()用来判断蓝牙开关权限AppOpsManager.OP_BLUETOOTH_CHANGE是否为AppOpsManager.MODE_ALLOWED,是的话就继续执行打开蓝牙的流程,否的话就立即退出。

  1. 在AppOpsManager里有:

a. 以 MODE_ 开头的权限模式

MODE_ALLOWED = 0 //允许执行

MODE_IGNORED = 1 //忽略请求,不允许执行

MODE_ERRORED = 2 //发生错误,不允许执行

MODE_DEFAULT = 3 //调用者需使用默认的安全检查方法,不常用

MODE_ASK = 4 //弹出对话框让用户选择允许或不允许执行

b. 以 OP_ 开头的各个具体操作权限

OP_COARSE_LOCATION = 0 //试图获取位置信息

OP_CALL_PHONE = 13; //试图拨打电话

OP_BLUETOOTH_CHANGE = 49 //试图开关蓝牙

OP_SEND_MMS = 50 //试图发送彩信

...

c. mService : IAppOpsService,代表AppOpsService服务,用于调用AppOpsService里实现的功能

d. isStrictEnable() : boolean 通过System Properties中的persist.sys.strict_op_enable来判断是否要开启AppOps功能

e. noteOp() 这个接口是用来权限提醒和保存。

  1. AppOpsManager.noteOp()的实现:

mService.noteOperation(op, uid, packageName) 进入了AppOpsService.noteOperation()的处理流程

  1. AppOpsService接收AppOpsManager发过来的调用指令,开始执行noteOperation()。在noteOperation()里会调用到 getOpsLocked() 和 getOpLocked() 来取得权限模式,然后根据获取到的mode判断是否给予允许执行,或则弹出对话框让用户选择。

  2. 在相应的操作权限还未鉴权过的,在getOpLocked()里会调用到getDefaultMode()用于获取代码里数组AppOpsManager.sOpDefaultStrictMode和文件appops_policy.xml中预配置模式。

  3. mPolicy是AppOpsPolicy的实例,在AppOpsPolicy中实现了对appops_policy.xml的读取和解析。

  4. AppOpsPolicy.getDefualtMode(int code, String packageName),根据appops_policy.xml中获取权限模式。在appops_policy.xml中我们看到:

xml 复制代码
<user-app permission="ask" show="true"/>                                  
<system-app permission="allowed" show="false"/>

user-app和system-app分别表示第三方应用和系统预装的应用,permission="ask"和permission="allowed"分别表示MODE_ASK和MODE_ALLOWED。所以第三方应用试图获取某项权限时都会弹出对话框让用户进行授权,而系统预装的应用试图获取某项权限时就直接被允许,无需用户授权,如本文开头所讲的系统自带的Settings里操作蓝牙开关没弹对话框就可以打开蓝牙开关。

xml 复制代码
<pkg name="com.android.calendar" type="system-app">                        
    <op name="android:read_contacts" permission="ask" show="true"/>        
</pkg>

<pkg> 里是对指定App中的特定操作权限进行配置。

  1. 假如获取到的权限模式为MODE_ASK则调用askOperationLocked()弹出对话框,让用户进行授权:
相关推荐
666xiaoniuzi3 小时前
深入理解 C 语言中的内存操作函数:memcpy、memmove、memset 和 memcmp
android·c语言·数据库
沐言人生7 小时前
Android10 Framework—Init进程-8.服务端属性文件创建和mmap映射
android
沐言人生7 小时前
Android10 Framework—Init进程-9.服务端属性值初始化
android·android studio·android jetpack
沐言人生8 小时前
Android10 Framework—Init进程-7.服务端属性安全上下文序列化
android·android studio·android jetpack
追光天使8 小时前
【Mac】和【安卓手机】 通过有线方式实现投屏
android·macos·智能手机·投屏·有线
小雨cc5566ru8 小时前
uniapp+Android智慧居家养老服务平台 0fjae微信小程序
android·微信小程序·uni-app
一切皆是定数9 小时前
Android车载——VehicleHal初始化(Android 11)
android·gitee
一切皆是定数9 小时前
Android车载——VehicleHal运行流程(Android 11)
android
problc9 小时前
Android 组件化利器:WMRouter 与 DRouter 的选择与实践
android·java
图王大胜10 小时前
Android SystemUI组件(11)SystemUIVisibility解读
android·framework·systemui·visibility