一、简介
监听隐私运行时权限调用: 此流程在搭载 Android 11(API 级别 30)及更高版本的设备上可用,可让您更好地识别可能出现的意外数据访问。您的应用可以注册 AppOpsManager.OnOpNotedCallback 实例,该实例可在每次发生以下任一事件时执行相应操作:
- 应用的代码访问私密数据。为了帮助您确定应用的哪个逻辑部分调用了事件,您可以按归因标记审核数据访问。
- 依赖库或 SDK 中的代码访问私密数据。
数据访问审核是在发生数据请求的线程上调用的。这意味着,如果应用中的第三方 SDK 或库调用访问私密数据的 API,您的 OnOpNotedCallback 可以调用数据访问审核检查有关该调用的信息。通常,此回调对象可以通过查看应用的当前状态(例如当前线程的堆栈轨迹)以判断调用是来自您的应用还是来自 SDK。
二、使用
1. 监听单个activity
如需使用 AppOpsManager.OnOpNotedCallback 实例执行数据访问审核,请在您打算审核数据访问的组件中实现回调逻辑,例如在某个 Activity 的 onCreate() 方法中。
2. 全局监听
创建自定义子类 Application,并在子类的 onCreate() 方法中定义 AppOpsManager.OnOpNotedCallback。
执行注册监听
override fun onCreate(savedInstanceState: Bundle?) {
val onOpNotedCallback = object : AppOpsManager.OnOpNotedCallback() {
// 保存和记录信息。可能从不同线程调用,因此同步。可以进一步优化到只处理可变列表MutableList 的部分。
/**
* @param operation 操作
* @param stackTrace 堆栈跟踪
*/
@Synchronized
private fun saveAndLog(operation: String, stackTrace: String) {
// 将 操作和堆栈信息,存到opsNotedForThisApp
opsNotedForThisApp.add(Pair(operation, stackTrace))
// Log
Log.d(TAG, "saveAndLog" + operation)
Log.d(TAG, "saveAndLog stackTrace:" + stackTrace)
// 输出到屏幕outputTextView
val operationsOnly = opsNotedForThisApp.map { "- ${it.first}" }
runOnUiThread {
binding.outputTextView.text =
operationsOnly.joinToString("\n", "Check Log for stacktrace.\n", "\n")
}
}
/**
* onNoted—通过同步调用访问受保护数据时调用。例如,如果应用程序请求用户的最后一个已知位置,并且该函数立即返回值synchronous,则会触发onNoted。
*/
override fun onNoted(operation: SyncNotedAppOp) {
// 获取 操作operation.op 和 归因
val operationDescription =
prettyOperationDescription("onNoted()", operation.op, operation.attributionTag)
// 获取当前线程的堆栈信息
val prettyStackTrace = prettyStackTrack(Thread.currentThread().stackTrace)
saveAndLog(operationDescription, prettyStackTrace)
}
/**
* onAsyncNoted—通过异步回调访问受保护数据时调用。例如,如果某个应用程序订阅的位置发生了更改,
* 则在调用具有新位置的回调时将触发onAsyncNoted。地理围栏是另一个例子。
*
* 重要提示:由于您正在等待GPS信号更新,因此单击按钮后可能需要一两分钟才能显示。
*/
override fun onAsyncNoted(asyncOp: AsyncNotedAppOp) {
val operationDescription =
prettyOperationDescription("onAsyncNoted()", asyncOp.op, asyncOp.attributionTag)
// 对于AsyncNotedAppOp,使用“message”字段而不是检索当前线程的堆栈跟踪来标识调用更有效。
val message = asyncOp.message
saveAndLog(operationDescription, message)
}
/**
* onSelfNoted—当开发人员调用{@link android.app.apppsmanager#noteOp}
* 手动触发受保护的数据访问时调用。这是系统未触发的唯一回调。
* 当应用程序感觉自己正在访问受保护的数据并想要对其进行审核时,这是一种自责的方式
*
* 这是一个相当罕见的用例,所以在大多数情况下,您不需要这样做。
*/
override fun onSelfNoted(operation: SyncNotedAppOp) {
val operationDescription =
prettyOperationDescription("onSelfNoted()", operation.op, operation.attributionTag)
val prettyStackTrace = prettyStackTrack(Thread.currentThread().stackTrace)
saveAndLog(operationDescription, prettyStackTrace)
}
}
val appOpsManager =
getSystemService(AppOpsManager::class.java) as AppOpsManager
appOpsManager.setOnOpNotedCallback(mainExecutor, appOpsCallback)
}
三、按归因【Attribution】标记审核数据访问
如果您在某个 Activity 中访问数据(例如请求位置信息或访问用户的联系人列表),请在该 Activity 的 onCreate() 方法中调用 createAttributionContext(),并传入您希望与应用的一部分相关联的归因标记。
以下代码段展示了如何为应用的“照片位置信息分享”部分创建归因标记:
class SharePhotoLocationActivity : AppCompatActivity() {
lateinit var attributionContext: Context
override fun onCreate(savedInstanceState: Bundle?) {
attributionContext = createAttributionContext("sharePhotos")
}
fun getLocation() {
val locationManager = attributionContext.getSystemService(
LocationManager::class.java) as LocationManager
// Use "locationManager" to access device location information.
}
}
在 回调中拿到归因tag,知道调用原因
val appOpsCallback = object : AppOpsManager.OnOpNotedCallback() {
// attributionTag 归因tag
private fun logPrivateDataAccess(
opCode: String, attributionTag: String, trace: String) {
Log.i(MY_APP_TAG, "Private data accessed. " +
"Operation: $opCode\n " +
"Attribution Tag:$attributionTag\nStack Trace:\n$trace")
}
override fun onNoted(syncNotedAppOp: SyncNotedAppOp) {
logPrivateDataAccess(syncNotedAppOp.op,
syncNotedAppOp.attributionTag,
Throwable().stackTrace.toString())
}
override fun onSelfNoted(syncNotedAppOp: SyncNotedAppOp) {
logPrivateDataAccess(syncNotedAppOp.op,
syncNotedAppOp.attributionTag,
Throwable().stackTrace.toString())
}
override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp) {
logPrivateDataAccess(asyncNotedAppOp.op,
asyncNotedAppOp.attributionTag,
asyncNotedAppOp.message)
}
}
四、权限列表
运行时权限:
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
group:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
group:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
group:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS
普通权限
ACCESS_LOCATION_EXTRA_COMMANDS 定位权限
ACCESS_NETWORK_STATE 网络状态权限
ACCESS_NOTIFICATION_POLICY 通知 APP通知显示在状态栏
ACCESS_WIFI_STATE WiFi状态权限
BLUETOOTH 使用蓝牙权限
BLUETOOTH_ADMIN 控制蓝牙开关
BROADCAST_STICKY 粘性广播
CHANGE_NETWORK_STATE 改变网络状态
CHANGE_WIFI_MULTICAST_STATE 改变WiFi多播状态,应该是控制手机热点(猜测)
CHANGE_WIFI_STATE 控制WiFi开关,改变WiFi状态
DISABLE_KEYGUARD 改变键盘为不可用
EXPAND_STATUS_BAR 扩展bar的状态
GET_PACKAGE_SIZE 获取应用安装包大小
INTERNET 网络权限
KILL_BACKGROUND_PROCESSES 杀死后台进程
MODIFY_AUDIO_SETTINGS 改变音频输出设置
NFC 支付
READ_SYNC_SETTINGS 获取手机设置信息
READ_SYNC_STATS 数据统计
RECEIVE_BOOT_COMPLETED 监听启动广播
REORDER_TASKS 创建新栈
REQUEST_INSTALL_PACKAGES 安装应用程序
SET_TIME_ZONE 允许应用程序设置系统时间区域
SET_WALLPAPER 设置壁纸
SET_WALLPAPER_HINTS 设置壁纸上的提示信息,个性化语言
TRANSMIT_IR 红外发射
USE_FINGERPRINT 指纹识别
VIBRATE 震动
WAKE_LOCK 锁屏
WRITE_SYNC_SETTINGS 改变设置
SET_ALARM 设置警告提示
INSTALL_SHORTCUT 创建快捷方式
UNINSTALL_SHORTCUT 删除快捷方式