1.背景介绍
目前基于Gradle编译的字节码插装方案已经很成熟,比较知名的开源库有微信开源的Matrix,这里不过多介绍。
SystemUI是基于Android源码编译的,需要随着Rom打整包,所以需要探索出基于源码编译的字节码插装方案。
在 cs.android.com 上搜索 asm 相关类库引用,发现了 lockedregioncodeinjection 这一jar包,是针对AMS做字节码插装定制的,
基于此探索出SystemUI源码编译字节码插装方案。
2.genrule介绍
genrule是用来生成文件的,当且仅当编译过程中存在依赖关系时才会触发。
以SystemUI中shared模块为例:statslog-SystemUI-java-gen
genrule {
name: "statslog-SystemUI-java-gen",
tools: ["stats-log-api-gen"],
cmd: "$(location stats-log-api-gen) --java $(out) --module sysui --javaPackage com.android.systemui.shared.system --javaClass SysUiStatsLog",
out: ["com/android/systemui/shared/system/SysUiStatsLog.java"],
}
java_library {
name: "SystemUI-statsd",
srcs: [
":statslog-SystemUI-java-gen",
],
}
编译 SystemUI-statsd.jar 时依赖 statslog-SystemUI-java-gen 生成的文件,因此才会触发执行 stats-log-api-gen.jar 生成 SysUiStatsLog.java 文件。
在回过头来看genrule的配置文件:
tools传入的是可在命令行下运行的jar包,即指定main()入口的jar包。
在bp文件中可使用 cc_binary_host 或 java_binary_host 生成指定main()入口的jar包,可参考:stats-log-api-gen。
cmd是在命令行下如何执行tools指定的jar包,例如配置指令参数。
这里有两个特殊的参数,(out)对应的是genrule配置的out。
3.SystemUI源码编译字节码插装方案
在编译 SystemUI.apk 前,会将所有代码编译成一个 SystemUI-core.jar 包,
因此在生成 SystemUI-core.jar 之后,在生成 SystemUI.apk 之前,我们需要添加一个genrule依赖执行插装过程。
具体方案如下:
定义了一个新的jar包 SystemUI-injection 模块,其依赖 systemui-code-injection 的生成java文件,
java_library {
name: "SystemUI-injection",
srcs: [":systemui-code-injection"],
}
而 systemui-code-injection 依赖 SystemUI-core 模块,这样就保证了 systemui-code-injection 是在生成 SystemUI-core.jar 之后运行。
再使编译apk模块 SystemUI 依赖 SystemUI-injection,这样就保证了 systemui-code-injection 在生成 SystemUI.apk 前运行。