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()弹出对话框,让用户进行授权:
相关推荐
zhangphil15 分钟前
Android图像显示,CPU的Skia与GPU的Vulkan高性能渲染系统
android
故事不长丨1 小时前
安卓相机开发:Camera、Camera2与CameraX的使用对比及选型指南
android·相机·camera·camerax·camera2·移动设备·相机开发
_李小白1 小时前
【Android 美颜相机】第七天:GLTextureView 解析
android·数码相机
honortech1 小时前
Android studio中配置gradle和对应的AGP版本
android·ide·android studio
廋到被风吹走2 小时前
【数据库】【MySQL】事务隔离深度解析:MVCC 实现与幻读解决机制
android·数据库·mysql
AC赳赳老秦2 小时前
技术文档合著:DeepSeek辅助多人协作文档的风格统一与内容补全
android·大数据·人工智能·微服务·golang·自动化·deepseek
赛恩斯2 小时前
安卓构建工具D8和R8的区别
android
—Qeyser2 小时前
Flutter CustomScrollView 自定义滚动视图 - 完全指南
android·flutter·ios
鸣弦artha2 小时前
Flutter 框架跨平台鸿蒙开发 —— Image Widget 图片处理:圆角、裁剪、阴影
android·flutter·harmonyos
—Qeyser3 小时前
Flutter ListView 列表组件完全指南
android·flutter·ios