有效地使用 AppOpsManager.OnOpNotedCallback

问题描述

我们正在使用新的 AppOpsManager.OnopNotedCallback 实施关键区域使用情况审核。我们遇到的问题是,某些外部库会自行获取某些操作的上下文,这意味着我们没有指定任何 attributionTag。另一个问题是,对于 onAsyncNoted 回调(这是我们实际得到的所有),堆栈跟踪对于尝试解决关键区域访问的来源没有帮助。

此类堆栈跟踪示例:

E/CriticalAreaAccessAuditer: Private data accessed. Operation: android:record_audio; Attribution tag: null; Message: Audio recording on session 409; Stack Trace:
net.example.criticalareaaudit.CriticalAreaAccessAuditer$initialize$appOpsCallback$2$1.onAsyncNoted(CriticalAreaAccessAuditer.kt:59)
android.app.AppOpsManager$OnopNotedCallback$1.lambda$opNoted$0$AppOpsManager$OnopNotedCallback$1(AppOpsManager.java:9342)
android.app.AppOpsManager$OnopNotedCallback$1$$ExternalSyntheticLambda0.run(UnkNown Source:4)
android.os.Handler.handleCallback(Handler.java:938)
android.os.Handler.dispatchMessage(Handler.java:99)
android.os.Looper.loopOnce(Looper.java:201)
android.os.Looper.loop(Looper.java:288)
android.app.ActivityThread.main(ActivityThread.java:7796)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:974)

我们的 onAsyncNoted 代码

    override fun onNoted(op: SyncNotedAppOp) {
        logPrivateDataAccess(op.op,op.attributionTag,Throwable().stackTrace.joinToString("\n").trim())
    }

    override fun onSelfNoted(op: SyncNotedAppOp) {
        logPrivateDataAccess(op.op,Throwable().stackTrace.joinToString("\n").trim())
    }

    override fun onAsyncNoted(asyncop: AsyncNotedAppOp) {
        logPrivateDataAccess(asyncop.op,asyncop.attributionTag,Throwable().stackTrace.joinToString("\n").trim(),asyncop.message)
    }
    
    private fun logPrivateDataAccess(operation: String,attributionTag: String?,trace: String,message: String? = null) {
        Timber.e("Private data accessed. Operation: $operation; Attribution tag: $attributionTag; Message: $message; Stack Trace:\n$trace")
    }

我们注意到的另一件事是,对于关键区域操作的自我记录,attributionTag 和 message 是空的,即使它们被设置并且调用返回 AppOpsManager.MODE_ALLOWED:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    appOpsManager.noteOp(AppOpsManager.OPSTR_RECORD_AUdio,myUid(),packageName = "net.example",attributionTag = "SomeManager",message = "SomeManager.doThing()")
}

产生这个输出(至少在这里我们可以帮助自己使用 stackTrace,但是依赖 attributionTag 仍然更好,因为我们已经设置了它):

E/CriticalAreaAccessAuditer: Private data accessed. Operation: android:record_audio; Attribution tag: null; Message: null; Stack Trace:
E/CriticalAreaAccessAuditer: net.example.criticalareaaudit.CriticalAreaAccessAuditer$initialize$appOpsCallback$2$1.onSelfNoted(CriticalAreaAccessAuditer.kt:58)
E/CriticalAreaAccessAuditer: android.app.AppOpsManager.collectNotedOpForSelf(AppOpsManager.java:8943)
E/CriticalAreaAccessAuditer: android.app.AppOpsManager.noteOpNoThrow(AppOpsManager.java:8150)
E/CriticalAreaAccessAuditer: android.app.AppOpsManager.noteOp(AppOpsManager.java:8087)
E/CriticalAreaAccessAuditer: android.app.AppOpsManager.noteOp(AppOpsManager.java:8077)
E/CriticalAreaAccessAuditer: net.example.manager.someManager$doThing$2.apply(SomeManager.kt:96)
E/CriticalAreaAccessAuditer: net.example.manager.someManager$doThing$2.apply(SomeManager.kt:31)

归根结底,问题是如何通过外部库有效地使用 AppOpsManager.OnopNotedCallback 来审核和区分允许和不允许的关键区域访问。目前看来,AppOpsManager.OnopNotedCallback 并不能真正胜任大型复杂应用程序的任务。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)