Application与Activity是Android中非常重要的组件之其二,当然更多提起的还是Activity,它与用户界面有更直接的关系;当点击设备App图标时,界面上展示给用户能看到过程中,就包含启动Application与Activity的过程。应用运行的一刻,Android系统会为应用创建一个Application对象,这个对象有数据传递、数据共享和数据缓存等功能,它就如同一个容器一样,可以在里面存取信息。而Activity在启动后它就像是一个载体,这个载体如同窗口一样,解析开发定义好的内容(xml定义控件)解析然后展示在这个窗口中,然后用户看到这个载体的内容,在内容有操作后Activity会拿到用户的操作并反馈。
为什么要说到Application?
在一系列Android基础学习上都是基于对Android应用测试更深的碰触,每一次的困惑都需要通过这些基础去解决。在学习UiAutomator基于Instrumentation运行的过程中,就引发出Instrumentation到底是什么东东,从而到了Application对象的创建。下面进入源码分析
一、InStrumentation的OnCreate过程
用户点击应用程序,首先先创建一个应用进程,然后进入到ActivityThread的main方法中,ActivityThread类通常就是我们说的UI线程(主线程),一个进程对应一个ActivityThread,用于调度Activity的生命周期,Service的生命周期,以及调度Instrumentation的创建。
1.执行ActivityThread的main函数,初始化一个ActivityThread实例,然后调用attach方法。顺便提提在说Looper原理中提到的主线程自动创建Looper对象的源码也是这里。
public static void main(String[] args) {
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}Looper.loop();
}
2.在ActivityThread这个类中是有一个Instrumentation成员变量mInstrumentation。执行attach方法,入参是false,在attach的if语句块中变成ture,并没有对mInstrumentation做任何事情,所以mInstrumentation还是一个空对象。然后主要看一下ActivityManagerNative.getDefault()得到一个IactivityManager对象,然后执行了attachApplication方法。但是通过源码可以看到IActivityManager它是一个接口,而实现这个接口的就是ActivityManagerNative类。
final ApplicationThread mAppThread = new ApplicationThread();
private void attach(boolean system) {
if (!system) {
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
} else {mInstrumentation = new Instrumentation();
}
}
3.继续看getDefault方法
(1)调用的是gDefault方法
static public IActivityManager getDefault() {
return gDefault.get();
}
(2)通过ServiceManager.getService()获得了一个IBinder引用,这个IBinder引用其实就是ActivityManagerService的引用。
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
(3)因为在在SystemServer中会调用ActivityManagerService的setSystemProcess()方法:在setSystemProcess()中,会调用ServiceManager的addService()方法,把ActivityManagerService的引用存储到ServiceManager中进行管理。所以现在通过ServiceManager.getService()取出的activity实际就是ActivityManagerService(Context.ACTIVITY_SERVICE的值就是activity)。
public void setSystemProcess() {
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
ServiceManager.addService("meminfo", new MemBinder(this));
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));
}
(4)然后把这个ActivityManagerService这个引用作为入参调用了asInterface方法,最后返回一个ActivityManagerProxy,这个ActivityManagerProxy是实现IActivityManager接口的
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}return new ActivityManagerProxy(obj);
}
4.然后回到ActivityThread的attach方法,调用了attachApplication方法,这个方法在ActivityManagerProxy中也有,但是ActivityManagerService复写了这个方法,所以调用的是ActivityManagerService的attachApplication方法,入参的是ApplicationThread,它是ActivityThread的内部类继承了ApplicationThreadNative类,而ApplicationThreadNative类又是继承了Binder类,所以在这里ApplicationThread充当了Binder的作用,来到ActivityManagerService的attachApplication方法
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
5.调用了ActivityManagerService的attachApplicationLocked方法
ActivityStackSupervisor mStackSupervisor;
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
mCoreSettingsObserver.getCoreSettingsLocked());if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
}
先看看ProcessRecord 实例app的通过mPidsSelfLocked这个集合拿到的,然后看thread.bindApplication这里,thread是入参的ApplicationThread对象,也就是调用了ApplicationThread的bindApplication方法,但是这里有一个很重要的入参app.instrumentationClass。先放在这里,后面说到Instrumentation还会继续说到这里;在执行完bindApplication()之后,会调用ActivityStackSupervisor的attachApplicationLocked()方法来,在该方法中会调用realStartActivityLocked()方法来启动一个Activity,这个Activity也就是我们默认的首页Activity,也是我们常用的MainActivity。
6.后面再看Activity,先记下往下看,调用的ApplicationThread的bindApplication方法
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) {AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableOpenGlTrace = enableOpenGlTrace;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
sendMessage(H.BIND_APPLICATION, data);
}
实例化一个AppBindData对象,然后给成员变量赋值,这里继续关注instrumentationName这个变量值,然后作为入参调用sendMessage。它是从ActivityManagerService的attachApplicationLocked方法中调用bindApplication方法入参的app.instrumentationClass就是这里的instrumentationName。H类它是ActivityThread的内部类,继承的是Handler,H.BIND_APPLICATION返回的值就是BIND_APPLICATION,然后调用了sendMessage方法。
7.ApplicationThread的sendMessage方法
private void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
而mH是实例化H类的实例,调用了mH的sendMessage方法发送一个Message消息对象(建议看一下Handler机制)
8.根据Handler机制,消息是由handleMessage处理的,所以来到了mH对象的handleMessage方法,在该方法中是一个switch,匹配BIND_APPLICATION是调用了handleBindApplication方法,入参是AppBindData对象。
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}
9.来到handleBindApplication方法,看核心代码,判断了data.instrumentationName的值是否为空,来决定在ActivityThread中Instrumentation实例化。
(1)不为空,通过ClassLoader的loadClass方法得到instrumentationName这个变量类名并实例化赋值给mInstrumentation,然后执行init初始化。
(2)为空则直接实例化Instrumentation对象。
private void handleBindApplication(AppBindData data) {
if (data.instrumentationName != null) {
try {
java.lang.ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
+ data.instrumentationName + ": " + e.toString(), e);
}mInstrumentation.init(this, instrContext, appContext,
new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,
data.instrumentationUiAutomationConnection);} else {
mInstrumentation = new Instrumentation();
}.......
mInstrumentation.onCreate(data.instrumentationArgs);
......
mInstrumentation.callApplicationOnCreate(app);}
然后往下看,实例化后mInstrumentation对象,调用了onCreate方法;然后再通过mInstrumentation调用了callApplicationOnCreate方法,而callApplicationOnCreate实际就是调用了Application的onCreate方法。所以说Instrumentation比Application先执行onCreate方法,而所谓的Activity,可以结合回到上面第5点更加是在Application之后了。
二、探究app.instrumentationClass的来源
判断data.instrumentationName的值为空来决定ActivityThread类中mInstrumentation对象是什么,所以要看看data.instrumentationName是什么?找到ActivityManagerService的attachApplicationLocked方法中调用bindApplication方法入参的app.instrumentationClass,在第6点中可以看到app是ProcessRecord对象,所以找到ProcessRecord类,根据ProcessRecord类知道instrumentationClass是ComponentName对象,但是在整个ProcessRecord类中并没有找到实例化instrumentationClass的代码。然后就是要看看ProcessRecord 通过mPidsSelfLocked这个集合get的,那么是在什么时候put的呢?put的ProcessRecord 对象有没有给成员变量instrumentationClass赋值呢?
先假设一下,在点击桌面APP图标启动应用时,data.instrumentationName是空的,所以走else语句块,new了一个Instrumentation对象运行。
然后再回顾到《Appium基础学习之 | UiAutomator2.0使用》文章中,UiAutomator基于Instrumentation运行的命令:
adb shell am instrument -w -r -e debug false -e 'ymxh.uiautomation.uiauto2test.ExampleInstrumentedTest' io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner
1.Shell执行am命令,在android源码包\frameworks\base\cmds\am目录下找到am的shell文件,打开后内容很简单,先引入am.jar包,然后运行com.android.commands.am.Am,$@表示全部参数
base=/system
export CLASSPATH=$base/framework/am.jar
exec app_process $base/bin com.android.commands.am.Am "$@"
2.在源码中找到Am.java类,找到主函数,实例化Am对象调用run方法。在Am中找不到入参为args参数的run方法,但是Am是继承了BaseCommand,所以调用的是BaseCommand的run方法。
public class Am extends BaseCommand {
private IActivityManager mAm
public static void main(String[] args) {
(new Am()).run(args);
}}
3.来到BaseCommand的run方法调用的是onRun(),Am重写了onRun()方法,所以又回到Am的onRun方法;在Am的onRun方法中,首先通过BaseCommand的nextArgRequired方法得到下一个子命令instrument,可以看到am很多子命令,如果后续有用到再说,这里重点是instrument,执行了runInstrument方法。
public void onRun() throws Exception {
mAm = ActivityManagerNative.getDefault();
String op = nextArgRequired();
else if (op.equals("instrument")) {
runInstrument();
}}
4.调用了Am的runInstrument方法
private void runInstrument() throws Exception {
String opt;
while ((opt=nextOption()) != null) {
if (opt.equals("-p")) {
profileFile = nextArgRequired();
} else if (opt.equals("-w")) {
wait = true;
} else if (opt.equals("-r")) {
rawMode = true;
} else if (opt.equals("-e")) {
argKey = nextArgRequired();
argValue = nextArgRequired();
args.putString(argKey, argValue);
} else if (opt.equals("--no_window_animation")
|| opt.equals("--no-window-animation")) {
no_window_animation = true;
} else if (opt.equals("--user")) {
userId = parseUserArg(nextArgRequired());
} else if (opt.equals("--abi")) {
abi = nextArgRequired();
} else {
System.err.println("Error: Unknown option: " + opt);
return;
}
}
一个while循环读取参数,如-w给wait赋值true,-r、-e开头后面的参数都拿到后赋值
ComponentName cn = ComponentName.unflattenFromString(cnArg);
然后cn是ComponentName对象,调用unflattenFromString方法返回。调用unflattenFromString方法入参的是cnArg,这个值通过BaseCommand的nextArgRequired方法获取下一个命令行中参数,也就是io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner这个参数。因为在前面的while循环已经把前面的参数都取出来了,最后一个就是io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner。
InstrumentationWatcher watcher = null;
UiAutomationConnection connection = null;
if (wait) {
watcher = new InstrumentationWatcher();
watcher.setRawOutput(rawMode);
connection = new UiAutomationConnection();
}
然后实例化InstrumentationWatcher、UiAutomationConnection两个对象
if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId, abi)) {
throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
}
}
再接着往下看mAm.startInstrumentation,mAm是在上面onRun方法通过ActivityManagerNative.getDefault()得到一个IActivityManager对象,这个在上面用到过啊,实际就是ActivityManagerService引用,然后调用了asInterface方法,最后返回一个ActivityManagerProxy。所以执行的是ActivityManagerProxy的startInstrumentation方法。
5.再接着往下看startInstrumentation入参,首先是cn,在上面说过是通过ComponentName类的unflattenFromString方法返回的,所有来到unflattenFromString方法
public final class ComponentName implements Parcelable, Cloneable, Comparable<ComponentName> {
private final String mPackage;
private final String mClass;public ComponentName(String pkg, String cls) {
if (pkg == null) throw new NullPointerException("package name is null");
if (cls == null) throw new NullPointerException("class name is null");
mPackage = pkg;
mClass = cls;
}public static ComponentName unflattenFromString(String str) {
int sep = str.indexOf('/');
if (sep < 0 || (sep+1) >= str.length()) {
return null;
}
String pkg = str.substring(0, sep);
String cls = str.substring(sep+1);
if (cls.length() > 0 && cls.charAt(0) == '.') {
cls = pkg + cls;
}
return new ComponentName(pkg, cls);
}}
先通过indexOf得到入参字符串中反斜线/的下标位置,然后通过substring分别得到反斜线/前面与后面的值。也就是pkg=io.appium.uiautomator2.server.test,cls=androidx.test.runner.AndroidJUnitRunner。然后再实例化ComponentName对象返回,这里把两个值都给了ComponentName对象的成员变量mPackage、mClass。
6.再回到startInstrumentation的入参第二个参数profileFile,命令行没有-p,所以profileFile为null;第三个参数是0,第四个参数是Bundle对象,第五个参数InstrumentationWatcher对象,第六个参数UiAutomationConnection对象,第七个参数调用UserHandle.USER_CURRENT得到的值是-2,第八个参数null
7.知道这些入参值后,来到ActivityManagerProxy的startInstrumentation方法
public boolean startInstrumentation(ComponentName className, String profileFile,
int flags, Bundle arguments, IInstrumentationWatcher watcher,
IUiAutomationConnection connection, int userId, String instructionSet)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
ComponentName.writeToParcel(className, data);
data.writeString(profileFile);
data.writeInt(flags);
data.writeBundle(arguments);
data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
data.writeStrongBinder(connection != null ? connection.asBinder() : null);
data.writeInt(userId);
data.writeString(instructionSet);
mRemote.transact(START_INSTRUMENTATION_TRANSACTION, data, reply, 0);
reply.readException();
boolean res = reply.readInt() != 0;
reply.recycle();
data.recycle();
return res;
}
通过Parcel对象写入一些数据,然后主要看mRemote.transact(START_INSTRUMENTATION_TRANSACTION, data, reply, 0)这行代码,mRemote是执行ActivityManagerNative.getDefault()的时候通过asInterface方法实例化ActivityManagerProxy对象时入参的ActivityManagerService引用;所以这里是调用了ActivityManagerService的transact方法,在ActivityManagerService类中没有transact方法,来到父类ActivityManagerNative中找,同样没有transact方法;再到Binder类中找到,然后根据代码调用关系最后是到了ActivityManagerService类调用了startInstrumentation方法。
8.来到ActivityManagerService类调用了startInstrumentation方法
public boolean startInstrumentation(ComponentName className,
String profileFile, int flags, Bundle arguments,
IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection,
int userId, String abiOverride) {
......
ProcessRecord app = addAppLocked(ai, false, abiOverride);
app.instrumentationClass = className;
app.instrumentationInfo = ai;
app.instrumentationProfileFile = profileFile;
app.instrumentationArguments = arguments;
app.instrumentationWatcher = watcher;
app.instrumentationUiAutomationConnection = uiAutomationConnection;
app.instrumentationResultClass = className;
Binder.restoreCallingIdentity(origId);
}
}
终于是在这里找到了ProcessRecord对象,而instrumentationClass的值也是在这里赋值了;一切悬案好像都要揭开的样子了哦。调用了addAppLocked方法返回的ProcessRecord对象,所以往下看。
9.来到ActivityManagerService的addAppLocked方法
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
String abiOverride) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(info.processName, info.uid, true);
} else {
app = null;
}if (app == null) {
app = newProcessRecordLocked(info, null, isolated, 0);
mProcessNames.put(info.processName, app.uid, app);
if (isolated) {
mIsolatedProcesses.put(app.uid, app);
}
updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}......
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
startProcessLocked(app, "added application", app.processName, abiOverride,
null /* entryPoint */, null /* entryPointArgs */);
}return app;
}
通过一系列方法及判断得到ProcessRecord(这里顺便提提ProcessRecord这个类,整个进程中只有一个ProcessRecord对象,它会记录一系列的进程数据可以贯穿整个生命周期);然后看看startProcessLocked方法启动进程
ProcessRecord类讲解:https://blog.csdn.net/tonyandroid1984/article/details/70224827
10.来到ActivityManagerService的startProcessLocked方法
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
synchronized (mPidsSelfLocked) {
this.mPidsSelfLocked.put(startResult.pid, app);
if (isActivityProcess) {
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
}
}
核心代码是执行Process.start是socket通信告知Zygote创建fork子进程,在子进程中会接着关闭socket,调用ZygoteInit.invokeStaticMain(cloader, className, mainArgs),即调用ActivityThread.main(), 新的应用进程会从ActivityThread 的 main()函数处开始执行;具体实现比较复杂就不多说了,可以参考【android进程创建分析】;往下看可以看到mPidsSelfLocked这个集合put的所在之处了,入参pid、ProcessRecord加入集合中。
11.然后回到ActivityManagerService类调用了startInstrumentation方法
public boolean startInstrumentation(ComponentName className,
String profileFile, int flags, Bundle arguments,
IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection,
int userId, String abiOverride) {
......
ProcessRecord app = addAppLocked(ai, false, abiOverride);
app.instrumentationClass = className;
app.instrumentationInfo = ai;
app.instrumentationProfileFile = profileFile;
app.instrumentationArguments = arguments;
app.instrumentationWatcher = watcher;
app.instrumentationUiAutomationConnection = uiAutomationConnection;
app.instrumentationResultClass = className;
Binder.restoreCallingIdentity(origId);
}
}
返回的ProcessRecord给成员变量赋值,app.instrumentationClass复制的className是Am的runInstrument方法初始化ComponentName得到的。然后进程再开始从ActivityThread 的 main()函数处开始执行,这样就正式回到上面的第一大点InStrumentation的OnCreate过程。
三、KO:
回到上面第一大点,代码太混乱,画个图总结一下
1.InStrumentation的OnCreate过程图
2.通过adb shell am instrument命令行运行源码分析图
从命令行这边运行最后还是会调用ActivityThread的main函数,所以又回到了上面的流程:
(1)在之前留下的问题中ProcessRecord 对象通过mPidsSelfLocked这个集合get得到的,而来到ActivityThread的handleBindApplication的方法中,从入参分析data.instrumentationName的值其实就是app.instrumentationClass;
(2)而app.instrumentationClass是一个ComponentName对象,这个ComponentName对象在adb shell am instrment命令行执行源码分析流程中可以看到,在实例化ComponentName对象这里把两个值pkg=io.appium.uiautomator2.server.test,cls=androidx.test.runner.AndroidJUnitRunner都给了ComponentName对象的成员变量mPackage、mClass。
(3)到ActivityThread的成员变量mInstrumentation实例的初始化,判断data.instrumentationName不为空,则执行代码
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
首先data.instrumentationName是指ComponentName对象,然后调用getClassName方法,这个方法得到就是mClass的值,然后反射实例化最终得到的是AndroidJUnitRunner的实例,AndroidJUnitRunner是继承Instrumentation的。
最终结论:用adb shell am instrument命令执行测试,mInstrumentation这个实例指向的并不是默认的Instrumentation而是命令中指定的AndroidJUnitRunner,所以后面调用的是AndroidJUnitRunner的onCreate方法开始执行测试。