如何监控冷启动
一旦系统创建了应用程序进程,应用程序进程就负责接下来的阶段:
-
创建应用程序对象。
-
启动主线程。
-
创建主要 Activity 。
-
填充 View 。
-
布置屏幕。
-
进行初始化绘制。
一旦应用进程完成了第一次绘制,系统进程就会换出当前显示的背景窗口,用主活动替换它。 此时,用户可以开始使用该应用程序。
主线程开始
在上一篇博文中,我们了解到:
当应用程序进程启动时,它会调用 ActivityThread.main(),它会在 system_server 进程中对 ActivityManagerService.attachApplication() 进行阻塞 IPC 调用。
system_server 进程对应用进程中的 ActivityThread.bindApplication() 进行 IPC 调用,这将 BIND_APPLICATION 消息排入主线程消息队列。
当对 ActivityManagerService.attachApplication() 的 IPC 调用完成后,ActivityThread.main() 然后调用 Looper.loop(),它会永远循环,处理发布到其 MessageQueue 的消息。
处理的第一条消息是 BIND_APPLICATION,它调用 ActivityThread.handleBindApplication() 来加载 APK 并加载应用程序组件。
这里重要的一点是,在对 ActivityManagerService.attachApplication() 的 IPC 调用返回之前,应用程序进程主线程中不会发生任何事情。
调度 Activity 启动
来看看调用ActivityThread.bindApplication()后system_server进程发生了什么:
public class ActivityManagerService extends IActivityManager.Stub {
private boolean attachApplicationLocked(
IApplicationThread thread, int pid, int callingUid,
long startSeq) {
thread.bindApplication(...);
// See if the top visible activity is waiting to run
// in this process...
mAtmInternal.attachApplication(...);
// Find any services that should be running in this process...
mServices.attachApplicationLocked(app, processName);
// Check if a next-broadcast receiver is in this process...
if (isPendingBroadcastProcessLocked(pid)) {
sendPendingBroadcastsLocked(app);
}
return true;
}
}
复制代码
与 Activity 启动相关的行是 mAtmInternal.attachApplication(...)。 它调用 ActivityTaskManagerService.attachApplication() 调用 RootActivityContainer.attachApplication:
class RootActivityContainer extends ConfigurationContainer {
boolean attachApplication(WindowProcessController app) {
for (ActivityDisplay display : mActivityDisplays) {
ActivityStack stack = display.getFocusedStack()
ActivityRecord top = stack.topRunningActivityLocked();
stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
for (ActivityRecord activity : mTmpActivityList) {
if (activity.app == null
&& app.mUid == activity.info.applicationInfo.uid
&& app.mName.equals(activity.processName)) {
mStackSupervisor.realStartActivityLocked(
activity,
app,
top == activity /* andResume */,
true /* checkConfig */
)
}
}
}
...
}
}
复制代码
上面的代码:
迭代每个 Display 。
检索该 Display 的焦点 Activity 堆栈。
迭代焦点 Activity 堆栈的每个 Activity 。
如果该 Activity 属于正在启动的进程,则调用 ActivityStackSupervisor.realStartActivityLocked()。 请注意,如果活动位于堆栈顶部,则传递为 true 的 andResume 参数。
这是 ActivityStackSupervisor.realStartActivityLocked():
public class ActivityStackSupervisor{
boolean realStartActivityLocked(
ActivityRecord r,
WindowProcessController proc,
boolean andResume,
boolean checkConfig
) {
...
ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
clientTransaction.addCallback(LaunchActivityItem.obtain(...));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
boolean forward = dc.isNextTransitionForward()
lifecycleItem = ResumeActivityItem.obtain(forward);
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction.
mService.getLifecycleManager()
.scheduleTransaction(clientTransaction);
...
}
}
复制代码
到目前为止,我们看到的所有方法调用都发生在 system_server 进程中。 ClientLifecycleManager.scheduleTransaction() 在应用进程中对 ActivityThread.scheduleTransaction() 进行 IPC 调用,调用 ClientTransactionHandler.scheduleTransaction() 将 EXECUTE_TRANSACTION 消息放入主线程消息队列中:
public abstract class ClientTransactionHandler {
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(
ActivityThread.H.EXECUTE_TRANSACTION,
transaction
);
}
}
复制代码
当 EXECUTE_TRANSACTION 被处理时,它调用 TransactionExecutor.execute()。
实际 Activity 启动
TransactionExecutor.execute() 调用 TransactionExecutor.performLifecycleSequence() 调用回 ActivityThread 来创建、启动和恢复活动:
public class TransactionExecutor {
private void performLifecycleSequence(...) {
for (int i = 0, state; i < path.size(); i++) {
state = path.get(i);
switch (state) {
case ON_CREATE:
mTransactionHandler.handleLaunchActivity(...);
break;
case ON_START:
mTransactionHandler.handleStartActivity(...);
break;
case ON_RESUME:
mTransactionHandler.handleResumeActivity(...);
break;
case ON_PAUSE:
mTransactionHandler.handlePauseActivity(...);
break;
case ON_STOP:
mTransactionHandler.handleStopActivity(...);
break;
case ON_DESTROY:
mTransactionHandler.handleDestroyActivity(...);
break;
case ON_RESTART:
mTransactionHandler.performRestartActivity(...);
break;
}
}
}
}
复制代码
第一个绘制
让我们看看从 ActivityThread.handleResumeActivity() 导致第一次绘制的调用序列:
- ActivityThread.handleResumeActivity()
- ➡️ WindowManagerImpl.addView()
- ➡️ WindowManagerGlobal.addView()
- ➡️ ViewRootImpl.setView()
- ➡️ ViewRootImpl.requestLayout()
- ➡️ ViewRootImpl.scheduleTraversals()
- ➡️ Choreographer.postCallback()
- ➡️ Choreographer.scheduleFrameLocked()
Choreographer.scheduleFrameLocked() 将 MSG_DO_FRAME 消息放入主线程消息队列中。
处理 MSG_DO_FRAME 时,它调用 Choreographer.doFrame(),后者调用 ViewRootImpl.doTraversal(),后者执行测量传递、布局传递,最后是视图层次结构上的第一个绘制传递(请参阅 Android 如何绘制视图)。