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()弹出对话框,让用户进行授权:
相关推荐
ajassi20004 分钟前
开源 java android app 开发(十八)最新编译器Android Studio 2025.1.3.7
android·java·开源
用户20187928316712 分钟前
Java 泛型:快递站老板的 "类型魔法" 故事
android
Knight_AL26 分钟前
浅拷贝与深拷贝详解:概念、代码示例与后端应用场景
android·java·开发语言
夜晚中的人海1 小时前
【C++】智能指针介绍
android·java·c++
用户2018792831672 小时前
后台Activity输入分发超时ANR分析(无焦点窗口)
android
用户2018792831672 小时前
Activity配置变化后ViewModel 的 “不死之谜”
android
游戏开发爱好者83 小时前
BShare HTTPS 集成与排查实战,从 SDK 接入到 iOS 真机调试(bshare https、签名、回调、抓包)
android·ios·小程序·https·uni-app·iphone·webview
2501_916008893 小时前
iOS 26 系统流畅度实战指南|流畅体验检测|滑动顺畅对比
android·macos·ios·小程序·uni-app·cocoa·iphone
2501_915106325 小时前
苹果软件加固与 iOS App 混淆完整指南,IPA 文件加密、无源码混淆与代码保护实战
android·ios·小程序·https·uni-app·iphone·webview
2501_915921435 小时前
iOS 26 崩溃日志解析,新版系统下崩溃获取与诊断策略
android·ios·小程序·uni-app·cocoa·iphone·策略模式