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()弹出对话框,让用户进行授权:
相关推荐
移动开发者1号38 分钟前
使用 Android App Bundle 极致压缩应用体积
android·kotlin
移动开发者1号40 分钟前
构建高可用线上性能监控体系:从原理到实战
android·kotlin
ii_best6 小时前
按键精灵支持安卓14、15系统,兼容64位环境开发辅助工具
android
美狐美颜sdk6 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
恋猫de小郭10 小时前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin
aqi0011 小时前
FFmpeg开发笔记(七十七)Android的开源音视频剪辑框架RxFFmpeg
android·ffmpeg·音视频·流媒体
androidwork13 小时前
深入解析内存抖动:定位与修复实战(Kotlin版)
android·kotlin
梦天201513 小时前
android核心技术摘要
android
szhangbiao15 小时前
“开发板”类APP如果做屏幕适配
android
高林雨露16 小时前
RecyclerView中跳转到最后一条item并确保它在可视区域内显示
android