From 0d539ed26f75f78db92c6cc1a65b0736d5e70591 Mon Sep 17 00:00:00 2001 From: Omooo <869759698@qq.com> Date: Tue, 19 May 2020 22:22:45 +0800 Subject: [PATCH] =?UTF-8?q?Update=20Activity=20=E7=BB=84=E4=BB=B6=E7=9A=84?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E8=BF=87=E7=A8=8B.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Activity 组件的启动过程.md | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) diff --git a/blogs/Android/Framework/源代码情景分析/Activity 组件的启动过程.md b/blogs/Android/Framework/源代码情景分析/Activity 组件的启动过程.md index 42f2cce..50e90dd 100644 --- a/blogs/Android/Framework/源代码情景分析/Activity 组件的启动过程.md +++ b/blogs/Android/Framework/源代码情景分析/Activity 组件的启动过程.md @@ -160,3 +160,205 @@ ActivityStack 类的成员变量 mHistory 用来描述系统的 Activity 组件 现在,ActivityStack 类就得到了请求 AMS 执行启动 Activity 组件操作的源 Activity 组件,以及要启动的目标 Activity 组件的信息了,它们分别保存在 ActivityRecord 对象 sourceRecord 和 r 中。最后调用 startActivityUncheckedLocked 进一步执行启动目标 Activity 组件的操作。 +```java +public class ActivityStack { + final int startActivityUncheckedLocked(ActivityRecord r, ...){ + startActivityLocked(ActivityRecord r, ...); + } + + private final void startActivityLocked(ActivityRecord r, ...){ + mHistory.add(addPos, r); + resumeTopActivityLocked(null); + } + + final boolean resumeTopActivityLocked(ActivityRecord prev){ + // next 当前是 MainActivity + ActivityRecord next = topRunningActivityLocked(null); + // mResumedActivity 当前是 Launcher + if(mResumedActivity != null){ + startPausingLocked(); + return true; + } + } +} +``` + +系统当前正在激活的 Activity 组件是 Launcher 组件,即 ActivityStack 类的成员变量 mResumedActivity 指向了 Launcher 组件,因此,接下来就会调用 startPausingLocked 来通知它进入 Paused 状态,它可以将焦点让给即将要启动的 MainActivity 组件。 + +```java +public class ActivityStack { + private final void startPausingLocked() { + ActivityRecord prev = mResumedActivity; + if (prev.app != null && prev.app.thread != null) { + prev.app.thread.schedulePauseActivity(...); + } + } +} +``` + +ActivtyRecord 类有一个成员变量 app,它的类型为 ProcessRecord,用来描述一个 Activity 组件所运行在的应用程序进程;而 ProcessRecord 类又有一个 thread 成员变量,它的类型为 ApplicationThreadProxy,用来描述一个 Binder 代理对象,引用的是一个类型为 ApplicationThread 的 Binder 本地对象。 + +```java +class ApplicationThreadProxy implements IApplicationThread { + public final void schedulePauseActivity(IBinder token, ...){ + Parcel data = Parcel.obtain(); + data.writeStrongBinder(token); + mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); + } +} +``` + +通过 ApplicationThreadProxy 类内部的一个 Binder 代理对象 mRemote 向 Launcher 组件所在的应用程序进程发送一个类型为 SCHEDULE_PAUSE_ACTIVITY_TRANSACTION 的进程间通信请求。 + +这个进程间通信请求是异步的,因此,AMS 将它发送出去之后,就马上返回了。 + +以上都是在 AMS 中执行的,接下来就会在应用程序 Launcher 中去处理 AMS 的请求了。 + +```java +public final class ActivityThread { + private final class ApplicationThread extends ApplicationThreadNative { + public final void schedulePauseActivity(IBinder token, ...) { + queueOrSendMessage(H.PAUSE_ACTIVITY, ...); + } + } +} +``` + +ApplicationThread 类的成员函数 schedulePauseActivity 用来处理类型为 SCHEDULE_PAUSE_ACTIVITY_TRANSACTION 的进程间通信请求。 + +最后调用外部类 ActivityThread 的 queueOrSendMessage 来向 Launcher 的主进程的消息队列发送一个类型为 PAUSE_ACTIVITY 的消息。 + +应用程序 Laucher 为什么不直接在当前线程中执行中止 Launcher 组件的操作呢?一方面是因为当前线程需要尽快返回到 Binder 线程池中去处理其他进程间通信请求;另一方面是因为在中止 Launcher 组件的过程中,可能会涉及用户页面相关的操作,因此就需要将它放在主线程中执行。 + +```java +public final class ActivityThread { + private final class H extends Handler { + public void handleMessage(Message msg) { + switch (msg.what) { + case PAUSE_ACTIVITY: + handlePauseActivity(...); + } + } + } +} + +public final class ActivityThread { + final HashMap mActivities + = new HashMap<>(); + + private final void handlePauseActivity(IBinder token, ...) { + ActivityClientRecord r = mActivities.get(token); + if (r != null) { + performPauseActivity(); + QueuedWork.waitToFinish(); + ActivityManagerNative.getDefault().activityPaused(token, state); + } + } +} +``` + +在应用程序进程中启动的每一个 Activity 组件都使用一个 ActivityClientRecord 对象来描述,这些 ActivtyClientRecord 对象对应于 ActivityManagerService 中的 ActivityRecord 对象,并且保存在 ActivityThread 类的成员变量 mActivities 中。 + +调用成员函数 performPauseActivity 向 Launcher 组件发送一个中止事件通知,即调用它的成员函数 onPause。然后调用 QueuedWork 的 waitToFinish 等待完成前面的一些数据写入操作,例如将数据写入磁盘的操作。由于现在 Launcher 组件即将要进入 Paused 状态了,因此就要保证它前面的所有数据写入操作都处理完成;否则,等到它重新进入 Resumed 状态时,就无法恢复之前所保存的一些状态数据。 + +完成这些事之后,ActivityThread 类的成员函数 handlePauseActivity 就处理完 AMS 给它发送的中止 Launcher 组件的进程间通信请求了。 + +最后调用 ActivityManagerNative 类的静态成员函数 getDefault 来获得 AMS 的一个代理对象,然后再调用这个代理对象的成员函数 activityPaused 来通知 AMS Launcher 组件已经进入 Paused 状态了,因此,它就可以将 MainActivity 组件启动起来了。 + +```java +class ActivityManagerProxy implements IActivityManager { + public void activityPaused(IBinder token, ...) { + Parcel data = Parcel.obtain(); + data.writeStrongBinder(token); + mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, ...); + } +} +``` + +将前面传进来的参数写入到 Parcel 对象 data 中,然后再通过 ActivityManagerProxy 类内部的一个 Binder 代理对象 mRemote 向 AMS 发送一个类型为 ACTIVITY_PAUSED_TRANSACTION 的进程间通信请求。 + +以上都是在应用程序 Launcher 中执行的,接下来是在 AMS 中处理 Launcher 组件发出的进程间通信请求。 + +```java +public final int class ActivityManagerService extends ActivityManagerNative { + public final void activityPaused(IBinder token, ...) { + mMainStack.activityPaused(token, ...); + } +} +``` + +ActivityManagerService 类的成员函数 activityPaused 用来处理类型为 ACTIVITY_PAUSED_TRANSACTION 的进程间通信请求。 + +```java +public class ActivityStack { + final void activityPaused(IBinder token, ...) { + ActivityRecord r = null; + r = (ActivityRecord)mHistory.get(index); + r.state = ActivityState.PAUSED; + completePauseLocked(); + } +} +``` + +首先把 Launcher 组件对应的 ActivityRecord 对象的 state 设置为 PAUSED 状态,表示 Launcher 组件已经进入 Paused 状态了。然后调用 completePauseLocked 来执行启动 MainActivity 组件的操作。 + +```java +public class ActivityStack { + private final void completePauseLocked() { + ActivityRecord prev = mPausingActivity; + resumeTopActivityLocked(prev); + } + + final boolean resumeTopActivityLocked(ActivityRecord prev) { + startSpecificActivityLocked(next, true, true); + } + + private final void startSpecificActivityLocked(ActivityRecord r, ...) { + ProcessRecord app = mService.getProcessRecordLocked(r.processName, ...); + if (app != null && app.thread != null) { + realStartActivityLocked(r, ...); + return; + } + mService.startProcessLocked(r.processName, r.info.application, true, 0, "activity", r.intent.getComponent(), false); + } +} +``` + +在 AMS 中,每一个 Activity 组件都有一个用户 ID 和一个进程名称;其中,用户 ID 是在安装该 Activity 组件时由 PKMS 分配的,而进程名称则是由该 Activity 组件的 android:process 属性来决定的。AMS 在启动一个 Activity 组件时,首先会以它的用户 ID 和进程名称来检查系统中是否存在一个对应的应用程序进程。如果存在,就会直接通知这个应用程序进程将该 Activity 组件启动起来;否则,就会先以这个用户 ID 和进程名称来创建一个应用程序进程,然后再通知这个应用程序进程将该 Activity 组件启动起来。 + +如果 ActivityRecord 对象 r 对应的 Activity 组件所需要的应用程序进程已经存在,就直接调用 realStartActivityLocked 来启动该 Activity 组件,否则,就先调用 startProcessLocked 为该 Activity 组件创建一个应用程序进程,然后再将它启动起来。 + +由于 MainActivity 组件是第一次被启动,所以 AMS 会先创建应用程序进程。 + +```java +// AMS +private final void startProcessLocked(...) { + int pid = Process.start("android.app.ActivityThread", ...); +} +``` + +调用 Process 类的 start 来启动一个新的应用程序进程,指定了该进程的入口函数为 ActivityThread 的 main 函数。 + +```java +public final class ActivityThread { + final ApplicationThread mAppThread = new ApplicationThread(); + + private final void attach(boolean system) { + IActivityManager mgr = ActivityManagerNative.getDefault(); + mgr.attachApplication(mAppThread); + } + + public static final void main(String[] args) { + Looper.prepareMainLooper(); + ActivityThread thread = new ActivityThread(); + thread.attach(false); + Looper.loop(); + } +} +``` + +新的应用程序进程在启动时,主要做了两件事情: + +1. 在进程中创建一个 ActivityThread 对象,并且调用 attach 函数向 AMS 发送一个启动完成通知 +2. 创建一个消息循环 +