前言
要想启动一个应用程序,首先要保证这个应用程所需要的应用程序进程已经创建启动。AMS在启动应用程序时,会检查这个应用程序需要的应用程序进程是否存在,不存在就会请求Zygote孵化器进程来启动需要的应用程序进程。因此应用程序进程启动过程可以概括为两个部分:
- AMS发送启动应用程序进程请求
- Zygote接收请求并创建应用程序进程
关于这部分的具体流程分析可参考《Android进阶解密》第二章内容。本文重点分析Zygote创建应用程序进程走到ActivityThread的main方法后,创建Application的流程。
进入ActivityThread的main方法,需要关注的核心代码如下:
frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
// 需要关注的代码
thread.attach(false);
...
Looper.loop();
...
}
接下来进入attach方法,代码很多,但是需要重点关注的就这几行:
private void attach(boolean system) {
...
// 注释1
final IActivityManager mgr = ActivityManager.getService();
try {
// 注释2
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
}
如果对Binder机制稍有了解,你就会知道,注释1处调用ActivityManager的getService方法来获取AMS的代理对象,接着调用AMS的attachApplication方法。这里与Android8.0之前的代码逻辑有些不同,Android8.0之前是通过ActivityManagerNative的getDefault来获取AMS的代理对象的,现在这个逻辑封装到了ActivityManager中而不是ActivityManagerNative中。这里先查看ActivityManager的getService方法:
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
// 注释1
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
// 注释2
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
在注释1处获取IBinder类型的AMS引用(binder对象),接着在注释2处将它转换成IActivityManager类型的对象(也就是AMS的代理对象),这段代码采用的AIDL,IActivityManager.java文件是由AIDL工具在编译时自动生成的,IActivityManager.aidl的文件路径为frameworks/base/core/java\android/app/IActivityMananger.aidl。要实现跨进程通信,服务端也就是AMS只需要继承IActivityManager.Stub类并实现相应的方法就可以了。Android8.0之前并没有采用AIDL,用AMS的代理对象ActivityManagerProxy来与AMS进行通信,Android8.0去除了ActivityManagerNative的内部类ActivityManagerProxy,代替它的是IActivityManager,它是AMS在本地的代理。言归正传,回到attach方法,接下来进入AMS的attachApplication方法(跨进程通信,AMS在SystemServer进程)
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
// 注释1
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
接下来进入注释1处的attachApplicationLocked方法:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
// Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
// 用于描述一个应用程序进程(记录应用程序进程的相关信息)
ProcessRecord app;
...
if (app.instr != null) {
thread.bindApplication(processName, appInfo, providers,
app.instr.mClass,
profilerInfo, app.instr.mArguments,
app.instr.mWatcher,
app.instr.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);
} else {
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);
}
...
return true;
}
AMS负责四大组件的启动、切换、调度以及应用程序进程的管理,是Android中最为核心的服务,参与了应用程序的启动管理。这里省去了大量的检查和初始化的代码,保存要创建应用程序进程的相关信息等操作,也就是说通过ProcessRecord即应用程序进程信息的相关判断,thread是IApplicationThread类型的,此处代表的是IApplicationThread的代理对象,调用bindApplication方法,ApplicationThread继承IApplicationThread.Stub,此处又是Binder机制的跨进程通信,接下来进入ApplicationThread的bindApplication方法,ApplicationThread是ActivityThread的内部类,又从AMS所在的SystemServer系统服务进程回到了应用程序进程。
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
......
// 注释1
sendMessage(H.BIND_APPLICATION, data);
}
将应用程序进程的相关信息保存到AppBindData类型的data中,通过sendMessage方法发送消息,交给H类型的Handler处理
private class H extends Handler {
...
public static final int BIND_APPLICATION = 110;
...
public void handleMessage(Message msg) {
switch (msg.what) {
...
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
//调用ActivityThread的handleBindApplication()方法处理
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
}
}
进入H类的handleMessage方法,找到BIND_APPLICATION对应的case,从msg中取出之前保存的AppBindData类型的数据data,交给handleBindApplication方法
private void handleBindApplication(AppBindData data) {
// 注释1 获取LoadedApk
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
...
try {
// 注释2
// 创建一个Application对象
Application app = data.info.makeApplication(data.restrictedBackupMode,null);
mInitialApplication = app;
try {
// 注释3
// 通过mInstrumentation对象,回调Application的onCreate()方法
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
...
} finally {
...
}
...
}
先看注释1处,通过getPackageInfoNoCheck()方法对AppBindData对象的info变量赋值,info变量的类型是LoadedApk,关于LoadedApk,有一个通俗的说法,LoadedApk对象是apk文件在内存中的表示,apk文件的相关信息,比如apk文件中的资源,甚至是代码里面的Activity、Service等组件的信息都可以通过此对象获取,我们来看下getPackageInfoNoCheck()方法的源码
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {
return getPackageInfo(ai, compatInfo, null, false, true, false);
}
接着进入getPackageInfo方法:
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
boolean registerPackage) {
/*
* 下面这个地方不是很理解,看下面这一行代码的意思应该是判断是不是同一个用户
* 查了一下,differentUser的值大部分情况下应该都是false
*/
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (differentUser) {
// Caching not supported across users
ref = null;
} else if (includeCode) {
/*在getPackageInfoNoCheck()方法中调用本方法时,includeCode的值为true
*从缓存中根据应用的报名获取LoadedApk的弱引用对象
*/
ref = mPackages.get(aInfo.packageName);
} else {
ref = mResourcePackages.get(aInfo.packageName);
}
LoadedApk packageInfo = ref != null ? ref.get() : null;
/*
* 当获取的LoadedApk对象为null时,或者说是放缓存中不存在对应的LoadedApk对象时候
* 则调用LoadedApk的构造方法,创建一个LoadedApk对象
*/
if (packageInfo == null || (packageInfo.mResources != null
&& !packageInfo.mResources.getAssets().isUpToDate())) {
...
packageInfo =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
...
if (differentUser) {
// Caching not supported across users
} else if (includeCode) {
//把创建的LoadedApk对象放入缓存中
mPackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
} else {
mResourcePackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
}
}
return packageInfo;
}
}
总结一下getPackageInfo()方法的作用就是,从缓存中获取对应的LoadedApk对象,若缓存中不存在该对象,便去创建一个对象,保存在缓存里,并return LoadedApk的对象,最终把该对象赋值给handleBindApplication()中的data.info。
我们继续回到handleBindApplication()方法中的注释2处,调用data.info也就是LoadedApk对象的makeApplication()方法,创建一个Application对象,我们来看下makeApplication()方法
frameworks/base/core/java/android/app/LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
//若Application已经创建过,直接return
if (mApplication != null) {
return mApplication;
}
...
Application app = null;
...
try {
...
// 注释1
// 获取一个ContextImpl上下文对象
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
// 注释2
// 通过Instrumentation对象的newApplication()方法创建一个Application对象,
// 创建的这个Application对象也是makeApplication()方法最终return的对象
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
...
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
...
return app;
}
注释1处,内部主要还是通过new ContextImpl(xxx)的形式创建ContextImpl对象。再看注释2处,进入Instrumentation的newApplication方法,顾名思义它的作用就是创建Application
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
该反方最终通过反射的方式创建了一个Application对象,并且调用了Appliction的attach()方法,而attach方法又调用了attachBaseContext方法,现在应该明白为什么该方法在Application的onCreate之前调用了。
final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
接下来回到handleBindApplication方法的注释3处,通过mInstrumentation对象,调用callApplicationOnCreate方法,顾名思义就是去调用执行Application的onCreate()方法
public void callApplicationOnCreate(Application app) {
app.onCreate();
}
文章的后半部分主要是从handleBindApplication方法的3处重要逻辑展开的,为了看得更清晰一点,简单小结一下:
- data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); 获取保存Apk文件信息的LoadedApk对象
- Application app = data.info.makeApplication(data.restrictedBackupMode,null); 内部通过反射创建Application对象,在这个过程中会调用Application的attachBaseContext方法
- mInstrumentation.callApplicationOnCreate(app); 通过Instrumentation的callApplicationOnCreate方法执行Application的生命周期方法onCreate