How to monitor cold start

Once the system has created the application process, the application process is responsible for the following phases:

  1. Create the application object.

  2. Start the main thread.

  3. Create the main Activity.

  4. Populate the View.

  5. Set up the screen.

  6. Initialize the drawing.

Once the application process has finished drawing for the first time, the system process will swap out the currently displayed background window and replace it with the main activity. At this point, the user can start using the application.

Main thread start

In our last blog post, we learned:

When the application process is started, it will call ActivityThread. The main (), it will be in the process of system_server ActivityManagerService. AttachApplication () to block the IPC calls.

Process of system_server ActivityThread. In the process of the application of bindApplication () IPC calls, this will BIND_APPLICATION message in the thread the message queue.

When the ActivityManagerService. AttachApplication (), after the completion of the IPC call ActivityThread. The main () and then call stars. The loop (), it will always be cycle, Processes messages published to its MessageQueue.

Processing BIND_APPLICATION is the first message, it calls the ActivityThread. HandleBindApplication () to load the APK and load application components.

The important point here is that in ActivityManagerService. AttachApplication (IPC) before the call returns, the application process will not happen any things in the main thread.

Schedule an Activity to start

To see call ActivityThread. BindApplication () system_server process after what happened:

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; }}Copy the code

Associated with the Activity start line is mAtmInternal attachApplication (…). . It calls ActivityTaskManagerService. AttachApplication () call 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 */ ) } } } ... }}Copy the code

The code above:

Iterate over each Display.

Retrieves the focus Activity stack for this Display.

Iterate over each Activity in the focus Activity stack.

If the Activity as part of the starting process, called ActivityStackSupervisor. RealStartActivityLocked (). Note that if the activity is at the top of the stack, the andResume parameter is passed to true.

This is 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); . }}Copy the code

All of the method calls we’ve seen so far have occurred in the system_server process. ClientLifecycleManager. ScheduleTransaction () in the process of application of ActivityThread. ScheduleTransaction IPC call (), Call ClientTransactionHandler. ScheduleTransaction () put into the EXECUTE_TRANSACTION message thread message queue:

public abstract class ClientTransactionHandler { /** Prepare and schedule transaction for execution. */ void scheduleTransaction(ClientTransaction transaction) { transaction.preExecute(this); sendMessage( ActivityThread.H.EXECUTE_TRANSACTION, transaction ); }}Copy the code

When EXECUTE_TRANSACTION is processed, it calls the TransactionExecutor. The execute ().

The actual Activity starts

TransactionExecutor. The execute () call TransactionExecutor. PerformLifecycleSequence ActivityThread () calls back to create, launch and recovery activities:

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; }}}}Copy the code

First draw

Let’s take a look at from ActivityThread. HandleResumeActivity () in the first drawing call sequence:

  • ActivityThread.handleResumeActivity()
  • ➡ ️ WindowManagerImpl. AddView ()
  • ➡ ️ WindowManagerGlobal. AddView ()
  • ➡ ️ ViewRootImpl. SetView ()
  • ➡ ️ ViewRootImpl. RequestLayout ()
  • ➡ ️ ViewRootImpl. ScheduleTraversals ()
  • ➡ ️ Choreographer. PostCallback ()
  • ➡ ️ Choreographer. ScheduleFrameLocked ()

Choreographer. ScheduleFrameLocked () put into the MSG_DO_FRAME message threads in the message queue.

When MSG_DO_FRAME is processed, it calls Choreographer.doFrame(), which calls Viewrootimpl.dotraversal (), which performs measurement pass, layout pass, Finally, there is the first draw pass on the view hierarchy (see How Android draws views).