1、问题

Android 11 Launcher启动流程分析说过,Android App进程的入口是“android.app.ActivityThread”,那么:

  1. ActivityThread在Android App中充当一个什么样的角色?
  2. 它是怎么创建Application的?Application的生命周期是怎样的?
  3. 第一个Activity是怎么启动的?

2、ActivityThread#main

Android 11 进程启动分析(一)中可以看到,Android进程创建(fork)之后都会调用入口类的main方法,这与Java语言本身的设定是一致的。所以这里我们从ActivityThread#main入手,看看它都干了些什么。

public static void main(String[] args) {// 初始化选择性的系统拦截,这里我们不深究AndroidOs.install();...Looper.prepareMainLooper();...ActivityThread thread = new ActivityThread();thread.attach(/*system*/false, startSeq);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}...Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");
}

这里的操作很简单,就是创建了一个ActivityThread对象并调用它的attach方法,然后进入主线程消息循环。

3、ActivityThread#attach

private void attach(boolean system, long startSeq) {sCurrentActivityThread = this;mSystemThread = system;if (!system) {android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",UserHandle.myUserId());// 这里只是进行了一个赋值操作,没有额外的方法调用RuntimeInit.setApplicationObject(mAppThread.asBinder());// IActivityManager是一个AIDL接口,实现类是ActivityManagerServicefinal IActivityManager mgr = ActivityManager.getService();try {mgr.attachApplication(mAppThread, startSeq);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}// 添加监听,当使用内存超过最大可用内存3/4的时候,释放一些Activity,避免OOMBinderInternal.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 {...}...
}

这里对是否是系统进程做了一个判断,我们这里是分析非系统进程,所以只看if分支。if分支做了两件事情:

  1. 调用ActivityManagerService的attachApplication方法,注册ActivityThread
  2. 添加监听,当使用内存超过最大可用内存3/4的时候,释放一些Activity,避免OOM

这里有一个规律,一般系统的IxxxManager AIDL接口,实现类为xxxManagerService,比如IActivityManager -> ActivityManagerService,IActivityTaskManager -> ActivityTaskManagerService,IWindowManager -> WindowManagerService等等。

这里跟进ActivityManagerService的attachApplication方法。需要注意的是这个方法传进去的mAppThread参数是一个ApplicationThread的对象,它在ActivityThread初始化的时候就new了

final ApplicationThread mAppThread = new ApplicationThread();

ApplicationThread实现了IApplicationThread AIDL接口,用于与AMS通信。

4、ActivityManagerService#attachApplication

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);}
}

这里做了一个判空,然后调用了attachApplicationLocked方法

private boolean attachApplicationLocked(@NonNull IApplicationThread thread,int pid, int callingUid, long startSeq) {ProcessRecord app;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) {thread.bindApplication(processName, appInfo, providerList,instr2.mClass,profilerInfo, instr2.mArguments,instr2.mWatcher,instr2.mUiAutomationConnection, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.isPersistent(),new Configuration(app.getWindowProcessController().getConfiguration()),app.compat, getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, autofillOptions, contentCaptureOptions,app.mDisabledCompatChanges);} 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);}if (profilerInfo != null) {profilerInfo.closeFd();profilerInfo = null;}app.makeActive(thread, mProcessStats);mProcessList.updateLruProcessLocked(app, false, null);boolean badApp = false;boolean didSomething = false;// See if the top visible activity is waiting to run in this process...// 处理栈顶等待运行的ActivitydidSomething = mAtmInternal.attachApplication(app.getWindowProcessController());// Find any services that should be running in this process...didSomething |= mServices.attachApplicationLocked(app, processName);// Check if a next-broadcast receiver is in this process...if (!badApp && isPendingBroadcastProcessLocked(pid)) {didSomething |= sendPendingBroadcastsLocked(app);}// Check whether the next backup agent is in this process...if (!badApp && backupTarget != null && backupTarget.app == app) {thread.scheduleCreateBackupAgent(backupTarget.appInfo,compatibilityInfoForPackage(backupTarget.appInfo),backupTarget.backupMode, backupTarget.userId);}...return true;
}

这里做了一系列检查和处理之后调用了IApplicationThread对象thread的bindApplication接口,然后调用ProcessList.updateLruProcessLocked方法,让ProcessList去管理这个进程,这个在后续Android的进程管理相关文章会讲到。
紧接着,由调用了mAtmInternal.attachApplication方法,通过注释我们可以看到,这会检查栈顶Activity是否等待运行。
接下来是检查服务和广播,以及备份代理(BackupAgent)?

5、ApplicationThread#bindApplication

先看IApplicationThread#bindApplication,我们知道IApplicationThread的实现类就是ApplicationThread,ApplicationThread#bindApplication方法如下:

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 = ...sendMessage(H.BIND_APPLICATION, data);
}

总体来说就是打包了传进来的参数,然后通过Message发给Handler处理。该Message的处理定义在ActivityThread的内部类H中:

H.handleMessage():

public void handleMessage(Message msg) {switch (msg.what) {case BIND_APPLICATION:AppBindData data = (AppBindData)msg.obj;handleBindApplication(data);break;case...
}

这里进而调用了ActivityThread的handleBindApplication方法。

private void handleBindApplication(AppBindData data) {...mInstrumentation = new Instrumentation();mInstrumentation.basicInit(this);Application app;...// 实例化Application对象!app = data.info.makeApplication(data.restrictedBackupMode, null);...mInitialApplication = app;...mInstrumentation.onCreate(data.instrumentationArgs);mInstrumentation.callApplicationOnCreate(app);...
}

这里创建了mInstrumentation和mInitialApplication成员变量。data.info是一个LoadedApk类对象,一起来看看它的makeApplication方法吧。

LoadedApk#makeApplication():

public Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) {if (mApplication != null) {return mApplication;}Application app = null;String appClass = mApplicationInfo.className;if (forceDefaultAppClass || (appClass == null)) {appClass = "android.app.Application";}final java.lang.ClassLoader cl = getClassLoader();ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);...app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);appContext.setOuterContext(app);mActivityThread.mAllApplications.add(app);mApplication = app;...return app;
}

这里先创建了Application的Context,然后通过ActivityThread的mInstrumentation成员变量的newApplication方法。

Instrumentation#newApplication(java.lang.ClassLoader, java.lang.String, android.content.Context):

public Application newApplication(ClassLoader cl, String className, Context context)throws InstantiationException, IllegalAccessException, ClassNotFoundException {Application app = getFactory(context.getPackageName()).instantiateApplication(cl, className);app.attach(context);return app;
}

这里先获取了一个AppComponentFactory对象,然后调用它的instantiateApplication方法,然后调用了Application#attach方法。可以看到Application创建完成后,第一时间被调用的并不是它的onCreate方法。

AppComponentFactory类的注释是

Interface used to control the instantiation of manifest elements

也就是说,它是专门用来实例化manifest里面定义的元素对应组件的工厂类,包括Application和四大组件。我们来看它的instantiateApplication方法:

public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,@NonNull String className)throws InstantiationException, IllegalAccessException, ClassNotFoundException {return (Application) cl.loadClass(className).newInstance();
}

这个很简单,无须多言。接下来我们看看Application第一个被调用的方法Application#attach(Context)

final void attach(Context context) {attachBaseContext(context);mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

这里又调用了它的attachBaseContext方法,并给mLoadedApk赋值。Application本身继承自ContextWrapper,关于Context、ContextWrapper和ContextImpl可以参考这篇文章。

回到ActivityThread的handleBindApplication方法。

private void handleBindApplication(AppBindData data) {...// 实例化Application对象!app = data.info.makeApplication(data.restrictedBackupMode, null);...mInitialApplication = app;...mInstrumentation.onCreate(data.instrumentationArgs);// callApplicationOnCreate里调用了Application的onCreate方法mInstrumentation.callApplicationOnCreate(app);...
}

Application创建完成之后,调用了attach方法,然后才是我们熟悉的onCreate方法。这是因为Context包含了Android为我们封装好的上下文环境,有了它我们才更方便地在onCreate中进行各种操作。

至此,Application的创建和初始化就完成了。

6、ActivityTaskManagerService.LocalService#attachApplication

回到第4节分析ActivityManagerService#attachApplicationLocked方法的时候,看到:

// See if the top visible activity is waiting to run in this process...
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());

这里就是启动Activity的相关代码了。mAtmInternal是ActivityTaskManagerInternal的实例,实现类为ActivityTaskManagerService.LocalService。来看看ActivityTaskManagerService.LocalService#attachApplication 都干了些什么吧

public boolean attachApplication(WindowProcessController wpc) throws RemoteException {synchronized (mGlobalLockWithoutBoost) {...mRootWindowContainer.attachApplication(wpc);...}
}

跟进RootWindowContainer#attachApplication()

boolean attachApplication(WindowProcessController app) throws RemoteException {final String processName = app.mName;boolean didSomething = false;for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {final DisplayContent display = getChildAt(displayNdx);final ActivityStack stack = display.getFocusedStack();if (stack == null) {continue;}mTmpRemoteException = null;mTmpBoolean = false; // Set to true if an activity was started.final PooledFunction c = PooledLambda.obtainFunction(RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,PooledLambda.__(ActivityRecord.class), app, stack.topRunningActivity());stack.forAllActivities(c);c.recycle();if (mTmpRemoteException != null) {throw mTmpRemoteException;}didSomething |= mTmpBoolean;}if (!didSomething) {ensureActivitiesVisible(null, 0, false /* preserve_windows */);}return didSomething;
}

这里做了一个遍历,获取每个DisplayContent中活跃的任务栈,然后去启动对应的Activity。

跟进RootWindowContainer#startActivityForAttachedApplicationIfNeeded()

private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,WindowProcessController app, ActivityRecord top) {...if (mStackSupervisor.realStartActivityLocked(r, app, top == r /*andResume*/,true /*checkConfig*/)) {mTmpBoolean = true;}...
}

这里我们如果是启动Launcher或者从Launcher启动App,top == r应为true,也就是andResume参数为true
跟进StackSupervisor#realStartActivityLocked()方法

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,boolean andResume, boolean checkConfig) throws RemoteException {...// Create activity launch transaction.// 创建activity启动事务final ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.appToken);final DisplayContent dc = r.getDisplay().mDisplayContent;clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,// TODO: Have this take the merged configuration instead of separate global// and override configs.mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),r.getSavedState(), r.getPersistentSavedState(), results, newIntents,dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),r.assistToken, r.createFixedRotationAdjustmentsIfNeeded()));// Set desired final state.final ActivityLifecycleItem lifecycleItem;if (andResume) {lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());} else {lifecycleItem = PauseActivityItem.obtain();}clientTransaction.setLifecycleStateRequest(lifecycleItem);// Schedule transaction.mService.getLifecycleManager().scheduleTransaction(clientTransaction);...return true;
}

可以看到,这里andResume为true的情况下,事务会连续执行LaunchActivityItem和ResumeActivityItem的动作。
LaunchActivityItem和ResumeActivityItem是都是ClientTransactionItem的子类。

根据经验可以看出LaunchActivityItem和ResumeActivityItem等等是对操作Activity不同生命周期的封装,具体操作应该会在子类实现。这里具体操作在execute方法。

先看LaunchActivityItem#execute:

public void execute(ClientTransactionHandler client, IBinder token,PendingTransactionActions pendingActions) {ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,mPendingResults, mPendingNewIntents, mIsForward,mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments);client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
}

方法很简单,就是调用了ClientTransactionHandler的handleLaunchActivity,而ActivityThread正是继承自ClientTransactionHandler。来看看ActivityThread#handleLaunchActivity:

public Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {...final Activity a = performLaunchActivity(r, customIntent);...return a;
}

这里核心代码也很简单,跟进

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {...ContextImpl appContext = createBaseContextForActivity(r);Activity activity = null;java.lang.ClassLoader cl = appContext.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);StrictMode.incrementExpectedActivityCount(activity.getClass());...Application app = r.packageInfo.makeApplication(false, mInstrumentation);if (activity != null) {...// Activity resources must be initialized with the same loaders as the// application context.appContext.getResources().addLoaders(app.getResources().getLoaders().toArray(new ResourcesLoader[0]));appContext.setOuterContext(activity);// 没有调用onCreate前,先调用attachactivity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback,r.assistToken);...activity.mCalled = false;// 执行onCreate方法if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}...}r.setState(ON_CREATE);// updatePendingActivityConfiguration() reads from mActivities to update// ActivityClientRecord which runs in a different thread. Protect modifications to// mActivities to avoid race.synchronized (mResourcesManager) {mActivities.put(r.token, r);}...return activity;
}

可以看到,这里Activity创建之后也不是第一时间调用onCreate方法,而是先调用attach准备上下文环境。

Instrumentation#callActivityOnCreate(android.app.Activity, android.os.Bundle):

public void callActivityOnCreate(Activity activity, Bundle icicle) {prePerformCreate(activity);activity.performCreate(icicle);postPerformCreate(activity);
}

这里调用了Activty#performCreate,看看它都干了些啥:

final void performCreate(Bundle icicle) {performCreate(icicle, null);
}@UnsupportedAppUsage
final void performCreate(Bundle icicle, PersistableBundle persistentState) {dispatchActivityPreCreated(icicle);...if (persistentState != null) {onCreate(icicle, persistentState);} else {onCreate(icicle);}...dispatchActivityPostCreated(icicle);
}

这里有3个关键调用,onCreate就不必多说了。来看看dispatchActivityPreCreated方法:

private void dispatchActivityPreCreated(@Nullable Bundle savedInstanceState) {getApplication().dispatchActivityPreCreated(this, savedInstanceState);Object[] callbacks = collectActivityLifecycleCallbacks();if (callbacks != null) {for (int i = 0; i < callbacks.length; i++) {((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreCreated(this,savedInstanceState);}}
}

这就是为什么我们可以在Application或者Activity中调用registerActivityLifecycleCallbacks方法来添加Activity声明周期的监听了。

这里分析了Activity的创建流程,resume的流程也是类似,自行查看以下就可以了,这里不啰嗦了。

7、ActivityThread总览

8、总结

本文开头提出了3个问题,现在总结答案。

  1. ActivityThread在Android App中充当一个什么样的角色?
    ActivityThread是App进程的入口类,它负责主线程消息循环的创建、Application的创建、与AMS通信、调度四大组件的创建和它们的生命周期。

  2. 它是怎么创建Application的?Application的生命周期是怎样的?
    这个问题并没有完全回答,Application的创建是在AMS调度下通过ActicityThread的mInstrumentation反射创建的,在调用onCreate方法之前先调用了attach方法来初始化上下文。至于销毁和低内存等,会在后续的进程管理相关文章继续解答。

  3. 第一个Activity是怎么启动的?
    AMS在调度完Application的创建和绑定之后,检查是否有待启动的,有的化通知ActivityThread进行创建并执行相关的生命周期方法。与Application一样,先调用了attach准备上下文环境,然后才是onCreate。

另外,需要注意的是,可以看出Application是与进程相关的,一个App如果有多个进程,那么Application也会创建多次。

ActivityThread源码分析相关推荐

  1. 【Android 安全】DEX 加密 ( Application 替换 | Android 应用启动原理 | ActivityThread 源码分析 )

    文章目录 一.ActivityThread 源码分析 二.ActivityThread 部分代码示例 dex 解密时 , 需要将 代理 Application 替换为 真实 Application ; ...

  2. 2-APP启动过程2+ActivityThread源码分析

    下面看下app初始化的主要步骤,app的初始化时从ActivityThread的main()开始的.首先,ActivityThread并不是一个线程,但它从main()跑起来后,它是程序运行的当前环境 ...

  3. ActivityThread 源码分析

    目录 前言 分析 ActivityThread 的消息分发机制 总结 前言 前面分析了 Activity 的启动流程,ActivityThread 作为一个非常重要的角色发挥了非常重要的作用,为了对启 ...

  4. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread 流程分析 二 )

    文章目录 前言 一.ActivityManagerService.attachApplicationLocked 二.ActivityStackSupervisor.attachApplication ...

  5. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 二 )

    文章目录 前言 一.ActivityThread 类 handleLaunchActivity -> performLaunchActivity 方法 二.Instrumentation.new ...

  6. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 一 )

    文章目录 前言 一.ClientTransactionHandler.scheduleTransaction 二.ActivityThread.H 处理 EXECUTE_TRANSACTION 消息 ...

  7. 【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )

    文章目录 前言 一.热启动与冷启动选择 二.AMS 进程中执行的相关操作 三.通过 Binder 机制转到 ActivityThread 中执行的操作 总结 前言 上一篇博客 [Android 启动过 ...

  8. 【Android 安全】DEX 加密 ( Application 替换 | 获取 ContextImpl、ActivityThread、LoadedApk 类型对象 | 源码分析 )

    文章目录 一.获取对象类型分析 二.获取 ContextImpl 类型对象 三.获取 ActivityThread.LoadedApk 类型对象 dex 解密时 , 需要将 代理 Applicatio ...

  9. 【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 )

    文章目录 一.Activity 启动源码分析 ( AMS | ActivityManagerService ) 1.Instrumentation 调用 AMS 方法 2.ActivityStarte ...

最新文章

  1. Thrift协议与传输选择
  2. js去掉前后空格的函数_2020年最火爆的Vue.js面试题
  3. 关于get和post两种提交方式
  4. centos 编译安装mysql
  5. 冯珊珊_高球一姐【冯珊珊】签约【GREENJOY】成为品牌全球代言人
  6. 想做网络推广教你如何快速通过SEO考核期呢?
  7. Python---编写一函数,将摄氏温度与华氏温度互转。
  8. 【转】Postman安装与使用
  9. layui 单选框、复选框、下拉菜单 不显示问题 记录
  10. ssrs 基于表达式显示_基于表达式的访问控制
  11. 二叉树非递归后序遍历算法
  12. centeros7安装mysql
  13. 统计带头结点的单向链表的个数并存放在形参n所指的单元中。 欢迎评论 指点。
  14. java可以连接php吗_java - 需要PHP或Java代码才能使用多个Internet连接
  15. [原创]Tsung压力测试工具简介及安装
  16. 内容提供者和内容观察者
  17. XP仿Windows7主题包 不占内存的。
  18. Java高并发编程实战4,synchronized与Lock底层原理
  19. 红外接收C语言实现 NEC 定时器
  20. HC595驱动数码管

热门文章

  1. 任正非小女儿姚安娜正式出道 | 钛快讯
  2. 《pr相关资源教程》
  3. mac 实现python自动微信发消息案例
  4. 详解分治法(divide-and-conquer)及其典型应用
  5. 打造智能化交通出行的关键技术依仗-智慧交通
  6. 文本特征提取之词袋模型
  7. #inclde<>和#include“ “的区别
  8. 回文自动机 / 回文树
  9. musescore windows 上面编译
  10. 《惢客创业日记》2019.07.19(周五)同质化的创业危机