Android中Application的创建流程

一、前言

System进程和App进程都运行着一个或多个App,每个App都会有一个对应的Application对象(该对象跟LoadedApk一一对应)。下面分别解析以下两种进程创建Application的过程:

  • System Server进程
  • App进程

二、System Server进程

Android系统启动流程一文中,讲到过Zygote通过回调函数进入到System Server阶段,也就是调用了System Server的main()方法中,该方法中会调用run()方法,具体代码如下:

1
2
3
4
//路径:/frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
new SystemServer().run();//见2.1
}

2.1 SystemServer.run()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//路径:/frameworks/base/services/java/com/android/server/SystemServer.java  
private void run() {
try {
......
//创建消息Looper
Looper.prepareMainLooper();
//加载动态库libandroid_servers.so
System.loadLibrary("android_servers");
performPendingShutdown();
//创建系统的Context
createSystemContext();//见2.2
//创建SystemServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
}
...
try {
traceBeginAndSlog("StartServices");
//启动引导服务
startBootstrapServices();
//启动核心服务
startCoreServices();
//启动其他服务
startOtherServices();
SystemServerInitThreadPool.shutdown();
}
......
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}

在System Server的run()方法中,会调用createSystemContext()来创建系统的上下文。

2.2 createSystemContext()

1
2
3
4
5
6
7
8
9
//路径:/frameworks/base/services/java/com/android/server/SystemServer.java
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();//见[2.3]
mSystemContext = activityThread.getSystemContext();//获取系统上下文
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

final Context systemUiContext = activityThread.getSystemUiContext();//获取系统UI上下文
systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}

调用了ActivityThread.systemMain()方法,以及getSystemContext()获取系统上下文、getSystemUiContext()获取系统UI上下文。

2.3 ActivityThread.systemMain()

1
2
3
4
5
6
7
8
9
10
11
12
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
public static ActivityThread systemMain() {
// 高内存设备进行硬件加速绘图
if (!ActivityManager.isHighEndGfx()) {
ThreadedRenderer.disable(true);
} else {
ThreadedRenderer.enableForegroundTrimming();
}
ActivityThread thread = new ActivityThread();//见2.4
thread.attach(true);//见2.5
return thread;
}

2.4 ActivityThread初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread {
private ContextImpl mSystemContext;//记录system进程的ContextImpl对象
private ContextImpl mSystemUiContext;//系统 UI 的上下文对象
final ApplicationThread mAppThread = new ApplicationThread();//创建ApplicationThread对象
AppBindData mBoundApplication;//用于绑定应用程序的相关信息
Application mInitialApplication;//当前进程中首次初始化的app对象
private static volatile ActivityThread sCurrentActivityThread;//记录当前ActivityThread
Instrumentation mInstrumentation;//用于监控和管理应用程序的执行环境。它提供了一种机制,可以向应用程序注入代码,监视和控制应用程序的行为
boolean mSystemThread = false;//标记当前进程是否为system进程
static volatile Handler sMainThreadHandler;//处理主线程消息的句柄
...
ActivityThread() {
mResourcesManager = ResourcesManager.getInstance();//获取资源管理实例
}
...
}

创建ActivityThread实例时,会初始化很多变量,其中有一个Application类的mInitialApplication对象,它的初始化分为两种情况:

  1. System Server进程则是由ActivityThread.attach()过程赋值。
  2. 普通App进程则是由ActivityThread.handleBindApplication()过程赋值。

2.5 ActivityThread.attach()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;//传入的参数为true,即设置mSystemThread为true,这意味着当前进程是系统进程
if (!system) {//非系统进程执行该分支
...
} else {//系统进程执行该分支
...
try {
mInstrumentation = new Instrumentation();//创建Instrumentation对像
//getSystemContext见[2.6]
//createAppContext见[2.7]
ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
//makeApplication见[2.8]
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();//创建Application对象
}
...
}
...
}

传入的system参数为true,这意味着当前进程是系统进程,对应进入else分支,会实例化mInstrumentation和mInitialApplication对象。

2.6 getSystemContext()

1
2
3
4
5
6
7
8
9
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
public ContextImpl getSystemContext() {
synchronized (this) {
if (mSystemContext == null) {
mSystemContext = ContextImpl.createSystemContext(this);
}
return mSystemContext;
}
}

调用createSystemContext()创建系统上下文。

2.6.1 createSystemContext()

1
2
3
4
5
6
7
8
9
10
11
12
//路径:/frameworks/base/core/java/android/app/ContextImpl.java
static ContextImpl createSystemContext(ActivityThread mainThread) {
//创建LoadedApk对象,见[2.6.1.1]
LoadedApk packageInfo = new LoadedApk(mainThread);
//创建ContextImpl对象,见[2.6.1.2]
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0, null);
//设置资源并更新资源配置
context.setResources(packageInfo.getResources());
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetrics());
return context;
}

创建LoadedApk对象和ContextImpl对象,并设置资源、更新资源配置。

2.6.1.1 LoadedApk初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//路径:/frameworks/base/core/java/android/app/LoadedApk.java
public final class LoadedApk {
private final ActivityThread mActivityThread;
final String mPackageName;
private ApplicationInfo mApplicationInfo;
private String mAppDir;
private String mResDir;
private String[] mOverlayDirs;
private String[] mSharedLibraries;
private String mDataDir;
private String mLibDir;
private File mDataDirFile;
private File mDeviceProtectedDataDirFile;
private File mCredentialProtectedDataDirFile;
private final ClassLoader mBaseClassLoader;
...
Resources mResources;
private ClassLoader mClassLoader;
private Application mApplication;
...
// Create information about a new .apk
public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
CompatibilityInfo compatInfo, ClassLoader baseLoader,
boolean securityViolation, boolean includeCode, boolean registerPackage) {
mActivityThread = activityThread;
setApplicationInfo(aInfo);
mPackageName = aInfo.packageName;
mBaseClassLoader = baseLoader;
mSecurityViolation = securityViolation;
mIncludeCode = includeCode;
mRegisterPackage = registerPackage;
mDisplayAdjustments.setCompatibilityInfo(compatInfo);
}

LoadedApk(ActivityThread activityThread) {
mActivityThread = activityThread;//对应ActivityThread实例
mApplicationInfo = new ApplicationInfo();//创建ApplicationInfo对象,里面啥也没干
mApplicationInfo.packageName = "android";//默认包名为"android"
mPackageName = "android";
...
mClassLoader = ClassLoader.getSystemClassLoader();//见https://gal2xy.github.io/2023/11/25/Android中的ClassLoader/
mResources = Resources.getSystem();
}
...
}

LoadedApk主要是用来创建apk的相关信息,并集合成一个LoadedApk对象,其中相关信息包括:活动线程、包名、资源目录、共享库目录、类加载器等等。System Server进程走的是带一个参数的LoadedApk构造函数,其中比较重要的是将之前创建的ActivityThread实例赋值mActivityThread字段、创建ApplicationInfo对象、获取类加载器。

2.6.1.2 ContextImpl初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//路径:/frameworks/base/core/java/android/app/ContextImpl.java
private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
@NonNull LoadedApk packageInfo, @Nullable String splitName,
@Nullable IBinder activityToken, @Nullable UserHandle user, int flags,
@Nullable ClassLoader classLoader) {
mOuterContext = this;
if ((flags & (Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE
| Context.CONTEXT_DEVICE_PROTECTED_STORAGE)) == 0) {
final File dataDir = packageInfo.getDataDirFile();
if (Objects.equals(dataDir, packageInfo.getCredentialProtectedDataDirFile())) {
flags |= Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
} else if (Objects.equals(dataDir, packageInfo.getDeviceProtectedDataDirFile())) {
flags |= Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
}
}
mMainThread = mainThread;
mActivityToken = activityToken;
mFlags = flags;
//设置当前进程的用户
if (user == null) {
user = Process.myUserHandle();
}
mUser = user;
//将刚刚创建的LoadedApk实例赋给mPackageInfo
mPackageInfo = packageInfo;
mSplitName = splitName;
mClassLoader = classLoader;
mResourcesManager = ResourcesManager.getInstance();
//根据传入的上下文对象container是否为空来进行不同操作
if (container != null) {
mBasePackageName = container.mBasePackageName;
mOpPackageName = container.mOpPackageName;
setResources(container.mResources);
mDisplay = container.mDisplay;
} else {//将刚刚创建的LoadedApk实例的信息赋值某些字段
mBasePackageName = packageInfo.mPackageName;
ApplicationInfo ainfo = packageInfo.getApplicationInfo();//实际上是空的对象
if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) {
mOpPackageName = ActivityThread.currentPackageName();
} else {
mOpPackageName = mBasePackageName;
}
}
mContentResolver = new ApplicationContentResolver(this, mainThread, user);
}

传入的参数mainThread为之前创建的ActivityThread实例、参数packageInfo为刚刚创建的LoadedApk实例。

整个代码实际上是利用刚刚创建的LoadedApk实例来创建ContextImpl实例。

2.7 ContextImpl.createAppContext()

1
2
3
4
5
6
7
8
//路径:/frameworks/base/core/java/android/app/ContextImpl.java
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
//见[2.6.1.2]
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0, null);
context.setResources(packageInfo.getResources());//设置app资源
return context;
}

需要注意,传入的参数mainThread为之前创建的ActivityThread实例,参数packageInfo是ContextImpl实例(在2.6.1.2中创建的)中的mpackageInfo(在2.6.1.1中创建的)。

调用ContextImpl的构造函数再创建一次ContextImpl实例!?是因为一个是SystemContext一个是AppContext的缘故?

2.8 makeApplication()

在2.5中通过context.mPackageInfo.makeApplication(true, null)调用该方法,context.mPackageInfo是刚刚创建的LoadedApk实例(在2.6.1.1中创建的)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//路径:/frameworks/base/core/java/android/app/LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
//保证一个LoadedApk对象只创建一个对应的Application对象
if (mApplication != null) {
return mApplication;
}
...
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {//传入的参数为true,进入该分支
appClass = "android.app.Application";//system_server进程进入该分支
}
try {
//获取类加载器,见[2.9]
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {//在之前流程可知默认android,显然不进入此分支
initializeJavaContextClassLoader();
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
//创建Application对象,见[2.10]
app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
appContext.setOuterContext(app);
}
...
mActivityThread.mAllApplications.add(app);//加入到Application列表中,之前说个一个进程可以有多个app
mApplication = app;//将刚刚创建的Application对象app赋值给mApplication
if (instrumentation != null) {//传入的instrumentation为null,不进入此分支
try {
instrumentation.callApplicationOnCreate(app);
}
...
}
...
return app;
}

主要是获取appClass、创建类加载器和appContext,利用这些来创建Application对象。

2.9 getClassLoader()

1
2
3
4
5
6
7
8
9
//路径:/frameworks/base/core/java/android/app/LoadedApk.java
public ClassLoader getClassLoader() {
synchronized (this) {
if (mClassLoader == null) {
createOrUpdateClassLoaderLocked(null /*addedPaths*/);
}
return mClassLoader;
}
}

如果类加载器不为空则调用createOrUpdateClassLoaderLocked()方法。

2.9.1 createOrUpdateClassLoaderLocked()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//路径:/frameworks/base/core/java/android/app/LoadedApk.java
private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
if (mPackageName.equals("android")) {//System Server进程进入该分支
if (mClassLoader != null) {
return;
}
if (mBaseClassLoader != null) {
mClassLoader = mBaseClassLoader;
} else {
mClassLoader = ClassLoader.getSystemClassLoader();//如果是System Server进程则到这
}
return;
}
//mPackageName不为"android"
...
if (mRegisterPackage) {
...
//添加包依赖,见[2.9.2]
ActivityManager.getService().addPackageDependency(mPackageName);
...
}
// Lists for the elements of zip/code and native libraries.
final List<String> zipPaths = new ArrayList<>(10);
final List<String> libPaths = new ArrayList<>(10);
final boolean isBundledApp = mApplicationInfo.isSystemApp() && !mApplicationInfo.isUpdatedSystemApp();
//构建路径,见[2.9.3]
makePaths(mActivityThread, isBundledApp, mApplicationInfo, zipPaths, libPaths);
String libraryPermittedPath = mDataDir;
if (isBundledApp) {
libraryPermittedPath += File.pathSeparator + System.getProperty("java.library.path");
}
final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
if (!mIncludeCode) {//构造函数中mIncludeCode为true
...
}
final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) : TextUtils.join(File.pathSeparator, zipPaths);
...
boolean needToSetupJitProfiles = false;
if (mClassLoader == null) {
...
////见[2.9.4]
mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
libraryPermittedPath, mBaseClassLoader);
...
}
...
// Setup jit profile support.
...
}

2.9.2 ActivityManagerService.addPackageDependency()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//路径:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void addPackageDependency(String packageName) {
synchronized (this) {
//获取调用该方法的进程id
int callingPid = Binder.getCallingPid();
//调用该方法的进程的 PID 和当前进程的 PID 相同,说明是在当前进程内部调用该方法,直接返回
if (callingPid == myPid()) {
return;
}
ProcessRecord proc;
synchronized (mPidsSelfLocked) {
//根据调用该方法的进程id获取对应进程记录
proc = mPidsSelfLocked.get(Binder.getCallingPid());
}
if (proc != null) {//成功获取到该进程的记录
if (proc.pkgDeps == null) {//该进程的包名依赖为空
proc.pkgDeps = new ArraySet<String>(1);
}
proc.pkgDeps.add(packageName);//添加包名依赖
}
}
}

2.9.3 makePaths()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//路径:/frameworks/base/core/java/android/app/LoadedApk.java
public static void makePaths(ActivityThread activityThread,
boolean isBundledApp,
ApplicationInfo aInfo,
List<String> outZipPaths,
List<String> outLibPaths) {
final String appDir = aInfo.sourceDir;
final String libDir = aInfo.nativeLibraryDir;
final String[] sharedLibraries = aInfo.sharedLibraryFiles;

outZipPaths.clear();
outZipPaths.add(appDir);

// Do not load all available splits if the app requested isolated split loading.
if (aInfo.splitSourceDirs != null && !aInfo.requestsIsolatedSplitLoading()) {
Collections.addAll(outZipPaths, aInfo.splitSourceDirs);
}
if (outLibPaths != null) {
outLibPaths.clear();
}

String[] instrumentationLibs = null;
// activityThread will be null when called from the WebView zygote; just assume
// no instrumentation applies in this case.
if (activityThread != null) {
String instrumentationPackageName = activityThread.mInstrumentationPackageName;
String instrumentationAppDir = activityThread.mInstrumentationAppDir;
String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
String instrumentationLibDir = activityThread.mInstrumentationLibDir;

String instrumentedAppDir = activityThread.mInstrumentedAppDir;
String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
String instrumentedLibDir = activityThread.mInstrumentedLibDir;

if (appDir.equals(instrumentationAppDir)
|| appDir.equals(instrumentedAppDir)) {
outZipPaths.clear();
outZipPaths.add(instrumentationAppDir);

// Only add splits if the app did not request isolated split loading.
if (!aInfo.requestsIsolatedSplitLoading()) {
if (instrumentationSplitAppDirs != null) {
Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
}

if (!instrumentationAppDir.equals(instrumentedAppDir)) {
outZipPaths.add(instrumentedAppDir);
if (instrumentedSplitAppDirs != null) {
Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
}
}
}

if (outLibPaths != null) {
outLibPaths.add(instrumentationLibDir);
if (!instrumentationLibDir.equals(instrumentedLibDir)) {
outLibPaths.add(instrumentedLibDir);
}
}

if (!instrumentedAppDir.equals(instrumentationAppDir)) {
instrumentationLibs = getLibrariesFor(instrumentationPackageName);
}
}
}

if (outLibPaths != null) {
if (outLibPaths.isEmpty()) {
outLibPaths.add(libDir);
}
if (aInfo.primaryCpuAbi != null) {
//目标sdk版本 < Android 7的sdk版本
if (aInfo.targetSdkVersion < Build.VERSION_CODES.N) {
outLibPaths.add("/system/fake-libs" + (VMRuntime.is64BitAbi(aInfo.primaryCpuAbi) ? "64" : ""));
}
for (String apk : outZipPaths) {
outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
}
}

if (isBundledApp) {
outLibPaths.add(System.getProperty("java.library.path"));
}
}
//遍历sharedLibraries的Lib库,未包含在其中的则添加到outZipPaths中,如果需要还可以添加到outLibPaths
if (sharedLibraries != null) {
for (String lib : sharedLibraries) {
if (!outZipPaths.contains(lib)) {
outZipPaths.add(0, lib);
appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
}
}
}
//遍历instrumentation的Lib库,未包含在其中的则添加到outZipPaths中,如果需要还可以添加到outLibPaths
...逻辑同上
}

2.9.4 ApplicationLoader.getClassLoader()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//路径:/frameworks/base/core/java/android/app/ApplicationLoaders.java
ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled, String librarySearchPath, String libraryPermittedPath, ClassLoader parent) {
return getClassLoader(zip, targetSdkVersion, isBundled, librarySearchPath, libraryPermittedPath, parent, zip);
}

private ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
String librarySearchPath, String libraryPermittedPath,
ClassLoader parent, String cacheKey) {
//获取父加载器
ClassLoader baseParent = ClassLoader.getSystemClassLoader().getParent();

synchronized (mLoaders) {
if (parent == null) {//走这
parent = baseParent;
}
if (parent == baseParent) {//进而走这
ClassLoader loader = mLoaders.get(cacheKey);
if (loader != null) {
return loader;
}
//创建pathClassloader对象
PathClassLoader pathClassloader = PathClassLoaderFactory.createClassLoader(
zip,
librarySearchPath,
libraryPermittedPath,
parent,
targetSdkVersion,
isBundled);
//native方法
setupVulkanLayerPath(pathClassloader, librarySearchPath);
mLoaders.put(cacheKey, pathClassloader);
return pathClassloader;
}
PathClassLoader pathClassloader = new PathClassLoader(zip, parent);
return pathClassloader;
}
}

传入的参数parent(ClassLoader对象)为mBaseClassLoader,在SystemServer进程中LoadedApk初始化时是为null的,所以走if (parent == null) 分支,进而走if (parent == baseParent) 分支。

2.10 newApplication()

1
2
3
4
5
6
7
8
9
10
//路径:/frameworks/base/core/java/android/app/Instrumentation.java
public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
}

static public Application newApplication(Class<?> clazz, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}

传入的参数cl是在 2.9 处获得的PathClassLoader对象,参数className对应要加载的Application类(”android.app.Application”),最后通过反射获取到该类,然后调用newInstance()方法实例化Application。

2.10.1 Application.attach()

1
2
3
4
5
6
7
8
9
10
11
12
13
//路径:/frameworks/base/core/java/android/app/Application.java
final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

//路径:/frameworks/base/core/java/android/content/ContextWrapper.java
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}

该方法主要功能:

  1. 将新创建的ContextImpl对象(2.8中创建的appContext)保存到Application的父类成员变量mBase;
  2. 将新创建的LoadedApk对象(2.8中创建的appContext中的mPackageInfo对象)保存到Application的父员变量mLoadedApk;

三、App进程

Android应用程序启动流程(一)一文中,应用程序同样也通过回调函数Zygote.MethodAndArgsCaller()进入到App运行阶段,即回调ActivityThread.main()方法。

3.1 ActivityThread.main()

1
2
3
4
5
6
7
8
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
...
//创建线程并将当前线程附加到ActivityThread,参数false表示不使用新线程
ActivityThread thread = new ActivityThread();
thread.attach(false);
...
}

在该方法中调用了thread.attach()方法。

3.2 ActivityThread.attach()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {//非系统进程进入此分支
//初始化RuntimeInit.mApplicationObject值
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManager.getService();
try {
//见[3.3]
mgr.attachApplication(mAppThread);
}
...
} else {//系统进程进入此分支
...
}
...
}

重点是mgr.attachApplication(mAppThread)

3.3 ActivityManagerService.attachApplication()

1
2
3
4
5
6
7
8
9
10
11
12
13
//路径:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
//获取调用该方法的进程的pid
int callingPid = Binder.getCallingPid();
//临时清除调用者的身份信息,返回唯一标识符以便后续恢复调用者身份
final long origId = Binder.clearCallingIdentity();
//给进程附加Application,见[3.4]
attachApplicationLocked(thread, callingPid);
//恢复之前清除的调用者身份
Binder.restoreCallingIdentity(origId);
}
}

接着调用attachApplicationLocked()方法给进程附加Application。

3.4 attachApplicationLocked()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//路径:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);//根据pid获取application record
}
}
...
try {
...
ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info;
...
if (app.instr != null) {
//见[3.5]
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(),只不过参数不同
...
}

...
}
...
}

代码很长,这里只关注thread.bindApplication()方法。

3.5 ActivityThread.bindApplication()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
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) {

//给AppBindData实例(data)进行一系列赋值
...

sendMessage(H.BIND_APPLICATION, data);
}

对data对象进行了一系列的赋值,最终调用sendMessage()方法将BIND_APPLICATION消息添加到消息队列中,接着我们就需要看ActivityThread的handleMessage()方法了。

1
2
3
4
5
6
7
8
9
10
11
12
13
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
public void handleMessage(Message msg) {
switch (msg.what) {
...
case BIND_APPLICATION:
AppBindData data = (AppBindData)msg.obj;
//见[3.6]
handleBindApplication(data);
break;
...
}
...
}

主线程接收到BIND_APPLICATION消息,执行handleBindApplication()方法。

3.6 handleBindApplication()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
private void handleBindApplication(AppBindData data) {
...
mBoundApplication = data;
...
//获取LoadedApk对象,见[3.7]
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
...
//创建appContext,见[2.7]
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
...
try {
//此处data.info指LoadedApk, 通过反射创建目标应用Application对象,见[2.8]
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
...
try {
//调用的是空方法,啥也没干,见[3.6.1]
mInstrumentation.onCreate(data.instrumentationArgs);
}
...
try {
//见[3.6.1]
mInstrumentation.callApplicationOnCreate(app);
}
...
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
// Preload fonts resources
...
}

主要是获取LoadedApk对象,借此创建ContextImpl对象(appContext)以及Application对象(app),并将创建好的app赋值给ActivityThread的mInitialApplication字段。

3.6.1 callApplicationOnCreate()

1
2
3
4
5
6
7
/frameworks/base/core/java/android/app/Instrumentation.java
public void callApplicationOnCreate(Application app) {
app.onCreate();
}

public void onCreate(Bundle arguments) {
}

3.7 getPackageInfoNoCheck()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai, CompatibilityInfo compatInfo) {
return getPackageInfo(ai, compatInfo, null, false, true, false);
}

private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
boolean registerPackage) {
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
// 根据不同的情况获取缓存的LoadedApk对象
if (differentUser) {
// Caching not supported across users
ref = null;
} else if (includeCode) {
ref = mPackages.get(aInfo.packageName);
} else {
ref = mResourcePackages.get(aInfo.packageName);
}

LoadedApk packageInfo = ref != null ? ref.get() : null;
if (packageInfo == null || (packageInfo.mResources != null
&& !packageInfo.mResources.getAssets().isUpToDate())) {
...
//创建LoadedApk对象
packageInfo = new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);

if (mSystemThread && "android".equals(aInfo.packageName)) {
//见[3.7.1]
packageInfo.installSystemApplicationInfo(aInfo,
getSystemContext().mPackageInfo.getClassLoader());
}

if (differentUser) {
// Caching not supported across users
} else if (includeCode) {
//更新mPackages,即将刚创建的packageInfo加入
mPackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
} else {
mResourcePackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
}
}
return packageInfo;
}
}

创建LoadedApk对象,并将将新创建的LoadedApk加入到mPackages。也就是说每个app都会创建唯一的LoadedApk对象。此处aInfo来源于ProcessRecord.info变量,也就是进程中的第一个app。

3.7.1 installSystemApplicationInfo()

1
2
3
4
5
6
//路径:/frameworks/base/core/java/android/app/LoadedApk.java
void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
assert info.packageName.equals("android");
mApplicationInfo = info;
mClassLoader = classLoader;
}

第二个参数通过getSystemContext().mPackageInfo.getClassLoader()获取的,对应LoadedApk对象中的ClassLoader。代码中很明显的一个特征就是比对packageName是否为”android”,而在System Server进程中创建的LoadedApk对象默认packageName为”android”。

四、总结

LoadedApk与Application一一对应,Application借助LoadedApk创建的,并存放在LoadedApk的mApplication字段,而在创建Application的过程中,也将LoadedApk存放在Application的mLoadedApk字段(互相包含!?)。最后返回Application的时候,也将Application存放在ActivityThread中的mInitialApplication字段。

接下来借用gityuan的两种流程图:

  • System Server进程创建Application

  • App进程创建Application


参考:

http://androidxref.com/8.0.0_r4/xref/

https://gityuan.com/2017/04/02/android-application/

https://phantomvk.github.io/2019/07/23/Android_Application_class/

https://ljd1996.github.io/2019/12/16/Android-Application/


Android中Application的创建流程
http://example.com/2023/11/27/Android安全/Android中Application的创建流程/
作者
gla2xy
发布于
2023年11月27日
许可协议