0

I am investigating behavior of android's View traversals and measure cache, using the AOSP source code and emulator.

I would like to emit debug log messages from each of the functions View.measure(), View.layout(), View.draw(), from all processes in which they are called.

Sounds straightforward, right? But I haven't found a mechanism that works reliably, yet.

What I tried:

  1. The standard logging mechanism: java.util.Log (and view using logcat).

    FAIL: Drops messages at random when there are too many of them.

  2. Creating and appending to a file in directory Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).

    FAIL: This only works for some processes (those with WRITE_EXTERNAL_STORAGE permission, presumably).

  3. Creating and appending to a file in directory view.getContext().getCacheDir().

    FAIL: The call to getCacheDir() fails in system_process, with: "java.lang.RuntimeException: No data directory found for package android".

  4. Creating and appending to a file in directory view.getContext().getExternalCacheDir().

    FAIL: This seems to work for all processes except system_process, in which getExternalCacheDir() returns /storage/emulated/0/Android/data/android/cache, but attempting to write to a file in there gives AccessDeniedException.

  5. Creating and appending to a file in directory view.getContext().getExternalFilesDir(null).

    FAIL: Same result as (4), except the directory name ends with "files" instead of "cache".

  6. Creating and appending to a file in /data/local/tmp.

    FAIL: Gives AccessDeniedException in all processes.

How can I do this logging??

I'd be interested in concrete solutions along any of the following lines:

  • Hack AOSP source to keep java.util.Log from dropping messages
  • Write an alternative logging daemon, which doesn't drop messages and must be made available during system startup (so that it will be available to processes such as system_process and com.android.systemui).
  • Just find a directory/file that system_process is allowed to write to (I think that's the only process for which I couldn't find such a file)
  • Hack AOSP source to make it so system_process has permission to write to some file.
Don Hatch
  • 5,041
  • 3
  • 31
  • 48

2 Answers2

0

About Logcat white/black list:
android logcat logs chatty module line expire message

You can grant permission manually if you want to pile the log on external storage:
How do I use adb grant or adb revoke?

Are you really want to log behavior of android's View traversals and measure cache across all processes? Starting with massive piles of log is not a good solution. I think.

Updated: 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);
        }
    }
}

This code will grant WRITE_EXTERNAL_STORAGE permission to all packages. Not tested. Can not recommend.

You Kim
  • 2,355
  • 1
  • 10
  • 11
  • Thanks for the info. Unfortunately I'm not able to make use of any of your suggestions. Evidently the "chatty expire" mechanism isn't getting triggered for me, for some reason (if I test by emitting far more than 5 lines per second, I never see the "chatty" message, I just see some log lines missed). Regarding adb grant, that apparently works only in the very limited case of an app that has already declared the permission as an "optional" permission; most apps of interest haven't, and in particular system_process isn't even an app. Regarding whether I really want to do this: yes, I do. – Don Hatch Mar 03 '18 at 23:27
  • I'd actually be fine with simply allowing all processes WRITE_EXTERNAL_STORAGE access systemwide on my emulator, if I knew what to tweak in the AOSP source. – Don Hatch Mar 03 '18 at 23:32
0

I found the following directories that each process can apparently create files in and write to; so, make each process create a file for its logging/tracing in the respective directory. There are apparently two cases which must be treated completely separately.

  • "system_process" (aka "system_server" aka "system") (NOT the same as "com.android.system.ui") can write to:
    • Environment.getDataDirectory() = "/data"
    • Environment.getDownloadCacheDirectory() = "/data/cache"
    • Environment.getDataSystemDirectory() = "/data/system"
  • All other processes that make UIs can write to:
    • 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" or "/data/user_de/0/app.name.appears.here/cache"
    • context.getFilesDir() = "/data/user/0/app.name.appears.here/files" or "/data/user_de/0/app.name.appears.here/files"

Note: the string literals listed above are what I observed each function to return on my emulator built from AOSP sources; I wouldn't assume it's safe to hard-code them.

Don Hatch
  • 5,041
  • 3
  • 31
  • 48