如何从框架 ui 代码中可靠地调试日志记录?

How to do debug logging robustly from framework ui code?

我正在调查 android 的视图遍历和测量缓存的行为, 使用 AOSP 源代码和模拟器。

我想从每个函数发出调试日志消息 View.measure(), View.layout(), View.draw(), 来自调用它们的所有进程。

听起来很简单,对吧?但是我还没有找到可靠的机制。

我尝试了什么:

  1. 标准日志记录机制:java.util.Log(并使用 logcat 查看)。

    失败:当消息过多时随机丢弃消息。

  2. 创建并附加到目录中的文件 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).

    失败:这仅适用于某些进程(那些 WRITE_EXTERNAL_STORAGE 许可,大概)。

  3. 正在目录 view.getContext().getCacheDir().

    中创建并附加到文件

    FAIL:调用 getCacheDir() 在 system_process 中失败,原因是: "java.lang.RuntimeException: No data directory found for package android".

  4. 正在目录 view.getContext().getExternalCacheDir().getExternalCacheDir().

    中创建并追加文件

    失败:这似乎适用于除 system_process 之外的所有进程, 其中 getExternalCacheDir() returns /storage/emulated/0/Android/data/android/cache, 但是尝试写入其中的文件会出现 AccessDeniedException。

  5. 在目录 view.getContext().getExternalFilesDir(null).

    中创建并附加文件

    失败:与 (4) 相同的结果,除了目录名称以 "files" 而不是 "cache" 结尾。

  6. 正在 /data/local/tmp.

    中创建并附加到文件

    失败:在所有进程中出现 AccessDeniedException。

我该如何记录日志?

我会对以下任一方面的具体解决方案感兴趣:

关于Logcatwhite/black列表:
android logcat logs chatty module line expire message

如果你想把日志堆到外部存储,你可以手动授予权限:
How do I use adb grant or adb revoke?

您真的要记录 android 的视图遍历行为并测量跨所有进程的缓存吗?从大量日志开始并不是一个好的解决方案。我认为。

更新: DefaultPermissionGrantPolicy.java

public void grantDefaultPermissions(int userId) {
    grantPermissionsToSysComponentsAndPrivApps(userId);
    grantDefaultSystemHandlerPermissions(userId);
    grantDefaultPermissionExceptions(userId);
    grantWriteExternalPermissionsToAllApps(userId); // added.
}

private void grantWriteExternalPermissionsToAllApps(int userId) {
    synchronized (mService.mPackages) {
        for (PackageParser.Package pkg : mService.mPackages.values()) {

            Set<String> permissions = new ArraySet<>();
            permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);

            grantRuntimePermissionsLPw(pkg, permissions, true, userId);
        }
    }
}

此代码将授予对所有包的 WRITE_EXTERNAL_STORAGE 权限。未经测试。不能推荐。

我发现每个进程显然都可以在其中创建文件和写入以下目录;因此,让每个进程在各自的目录中为其 logging/tracing 创建一个文件。 显然有两种情况必须完全分开处理。

  • "system_process"(又名 "system_server" 又名 "system")(与 "com.android.system.ui" 不同)可以写入:
    • Environment.getDataDirectory() = "/数据"
    • Environment.getDownloadCacheDirectory() = "/data/cache"
    • Environment.getDataSystemDirectory() = "/data/system"
  • 创建 UI 的所有其他进程都可以写入:
    • context.getExternalCacheDir() = "/storage/emulated/0/Android/data/app.name.appears.here/cache"
    • context.getExternalFilesDir(null) = "/storage/emulated/0/Android/data/app.name.appears.here/files"
    • context.getCacheDir() = "/data/user/0/app.name.appears.here/cache" 或 "/data/user_de/0/app.name.appears.here/cache
    • context.getFilesDir() = "/data/user/0/app.name.appears.here/files" 或 "/data/user_de/0/app.name.appears.here/files

注意:上面列出的字符串文字是我在从 AOSP 源构建的模拟器上观察到 return 的每个函数;我不认为 hard-code 他们是安全的。