Detailed explanation of Android activity startup process (based on api28)

Time:2021-6-11

preface

As one of the four major components of Android, activity’s startup is definitely not that simple. This involves the system service process. There are many details of the startup process. Here I only show the main process. The startup process of activity is changing with the change of version, and the code details are changing all the time, such as Android 5.0 and Android 8.0. My version here is based on Android api28, which is also the latest source code I can find at present. In fact, the flow of big questions is the same. If you master one version, you can quickly master other versions through the source code.

Because it involves the communication between different processes: system service process and local process, the latest version of Android uses Aidl to communicate across processes. Therefore, we need to have a certain understanding of Aidl, which will help us understand the whole startup process.

The explanation of the source code part involves a lot of code explanation, which may be a little uncomfortable, but it is still recommended to read the source code. I will add comments to the key code of the source code to facilitate understanding.

The code doesn’t pay too much attention to the details, only the whole process. Want to know the details can go to see the source code. I will mark the path of each code in front of the code. You can check the corresponding source code.

Every part of the source code before I will put the flow chart, must cooperate with the flow chart to eat, otherwise it may be chaotic.

Overview of the overall process

This part focuses on the overview of the whole startup process, and has a general concept in mind, which can help to understand the following specific details of the process.

Creation of ordinary activity

Normal activity creation is usually used in our codestartActivity(Intent intent)Method to create an activity. The overall process is as follows:

普通Activity启动整体流程.png

The startup process is designed into two processes: local process and system service process. The local process is the process where our application is located, and the system service process is the service process shared by all applications. The overall idea is as follows:

  1. Activity requests creation from instrumentation

  2. Instrumentation accesses AMS through the ibinder interface of AMS local process. The cross process technology adopted here is Aidl.

  3. Then the AMS process does a series of work, such as judging whether the activity exists, what the startup mode is, whether it has been registered, and so on.

  4. Through the client lifecycle manager, the local process can directly access the local activitythread in the ibinder interface of the system service process.

    Applicationthread is the inner class of activitythread, iapplicationthread is the binder interface of remote server

  5. After receiving the transaction from the server, applicationthread transfers the transaction directly to activitythread for processing.

  6. Activitythread uses instrumentation to create instances by using class loader and callback the life cycle of activity by using instrumentation

There are two processes involved here. The local process is mainly responsible for creating an activity and callback life cycle. The service process is mainly responsible for judging whether the activity is legal and whether the activity stack needs to be created. Process communication is involved between processes: Aidl( If you are not familiar with it, you can understand it first, but it can be simply understood as interface callback.)

Here are some key classes:

  • Instrumentation is the class that an activity contacts with the outside world (not the outside world of an activity itself, as opposed to an activity). An activity requests creation through instrumentation, and an activitythread creates and invokes the life cycle of an activity through instrumentation.

  • Activitythread, the only instance of each application, is responsible for the management of activity creation, while applicationthread is only the class of communication between application and server process, which is only responsible for communication and handing AMS tasks to activitythread.

  • AMS, full name of activitymanagerservice, is responsible for coordinating the process of activity creation by the server.

    Other classes, the following source code analysis will be explained in detail.

Creation of root activity

Root activity is the process that the first activity of the application starts when we click the desktop icon. Here I will focus on the relationship between multiple processes. The following source code will not explain the details, but only the creation process of ordinary activities. This is also a supplement. Let’s look at the overall flow chart

根Activity启动整体流程.png

It mainly involves four processes

  • The launcher process is the desktop process
  • System service process, AMS process
  • The zygote process is responsible for creating the process
  • Application process, that is, the process to be started

Main process:

  1. The launcher process requests AMS to create an activity
  2. AMS requests zygote to create the process.
  3. Zygote creates the process itself through fork. And inform AMS to complete the creation.
  4. AMS notifies the application process to create a root activity.

It is very similar to the creation of ordinary activities. It mainly involves the creation process.

Explanation of source code

The process of activity requesting AMS

flow chart

Activity请求AMS流程.png

Source code
  1. The system starts the application by calling the startactivitysafety method of the launcher. Launcher is a class that starts the root activity.

    This step is a process only available when the root activity is started. There is no ordinary start-up. It is just a supplement here

    packages/apps/Launcher3/src/com/android/launcher3/Launcher.java/;
    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
        	//Here, the method of the parent class is called. Continue to view the method implementation of the parent class
            boolean success = super.startActivitySafely(v, intent, item);
            ...
            return success;
        }
    packages/apps/Launcher3/src/com/android/launcher3/BaseDraggingActivity.java/;
    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
            ...
            // Prepare intent
            //Setting the flag singletask means opening in a new stack
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            if (v != null) {
                intent.setSourceBounds(getViewBounds(v));
            }
            try {
                boolean isShortcut = Utilities.ATLEAST_MARSHMALLOW
                        && (item instanceof ShortcutInfo)
                        && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
                        || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
                        && !((ShortcutInfo) item).isPromise();
                //Note 1 and note 2 are both started directly with startactivity. Note 1 makes some settings
                //Basedraggingactivity is inherited from baseactivity, and baseactivity is inherited from activity
                //So we jump directly to the startactivity logic of the activity.
                if (isShortcut) {
                    // Shortcuts need some special checks due to legacy reasons.
                    startShortcutIntentSafely(intent, optsBundle, item);//1
                } else if (user == null || user.equals(Process.myUserHandle())) {
                    // Could be launching some bookkeeping activity
                    startActivity(intent, optsBundle);//2
                } else {
                    LauncherAppsCompat.getInstance(this).startActivityForProfile(
                            intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
                }
                
               ...
            } 
        	...
            return false;
        }
  2. Activity starts an activity through instrumentation

    /frameworks/base/core/java/android/app/Activity.java/;
    public void startActivity(Intent intent, @Nullable Bundle options) {
        	//You will eventually jump to the startactivityforresult method
            if (options != null) {
                startActivityForResult(intent, -1, options);
            } else {
                // Note we want to go through this call for compatibility with
                // applications that may have overridden the method.
                startActivityForResult(intent, -1);
            }
        }
    
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                @Nullable Bundle options) {
        	//Mparent refers to the activitygroup, which has been replaced by fragment. It will always be null here
        	//The next step is to start it through meinstruction.execstartactivity
            if (mParent == null) {
                options = transferSpringboardActivityOptions(options);
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);//1
                if (ar != null) {
                    mMainThread.sendActivityResult(
                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
                }
                ...
            }
        ...
    }
  3. Instrumentation requests AMS to start. The function of this class is to monitor the interaction between the application and the system. So far, the task is handed over to AMS. After a series of processing, AMS will call back and start the activity through the local interface iactivitymanager.

    /frameworks/base/core/java/android/app/Instrumentation.java/;
    public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
        ...
        //This place is more complicated. Let's draw a conclusion first. I'll explain it next    
        //The object obtained by activitymanager. Getservice() is activitymanagerservice, referred to as AMS
        //Start activity through AMS. AMS is globally unique, and all activities must be verified and run in independent processes
        //So here is the way to use Aidl for cross process communication, the object obtained is actually an ibinder interface
            
        //Note 2 is to check the startup result, and throw it if there is an exception, such as not registered.
        try {
                intent.migrateExtraStreamToClipData();
                intent.prepareToLeaveProcess(who);
                int result = ActivityManager.getService()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);//1
                checkStartActivityResult(result, intent);//2
            } catch (RemoteException e) {
                throw new RuntimeException("Failure from system", e);
            }
            return null;
        
    }

    This step is to use Aidl technology to carry out cross-border communication. Get the agent object of AMS, and give the startup task to AMS.

    /frameworks/base/core/java/android/app/ActivityManager.java/;
    //Singleton class
    public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
    }
    
    private static final Singleton IActivityManagerSingleton =
    new Singleton() {
    @Override
    protected IActivityManager create() {
    //The ibinder interface of AMS is obtained
    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
    //Convert to iactivitymanager object. The remote service implements this interface, so you can call it directly
    //AMS proxy object interface method to request AMS. The technology used here is Aidl
    final IActivityManager am = IActivityManager.Stub.asInterface(b);
    return am;
    }
    };

The process of AMS processing request

flow chart

AMS处理启动Activity流程.png

Source code
  1. Next, let’s look at the implementation logic of AMS. The source code of AMS is to create an activitystarter through the activitystartcontroller, and then give the logic to the activitystarter to execute. Activitystarter is a class added by Android 7.0.

    /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java/;
    //Jump to startactivityasuser
    //Note that the last parameter, userhandle. Getcallinguserid (), indicates the caller's permission
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
    
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
                Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
                boolean validateIncomingUser) {
            enforceNotIsolatedCaller("startActivity");
    
            userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                    Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
    
            // TODO: Switch to user app stacks here.
        	//Here, you can get the activitystarter through the activitystartcontroller, and use the activitystarter to
        	//Perform the startup task. Here we give the task logic to the activitystarter
            return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                    .setCaller(caller)
                    .setCallingPackage(callingPackage)
                    .setResolvedType(resolvedType)
                    .setResultTo(resultTo)
                    .setResultWho(resultWho)
                    .setRequestCode(requestCode)
                    .setStartFlags(startFlags)
                    .setProfilerInfo(profilerInfo)
                    .setActivityOptions(bOptions)
                    .setMayWait(userId)
                    .execute();
    
        }

    Activitystartcontroller get activitystarter

    /frameworks/base/services/core/java/com/android/server/am/ActivityStartController.java/;
    //Gets the activitystarter object. This object is used only once. When its execute is executed, the object is invalid
    ActivityStarter obtainStarter(Intent intent, String reason) {
    return mFactory.obtain().setIntent(intent).setReason(reason);
    }
  2. This part is mainly about the source code of activitystarter, involving a lot of source code. AMS leaves the whole startup logic to activitystarter. Here, we mainly do pre-processing before starting, creating process and so on.

    /frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java/;
    //Here, you need to start preprocessing and execute the startactivitymaywait method
    int execute() {
            try {
               	...
                if (mRequest.mayWait) {
                    return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                            mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
                            mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                            mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                            mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                            mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                            mRequest.inTask, mRequest.reason,
                            mRequest.allowPendingRemoteAnimationRegistryLookup);
                }
                ...
            } 
        	...
        }
    
    //Start up pretreatment
    private int startActivityMayWait(IApplicationThread caller, int callingUid,
                String callingPackage, Intent intent, String resolvedType,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                IBinder resultTo, String resultWho, int requestCode, int startFlags,
                ProfilerInfo profilerInfo, WaitResult outResult,
                Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
                int userId, TaskRecord inTask, String reason,
                boolean allowPendingRemoteAnimationRegistryLookup) {
            ...
    		//Jump to startactivity
             final ActivityRecord[] outRecord = new ActivityRecord[1];
         	int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup);
    }
    
    //Record information about the startup process and activity
    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            SafeActivityOptions options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
        ...
        //Get the launcher process    
        ProcessRecord callerApp = null;
        if (caller != null) {
            callerApp = mService.getRecordForAppLocked(caller);
            ...
        }
        ...
        //Record the activity information
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, checkedOptions, sourceRecord);
        if (outActivity != null) {
            outActivity[0] = r;
        }
        ...
        mController.doPendingActivityLaunches(false);
    	//Keep jumping
        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity);
    }
    
    //Jump to startactivityUnchecked
    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity) {
        int result = START_CANCELED;
        try {
            mService.mWindowManager.deferSurfaceLayout();
            //Jump
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        } 
        ...
        return result;
    }
    
    //Mainly do stack related logic processing, and jump to activitystack supervisor for processing
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
        ...
        int result = START_SUCCESS;
        //This is the same as the flag we initially set in launcher_ ACTIVITY_ NEW_ Task related, a new stack will be created
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
        }
        ...
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                ...
            } else {
                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
                //Jump到ActivityStackSupervisor进行处理
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                                                                mOptions);
            }
        }
    }
  3. The activitystack supervisor is mainly responsible for the related work of the activity stack, and will work in combination with the activitystack. It mainly determines the state of the activity, whether it is at the top of the stack or in the stop state, etc

    /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java/;
    
    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    	...
        //Determine whether the activity to be started is in stop or resume state
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || !r.isState(RESUMED)) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.isState(RESUMED)) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }
        return false;
    }
  4. Activitystack mainly deals with the state of an activity in the stack

    /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java/;
    //Jump to resumetopactivityinnerlocked
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }
        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            //Jump to resumetopactivityinnerlocked
            result = resumeTopActivityInnerLocked(prev, options);
    	...
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }
    
    //Jump to stacksupervisor.startspecificactivitylocked, note 1
    @GuardedBy("mService")
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        ...
        if (next.app != null && next.app.thread != null) {
            ...
        } else {
            ...
            mStackSupervisor.startSpecificActivityLocked(next, true, true);//1
        }     
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }
  5. Here we go back to the activitystacksupervisor to judge whether the process has been created. If not, we throw an exception. The transaction is then created and handed back to local execution. The transaction here is the key. The work performed by activity is this transaction. The content of the transaction is the items in it. So pay attention to the following two items.

    /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java/;
    
    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        //Get the process of the activity to be started
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);
        getLaunchTimeTracker().setLaunchTime(r);
    
        //Judge whether the process has been started, jump to realstartactivitylocked, and really start the activity
        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, andResume, checkConfig);//1
                return;
            } 
            ...
        }
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
    
    
    //The main task is to create transactions for local execution
    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
        boolean andResume, boolean checkConfig) throws RemoteException {
        ...
        //Create the transaction clienttransaction object that starts the activity
        // Create activity launch transaction.
        final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                r.appToken);
        //Add a launchactivityitem whose content is to create an activity
        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, app.repProcState, r.icicle,
                r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                profilerInfo));
    
        // Set desired final state.
        //Add and execute the resume transaction resumeactivityitem, which will be executed locally later
        final ActivityLifecycleItem lifecycleItem;
        if (andResume) {
            lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
        } else {
            lifecycleItem = PauseActivityItem.obtain();
        }
        clientTransaction.setLifecycleStateRequest(lifecycleItem);
    
        //Starting transactions through client lifecycle manager
        //Here mservice is AMS
        //Remember the above two items: launchactivityitem and resumeactivityitem, which are the execution units of the transaction
        // Schedule transaction.
        mService.getLifecycleManager().scheduleTransaction(clientTransaction);
    }

    Getting client lifecycle manager through AMS

    /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java/;
    //Getting client lifecycle manager through AMS
    ClientLifecycleManager getLifecycleManager() {
    return mLifecycleManager;
    }
  6. Client lifecycle manager is a transaction management class, which is responsible for executing transactions

    /frameworks/base/services/core/java/com/android/server/am/ClientLifecycleManager.java
    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        //Executive affairs
        transaction.schedule();
        if (!(client instanceof Binder)) {
            transaction.recycle();
        }
    }
  7. Leave the transaction to the local activitythread for execution. Here, cross process communication is carried out through iapplicationthread, which is the interface of local applicationthread on the server side. The logic goes back to the application process.

    /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java/;
    
    //The iapplicationthread here is the ibinder interface to start the process
    //Applicationthread is the inner class of activitythread, iapplicationthread is the agent interface of ibinder
    //Here the logic is moved to local execution
    private IApplicationThread mClient;
    public void schedule() throws RemoteException {
        mClient.scheduleTransaction(this);
    }

Activitythread the process of creating an activity

flow chart

ActivityThread响应启动Activity流程.png

Source code
  1. The local implementation of iapplicationthread interface is the inner class applicationthread of activitythread

    /frameworks/base/core/java/android/app/ActivityThread.java/ApplicationThread.class/;
    //Implementation of jump to activitythread
    public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        ActivityThread.this.scheduleTransaction(transaction);
    }
  2. Activitythread executes the transaction. Activitythread inherits from clienttransactionhandler, and scheduletransaction is implemented in clienttransactionhandler. The main content here is to send the transaction to the internal class h of activitythread for execution. H is a handle that switches to the main thread to execute logic.

    /frameworks/base/core/java/android/app/ClientTransactionHandler.java
    void scheduleTransaction(ClientTransaction transaction) {
        //Transaction preprocessing
        transaction.preExecute(this);
        //Here, it is obvious that you can use the handle mechanism to switch threads. Let's take a look at the implementation of this method
        //This method is implemented in activitythread, which is the abstract method of clienttransactionhandler
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
    
    /frameworks/base/core/java/android/app/ActivityThread.java/;
    final H mH = new H();
    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        //Use handle to switch. MH is an instance of the class H
        mH.sendMessage(msg);
    }
  3. H processes the transaction. Call the transaction pool to process the transaction

    /frameworks/base/core/java/android/app/ActivityThread.java/H.class
    //Call the transaction pool to process the transaction
    public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            ...
            case EXECUTE_TRANSACTION:
                final ClientTransaction transaction = (ClientTransaction) msg.obj;
                //Call the transaction pool to process the transaction
                mTransactionExecutor.execute(transaction);
                if (isSystem()) {
                    transaction.recycle();
                }
                // TODO(lifecycler): Recycle locally scheduled transactions.
                break;
                ...
        }
        ...
    }
  4. The transaction pool processes the transaction. The transaction pool will take out two items in the transaction and execute them separately. These two transactions are the two items I mentioned above. Corresponding to different initialization work.

    /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
        
    public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
    
        //Executive affairs
        //These two transactions are the two events added in activitystack supervisor at that time (step 8)
        //Note 1 creates the activity, note 2 executes the activity window, and so on, and calls OnStart and onresume methods
        //Later, we will go into the process of note 1
        executeCallbacks(transaction);//1
        executeLifecycleState(transaction);//2
        mPendingActions.clear();
        log("End resolving transaction");
    }
    
    public void executeCallbacks(ClientTransaction transaction) {
        ...
            //Executive affairs
            //The item here is the item added at the beginning. Do you remember which one it is?
           	//By the way, launchactivityitem
            item.execute(mTransactionHandler, token, mPendingActions);
            item.postExecute(mTransactionHandler, token, mPendingActions);
        ...
    }
    
    private void executeLifecycleState(ClientTransaction transaction) {
        ...
        //As above, execute the item in the transaction, and the item type is resumeactivityitem
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }
  5. Launchactivityitem calls activitythread to execute the creation logic.

    /frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java/;
    
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client);
        //Clienttransactionhandler is the interface implemented by activitythread, and the specific logic goes back to activitythread
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
  6. Activitythread performs the creation of an activity. Instrumentation is mainly used to create and callback the life cycle of an activity, and to create the context of the activity and the app context (if not already created).

    /frameworks/base/core/java/android/app/ActivityThread.java/;
    
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        ...
            //Jump to performlaunchactivity
            final Activity a = performLaunchActivity(r, customIntent);
        ...
    }
    
    //Using instrumentation to create an activity callback lifecycle
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        	//Get activityinfo, and the user stores the code and androidmanives information.
        	ActivityInfo aInfo = r.activityInfo;
            if (r.packageInfo == null) {
                //Get APK description class
                r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                        Context.CONTEXT_INCLUDE_CODE);
            }
        
        	//Gets the package name type information of the activity
        	ComponentName component = r.intent.getComponent();
            if (component == null) {
                component = r.intent.resolveActivity(
                    mInitialApplication.getPackageManager());
                r.intent.setComponent(component);
            }
        ...
            //Create context
            ContextImpl appContext = createBaseContextForActivity(r);
       		//Create an activity
            Activity activity = null;
            try {
                java.lang.ClassLoader cl = appContext.getClassLoader();
                //Creating activities through instrumentation
                activity = mInstrumentation.newActivity(
                        cl, component.getClassName(), r.intent);
                StrictMode.incrementExpectedActivityCount(activity.getClass());
                r.intent.setExtrasClassLoader(cl);
                r.intent.prepareToEnterProcess();
                if (r.state != null) {
                    r.state.setClassLoader(cl);
                }
            }
        ...
            try {
                //Create an application based on the package name. If it has already been created, it will not be created repeatedly
                Application app = r.packageInfo.makeApplication(false, mInstrumentation);
                ...
                //Add window for activity
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }
                appContext.setOuterContext(activity);
                activity.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);
                }
    	...
            //Callback the oncreate method of activity through instrumentation
            ctivity.mCalled = false;
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
    }

    Let’s take a closer look at when oncreate is called

    /frameworks/base/core/java/android/app/Instrumentation.java/;
    public void callActivityOnCreate(Activity activity, Bundle icicle,
      PersistableBundle persistentState) {
    prePerformCreate(activity);
    //The performcreate method of activity is called
    activity.performCreate(icicle, persistentState);
    postPerformCreate(activity);
    }
    
    /frameworks/base/core/java/android/app/Activity.java/;
    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    mCanEnterPictureInPicture = true;
    restoreHasCurrentPermissionRequest(icicle);
    //Here we call back the oncreate method
    if (persistentState != null) {
      onCreate(icicle, persistentState);
    } else {
      onCreate(icicle);
    }
    ...
    }
  7. Instrumentation creates activity instances through class loaders

    /frameworks/base/core/java/android/app/Instrumentation.java/;
    
    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        String pkg = intent != null && intent.getComponent() != null
                ? intent.getComponent().getPackageName() : null;
        //Instantiation with appcomponentfactory
        return getFactory(pkg).instantiateActivity(cl, className, intent);
    }
  8. Finally, create the instance through the appcomponentfactory factory factory.

    /frameworks/support/compat/src/main/java/androidx/core/app/AppComponentFactory.java
    //In fact, it is equivalent to returning to instantiateactivitycompact directly
    public final Activity instantiateActivity(ClassLoader cl, String className, Intent intent)
        throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return checkCompatWrapper(instantiateActivityCompat(cl, className, intent));
    }
        
    //Generic method
    static  T checkCompatWrapper(T obj) {
            if (obj instanceof CompatWrapped) {
                T wrapper = (T) ((CompatWrapped) obj).getWrapper();
                if (wrapper != null) {
                    return wrapper;
                }
            }
            return obj;
        }  
    //It's finally the end. The class loader is used for instantiation. This is the end of the activity startup.
    public @NonNull Activity instantiateActivityCompat(@NonNull ClassLoader cl,
            @NonNull String className, @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        try {
            return (Activity) cl.loadClass(className).getDeclaredConstructor().newInstance();
        } catch (InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException("Couldn't call constructor", e);
        }
    }

Summary

The whole process of an activity startup is analyzed in detail through the whole process and code. I wonder if readers will have a question: what’s the use of understanding these? I can’t use it everyday. When you go through the whole process, you will find that you have a lot more in-depth understanding of Android, and you will be more confident in the face of development. Some bugs may have to be solved by others for a long time, but you will soon be able to solve them. In addition, this part of the content in the plug-in also has a great use, but also learn plug-in must learn knowledge.

Well, I have said so much. I hope the above will help you. If you have any questions, you can exchange them in the comment area or private letter. In addition, the blogger belongs to Android novice, if there is something wrong, please correct.

reference