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()弹出对话框,让用户进行授权:
相关推荐
诺诺Okami1 分钟前
Android Framework-Launcher-InvariantDeviceProfile
android
Antonio9151 小时前
【音视频】Android NDK 与.so库适配
android·音视频
sun00770010 小时前
android ndk编译valgrind
android
AI视觉网奇11 小时前
android studio 断点无效
android·ide·android studio
jiaxi的天空11 小时前
android studio gradle 访问不了
android·ide·android studio
No Silver Bullet12 小时前
android组包时会把从maven私服获取的包下载到本地吗
android
catchadmin12 小时前
PHP serialize 序列化完全指南
android·开发语言·php
tangweiguo0305198714 小时前
Kable使用指南:Android BLE开发的现代化解决方案
android·kotlin
00后程序员张16 小时前
iOS App 混淆与资源保护:iOS配置文件加密、ipa文件安全、代码与多媒体资源防护全流程指南
android·安全·ios·小程序·uni-app·cocoa·iphone
柳岸风18 小时前
Android Studio Meerkat | 2024.3.1 Gradle Tasks不展示
android·ide·android studio