Application的创建
一个 app 启动时候创建一个 Application
对象。这个对象的创建时间在 frameworks 中调用创建的,创建流程可见下图,涉及的几个主要的类调用。
一、主线程运行入口
APP进程起来后,主线程运行入库 ActivityThread.main()
方法。
```java
// ActivityThread.java
@UnsupportedAppUsage
final ApplicationThread mAppThread = new ApplicationThread();
public static void main(String[] args) {
// ...
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
// ...
}
@UnsupportedAppUsage
private void attach(boolean system, long startSeq) {
// ...
if (!system) {
// ...
final IActivityManager mgr = ActivityManager.getService(); //获取 IActivityManager 对象。
try {
mgr.attachApplication(mAppThread, startSeq); // Binder 调用 AMS 的 attachApplicaion() 方法。
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
// ...
}
// ...
}
```
运行启动是一般的app,并非 system app,因此进入到 if
分支。
二、ActivityManagerService
方法执行
从app主线程执行,进而跨进程调用到 ActivityManagerService
的 attachApplication(IApplicationThread thread, long startSeq)
方法。
// ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
@GuardedBy("this")
private void attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// ...... 这里的一个比较重要的数据是 appInfo:ApplicationInfo
// if 分支内,表明运行的时候隔离状态的app,这样的app不能访问系统资源,服务及其他app进程。
if (app.getIsolatedEntryPoint() != null) {
// This is an isolated process which should just call an entry point instead of
// being bound to an application.
thread.runIsolatedEntryPoint(
app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());
} else if (instr2 != null) {
thread.bindApplication(processName, appInfo,
app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
providerList,
instr2.mClass,
profilerInfo, instr2.mArguments,
instr2.mWatcher,
instr2.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.getCompat(), getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.getDisabledCompatChanges(), serializedSystemFontMap,
app.getStartElapsedTime(), app.getStartUptime());
} else {
thread.bindApplication(processName, appInfo,
app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
providerList, null, profilerInfo, null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.getCompat(), getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.getDisabledCompatChanges(), serializedSystemFontMap,
app.getStartElapsedTime(), app.getStartUptime());
}
// ......
}
在内部调用到 attachApplicationLocked()
方法,在方法内部,会执行到 bindApplication()
方法,除非运行的app是一个独立APP,即不访问系统任何资源。这个方法里还有一个重要的数据变量是 appInfo
表示了应用的信息,会在调用 bindApplication()
方法时传递给 ApplicationThread
对象方法。
三、ApplicationThread.bindApplication()
// ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
@Override
public final void bindApplication(String processName, ApplicationInfo appInfo,
String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage,
ProviderInfoList providerList, 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, AutofillOptions autofillOptions,
ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges,
SharedMemory serializedSystemFontMap,
long startRequestedElapsedTime, long startRequestedUptime) {
// ......
AppBindData data = new AppBindData();
// 构建 AppBindData 数据结构。
updateCompatOverrideScale(compatInfo);
CompatibilityInfo.applyOverrideScaleIfNeeded(config);
sendMessage(H.BIND_APPLICATION, data); // 发送消息。
}
}
在 ActivityManagerService
中进行执行后,获取必要的信息,然后执行回到 ApplicationThread
的 app 进程 bindApplication()
方法中,并构建 AppBindData
数据对象,最终发送消息 H.BIND_APPLICATION
进入消息队列等待执行。
四、handleBindApplication(AppBindData data)
通过消息机制执行到 handleMessage(Message msg)
,依据消息 what
值 BIND_APPLICATION
执行方法 handleBindApplication(AppBindData data)
。
// ActivityThread.java
@UnsupportedAppUsage
private void handleBindApplication(AppBindData data) {
// ...
// 获取 LoadedApk 类型对象
data.info = getPackageInfo(data.appInfo, mCompatibilityInfo, null /* baseLoader */,
false /* securityViolation */, true /* includeCode */,
false /* registerPackage */, isSdkSandbox);
// ...
// 获取 ActivityManagerService 的 Binder 句柄
final IActivityManager mgr = ActivityManager.getService();
// 创建 Context 上下文对象
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
// ...
Application app;
// ...
try {
// 通过 LoadedApk 对象创建 Application 对象,内部具体实现细节,并且调用到了 Application.attach(Coext)。
// 在 attach(Context) 方法内调用从 ContextWrapper 继承而来的 attachBaseContext(Context),设置 mBaseContext 的实例变量。
app = data.info.makeApplicationInner(data.restrictedBackupMode, null);
// ...
} finally {
// ...
}
// ...
try {
mgr.finishAttachApplication(mStartSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
执行 handleBindApplication()
方法传入参数 AppBindData
,在最终创建 Application
前,data.info
被赋值 。接着调用到 LoadedApk.makeApplicationInner(boolean forceDefaultAppClass, Instrumentation instrumentation)
。
// LoadedApk.java
public Application makeApplicationInner(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
return makeApplicationInner(forceDefaultAppClass, instrumentation,
/* allowDuplicateInstances= */ false);
}
private Application makeApplicationInner(boolean forceDefaultAppClass,
Instrumentation instrumentation, boolean allowDuplicateInstances) {
if (mApplication != null) {
return mApplication;
}
// ...
Application app = null;
final String myProcessName = Process.myProcessName();
String appClass = mApplicationInfo.getCustomApplicationClassNameForProcess(
myProcessName);
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
final java.lang.ClassLoader cl = getClassLoader();
// ...
// 创建方式与 ActivityThread 中 handleBindApplication 创建方式一致。
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
// ...
// 创建 Application
app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
// ...
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
// ...
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app); // 调用了 Application 的声明周期方法 onCreate
} catch (Exception e) {
// ...
}
}
return app;
}
最终调用的 Application
对象是在 Instrumentation
中创建。