java编译高级玩法:locked_region_code_injection

今天阅读Android Q WM代码时发现了一个高级的玩法,看名字就知道是通过注入方式实现自动为锁区域前后添加代码的方法。发现过程如下:

一段莫名其妙的注释

https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-mainline-10.0.0_r3/services/core/java/com/android/server/wm/ActivityTaskManagerService.java#362

    /* Global service lock used by the package the owns this service. */
    final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock();
    /**
     * It is the same instance as {@link mGlobalLock}, just declared as a type that the
     * locked-region-code-injection does't recognize it. It is used to skip wrapping priority
     * booster for places that are already in the scope of another booster (e.g. computing oom-adj).
     *
     * @see WindowManagerThreadPriorityBooster
     */
    final Object mGlobalLockWithoutBoost = mGlobalLock;

每个词都能读懂,但合起来就似是而非的不太明白。为什么相同的锁对象要弄出两个引用?什么叫跳过优先级加速器的包围。搜索这两个锁的用法似乎也没有特别的差异。还好有进一步提示@see WindowManagerThreadPriorityBooster

没有地方使用的静态方法

WindowManagerThreadPriorityBooster本身代码比较好懂,就是根据情况调整线程优先级达到加速效果。关键是初始化和调用它的地方:
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-mainline-10.0.0_r3/services/core/java/com/android/server/wm/WindowManagerService.java#873

    static void boostPriorityForLockedSection() {
        sThreadPriorityBooster.boost();
    }
    static void resetPriorityAfterLockedSection() {
        sThreadPriorityBooster.reset();
    }

从函数名称就能猜到肯定是在作用域前后调用这两个函数达到boost和reset的效果,燃鹅,搜索这个两个函数的调用地方,竟然没有?!?!

抓住了你的小尾巴

多亏我习惯使用OpenGrok来做项目代码搜索,马上还是发现了端倪


locked_injection_1.png

https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-mainline-10.0.0_r3/services/core/Android.bp#66

locked_injection_2.png

  1. 编译脚本里面做猫腻
  2. art-profile标记函数避免java编译时的空检查
    真相只有一个,这是用来直接注入到java生成的字节码中的!!

证据确凿验证猜想

直接去看lockedregioncodeinjection的源码,果然是个读取字节码然后转换输出的工具。具体逻辑就不深究了:
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-mainline-10.0.0_r3/tools/locked_region_code_injection/src/lockedregioncodeinjection/Main.java#80

locked_injection_3.png

又回到最初的起点

final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock();
final Object mGlobalLockWithoutBoost = mGlobalLock;

至此就能真正读懂开头那段注释了,使用locked-region-code-injection做代码注入的目标是WindowManagerGlobalLock,也就是只对mGlobalLock的锁区域做加速和恢复。而如果使用mGlobalLockWithoutBoost锁就表明:

  1. 这段区域可能已经被包含在mGlobalLock以经过加速
  2. 这段区域有其他带有加速的区域,例如AMS,看Android.bp中locked-region-code-injection的参数可知
  3. 这段区域不需要加速

你可能感兴趣的:(java编译高级玩法:locked_region_code_injection)