目录
重拾Android-【吃透源码系列】之Android系统启动(八)ActivityThread源码分析

ActivityThread结构图

它是Android应用进程的入口类,因此从main方法入手分析

public static void main(String[] args) {
... 代码省略

// 主线程准备一个消息的循环驱动器
Looper.prepareMainLooper();

... 代码省略

// 创建 ActivityThread 主线程
ActivityThread thread = new ActivityThread();
// 线程依附
thread.attach(false, startSeq);

... ...
// 开启循环工作,这也是为何主线程具有消息分发的功能
Looper.loop();
}

ActivityThread#attach()

/**
* @param system 当前是否是系统进程
* @param startSeq 依附起始时间序列
*/
private void attach(boolean system, long startSeq) {

// 只有处于低内存情况下,系统才会行使主权传入进行杀死进程的操作,因此正常情况下,system都是传递false
if (!system) {
... 代码省略

// 获取AIDL接口类型的 ActivityManagerService 对象
final IActivityManager mgr = ActivityManager.getService();
try {
// 向远程服务对象注册我们客户端的代理对象 APT
// 这里要记住,Binder通信几乎都是双向的,使得AMS可以调度我们客户端的四大组件
// 进入Server进程端 AMS,跟踪下去
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}

// Watch for getting close to heap limit.
// 这里本打算省略,但是理解一下也有利于我们深入了解Android系统的GC机制,起到OOM监控作用
// 这里的作用就是当后台进程开启过多,导致系统内存使用紧张达到占用最大值的3/4时,就会释放掉一些页面
// 这也是为何有时回退的时候会发现部分页面丢失了,需要我们重新去加载的原因。
BinderInternal.addGcWatcher(new Runnable() {
@Override public void run() {
if (!mSomeActivitiesChanged) {
return;
}
Runtime runtime = Runtime.getRuntime();
long dalvikMax = runtime.maxMemory();
long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
if (dalvikUsed > ((3*dalvikMax)/4)) {
if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
+ " total=" + (runtime.totalMemory()/1024)
+ " used=" + (dalvikUsed/1024));
mSomeActivitiesChanged = false;
try {
ActivityTaskManager.getService().releaseSomeActivities(mAppThread);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
});
} else {
... 代码省略
}

ViewRootImpl.ConfigChangedCallback configChangedCallback
= (Configuration globalConfig) -> {
synchronized (mResourcesManager) {
// TODO (b/135719017): Temporary log for debugging IME service.
if (Build.IS_DEBUGGABLE && mHasImeComponent) {
Log.d(TAG, "ViewRootImpl.ConfigChangedCallback for IME, "
+ "config=" + globalConfig);
}

// We need to apply this change to the resources immediately, because upon returning
// the view hierarchy will be informed about it.
if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
null /* compat */)) {
updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
mResourcesManager.getConfiguration().getLocales());

// This actually changed the resources! Tell everyone about it.
if (mPendingConfiguration == null
|| mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
mPendingConfiguration = globalConfig;
sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
}
}
}
};
ViewRootImpl.addConfigCallback(configChangedCallback);
}

查阅ActivityManagerService

@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();

// 将IApplicationThread继续传递下去,这个方法里主要作用是通过Binder的native方法得到当前进程的重要id
// 接下来这个方法的代码量接近四百行,单独代码块分析更清晰
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}

AMS#attachApplicationLocked

这个方法的作用:一是调度ActivityThread创建Application;二是继续启动进程创建之前已经加入任务栈的Activity(这在分析Launcher应用进程启动时分析过,也就是launcher应用)

private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {

... 代码省略

if (app.isolatedEntryPoint != null) { // 这里是孤立进程入口,它不应被绑定到应用程序上
// This is an isolated process which should just call an entry point instead of
// being bound to an application.
thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
} else if (instr2 != null) { // 这里的命中条件是活动的Instrumentation如果存在,也就是当前应用已经打开
... ...
} else {
// 对于首次进入的应用进程走这里
thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.mDisabledCompatChanges);
}

... 代码省略
}

继续回到AMS#ApplicationThread#BindApplication

// 这里的入参很多,最终会将这些参数打包通过二进制流传给服务端,通过服务端协调组件的调用
@Override
public final void bindApplication(String processName, ApplicationInfo appInfo,
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) {
... 代码省略

AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providerList.getList();
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
data.autofillOptions = autofillOptions;
data.contentCaptureOptions = contentCaptureOptions;
data.disabledCompatChanges = disabledCompatChanges;
sendMessage(H.BIND_APPLICATION, data);
}

H类是一个Handler对,也就是前面说过的主线程的Handler,在这里发送了一条bindApplication的消息,并且把AppBindData对象传递过去。那么为什么这里会去发送一条Handler消息呢?
是因为AMS等一些系统服务,都在server端,运行在Binder线程池里面,当AMS通过我们传递的ApplicationThread对象调用其bindApplication时,实际上还是运行在子线程里,所以这里使用了Handler机制来进行通信。

在H类的消息分发代码里,只看BIND_APPLICATION分支

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;
private void handleBindApplication(AppBindData data) {

... 代码省略

// 首先对Application进行创建
Application app;

try {
// data.info -》LoadedApk 这个类比较重要,对一些插件化技术
app = data.info.makeApplication(data.restrictedBackupMode, null);

// Propagate autofill compat state
app.setAutofillOptions(data.autofillOptions);

// Propagate Content Capture options
app.setContentCaptureOptions(data.contentCaptureOptions);

mInitialApplication = app;

// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
}
}

// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
// If the app targets < O-MR1, or doesn't change the thread policy
// during startup, clobber the policy to maintain behavior of b/36951662
if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1
|| StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
StrictMode.setThreadPolicy(savedPolicy);
}
}

// Preload fonts resources
FontsContract.setApplicationContextForResources(appContext);
if (!Process.isIsolated()) {
try {
final ApplicationInfo info =
getPackageManager().getApplicationInfo(
data.appInfo.packageName,
PackageManager.GET_META_DATA /*flags*/,
UserHandle.myUserId());
if (info.metaData != null) {
final int preloadedFontsResource = info.metaData.getInt(
ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
if (preloadedFontsResource != 0) {
data.info.getResources().preloadFonts(preloadedFontsResource);
}
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}

首先看一下LoaderApk(相当于apk在运行时的抽象映射)这个类的makeApplication方法

public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {

... 代码省略

// 首先得到应用信息类的类名(mApplicationInfo就是我们在清单文件里注册的xml属性解析得到的对象封装)
String appClass = mApplicationInfo.className;
// 如果清单文件里没有注册,那么就走默认的
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}

try {
... 代码省略

// Instrumentation类是用来创建Application、Activity,以及对生命周期调度的一个工具类(想深入了解,可以继续跟进AppComponentFactory查看)
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
} catch (Exception e) {
... ...
}
// 将当前应用的入口类加入
mActivityThread.mAllApplications.add(app);
mApplication = app;

if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

return app;
}
打赏
  • 微信
  • 支付宝

评论