AOSP Intent.getExtras的一个坑
注:非AOSP原生代码已做脱敏处理
工作中做了一个需求,其中一部分是想把系统进程里读到的一些数据,在应用进程启动Activity的时候去读取。
大致流程是通过自定义接口读到数据后传入ActivityOptions,然后通过ActivityOptions在ActivityThread里传给ActivityRecord里的Intent。通过AOSP的Intent.putExtras()放数据,应用进程启动时通过Intent.getExtras()读取。具体实现如下:
ActivityStarter
AOSP代码地址:https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/wm/ActivityStarter.java
Activity启动时通过execute()函数走到executeRequest()函数,入参Request类可以获得Activity启动的一些信息request.activityOptions。

Activity的启动通过startActivityUnchecked,其中第一个参数r为ActivityRecord对象

r初始化过程中将checkedOptions作为入参设置为ActivityOptions

于是在初始化之前通过我的自定义接口返回带有我自己数据的ActivityOptions
在https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/wm/ActivityStarter.java中加入接口调用
在启动Activity的时候,核心代码是ActivityThread中的performLaunchActivity()方法

在大致3230行处,我试图通过之前的ActivityOptions读到数据
但是运行App时获得报错,报错栈如下:
在intent.getExtras()报了ClassNotFoundException,猜测原因是App将自定义类的数据也放入了intent的mExtra中,但默认ClassLoader不知道这个类,在intent.getExtras()时的反序列化报错。但是这说不通,因为App本身是一定会知道自定义类的定义的,但在这里却不知道了。后来继续看performLaunchActivity的实现发现:

performLaunchActivity会获得App的ClassLoader并设置为mExtra的ClassLoader
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/content/Intent.java

所以精简过程为:intent.getExtras()返回的mExtras是一个Bundle类,Bundle类的初始化需要对里面的所有数据反序列化。App塞入了一个自定义的类在intent的mExtras里,但我们在获取mExtras的时候时机过早,Bundle还在使用系统默认的ClassLoader而获取不到相关自定义类的信息,导致ClassNotFoundException。而performLaunchActivity中会给mExtras做加载App的ClassLoader的操作。所以将代码后移即可解决问题。这个想法也通过issuetracker得到了证实:
https://issuetracker.google.com/issues/37053389

