ActivityThread.main的循环过程

在应用启动流程的结尾,我们知道一个应用的启动,最终会调用到ActivityThread.main()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) {
......

Looper.prepareMainLooper();
//创建ActivityThread对象
ActivityThread thread = new ActivityThread();
//建立Binder通道
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
Looper.loop(); //消息循环运行
throw new RuntimeException("Main thread loop unexpectedly exited");
}

thread.attach

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
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
......

RuntimeInit.setApplicationObject(mAppThread.asBinder());
//创建ActivityManagerProxy对象
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
//调用基于IActivityManager接口的Binder通道
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
}

//观察是否快接近heap的上限
BinderInternal.addGcWatcher(new Runnable() {
......
});
} else {
...
}

//添加Config回调接口
ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
......
});
}

IActivityManager 的服务端为 AMS,因此直接找AMS的 attachApplication 函数即可

AMS 的attachApplication 调用了 attachApplicationLocked

attachApplicationLocked逻辑

attachApplicationLocked 的代码也挺多,基本是干了这些事

  1. 根据pid从mPidsSelfLocked中查询到相应的ProcessRecord对象app;
  2. 当app==null,意味着本次创建的进程不存在, 则直接返回.
  3. 还刚进入attach过程,此时thread应该为null,若不为null则表示该app附到上一个进程,则调用handleAppDiedLocked清理.
  4. 绑定死亡通知,当进程pid死亡时会通过binder死亡回调,来通知system_server进程死亡的消息;
  5. 重置ProcessRecord进程信息, 此时app.thread也赋予了新值,便不再为空.
  6. app进程存在正在启动中的provider,则超时10s后发送CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息
  7. 调用thread.bindApplication绑定应用进程, 后面再进一步说明
  8. 处理Provider, Activity, Service, Broadcast相应流程

attachApplicationLocked 有个方法,是在bindApplication执行后执行的

1
2
3
4
5
6
7
8
9
10
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}

该函数会去查看在该进程中是否有等待的Activity需要去处理,在Activity的启动中会讲解

现阶段我们只需关心 thread.bindApplication

bindApplication

thread.bindApplication 它还是一个Binder操作,因此直接去找他的服务端,也就是ApplicationThread

1
2
3
4
5
6
7
public final void bindApplication(...) {
......
AppBindData data = new AppBindData();
data.processName = processName;
......
sendMessage(H.BIND_APPLICATION, data);
}

代码很简单,直接用过Handler发送消息,然后调用到方法 handleBindApplication

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
private void handleBindApplication(AppBindData data) {

mBoundApplication = data;
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);
...

//设置进程名, 也就是说进程名是在进程真正创建以后的BIND_APPLICATION过程中才取名
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId());
...

//获取LoadedApk对象
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
...

// 创建ContextImpl上下文
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
if (!Process.isIsolated()) {
final File cacheDir = appContext.getCacheDir();
if (cacheDir != null) {
System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
}
}
...
if (data.instrumentationName != null) {
...
} else {
mInstrumentation = new Instrumentation();
}

try {
// 此处data.info是指LoadedApk, 通过反射创建目标应用Application对象
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;

if (!data.restrictedBackupMode) {
List<ProviderInfo> providers = data.providers;
if (providers != null) {
installContentProviders(app, providers);
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}

mInstrumentation.onCreate(data.instrumentationArgs);
//调用Application.onCreate()回调方法.
mInstrumentation.callApplicationOnCreate(app);

} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}

该函数涉及到几个重要的方法

  1. getPackageInfoNoCheck
  2. ContextImpl.createAppContext(this, data.info)
  3. data.info.makeApplication
  4. mInstrumentation.onCreate
  5. mInstrumentation.callApplicationOnCreate(app)

getPackageInfoNoCheck

该函数的作用就是创建 LoadedApk对象

1
2
3
4
packageInfo =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);

createAppContext

该函数的作用就是创建ContextImpl对象

1
2
3
4
5
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
return new ContextImpl(null, mainThread,
packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
}

makeApplication

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
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
//可以知道,一个App只有一个Application
if (mApplication != null) {
return mApplication;
}

Application app = null;

String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}

try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
initializeJavaContextClassLoader();
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);

app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
...
}
mActivityThread.mAllApplications.add(app);
//设置mApplication对象值
mApplication = app;

if (instrumentation != null) {
try {
//调用app.onCreate()
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
...
}
}

SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
.getAssignedPackageIdentifiers();
final int N = packageIdentifiers.size();
for (int i = 0; i < N; i++) {
final int id = packageIdentifiers.keyAt(i);
if (id == 0x01 || id == 0x7f) {
continue;
}
//重写所有apk库中的R常量
rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
}
return app;
}

newApplication

1
2
3
public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
}

总结

  1. thread.attach(thread为ActivityThread)
  2. 创建 ActivityManagerProxy 对象
  3. 通过创建的Binder调用 mgr.attachApplication(mAppThread)
  4. 一系列操作回到应用程序调用 thread.bindApplication
  5. 调用应用程序的 handleBindApplication,主要有以下功能:
    - 设置进程名
    - 创建ContextImpl
    - 创建Application对象
    - 调用Application的onCreate