preface

Recently, I have been researching the source code of the system and found that a lot of the literature is out of date. “Exploring the Art of Android Development” is a good book, but based on 5.0, it is not able to keep pace with Google

Accidentally found “Android Advanced Decryption”, written based on 8.0, feel pleasantly surprised

This surprise didn’t last long. Compared with the android 11 code, there were still many steps changed, and there was not much update in this aspect. Finally, I decided to stand on the shoulders of giants to sort out and leave a message to remember

Let’s start with the Activity

The original idea was to start with the introduction of the system startup, but considering which way is better for readers to absorb, I finally chose to start with the Activity that everyone is most familiar with.

Versioning analysis

There are a lot of literature on the market about the correct startup process of Android 8. However, the coverage of mobile phones before Android is getting lower and lower now, so this paper only analyzes the system of Android 8-11

In order not to confuse the process, except for some version of the process does not change much, I will try to describe the rest separately.

Some young comrades do not speak wushu, do not want to see the code, you can directly pull the last to see the summary. But the best advice is to look at the sequence diagram first, then look at the source code, then go back and compare the sequence diagram, even better, download the source code and look at it yourself.

(Due to the word limit of digging gold, the summary is put in the next article. After review, the address of the next article will be posted in the comments section.)

Android 8 – 9

Request the AMS

First look at the sequence diagram:



We usually start an Activity using the startActivity method or startActivityForResult, but we end up calling startActivityForResult

frameworks/base/core/java/android/app/Activity.java

    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        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);
        }
    }

Copy the code
@Override public void startActivityForResult( String who, Intent intent, int requestCode, @Nullable Bundle options) { ... Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, who, intent, requestCode, options); . }Copy the code

The execStartActivity method of the Instrumentation is then called

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) { IApplicationThread whoThread = (IApplicationThread) contextThread; . try { ... int result = ActivityManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target ! = null ? target.mEmbeddedID : null, requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; }Copy the code

The ActivityManager getService method is called to get the AMS proxy object, followed by its startActivity method

The important thing to note here is, Android8.0 didn’t get the AMS proxy object through ActivityManagerNative’s getDefault. Now this logic is encapsulated in ActivityManager instead of ActivityManagerNative.

frameworks/base/core/java/android/app/ActivityManager.java

@SystemService(Context.ACTIVITY_SERVICE)
public class ActivityManager {
   public static IActivityManager getService(a) {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create(a) {
                    // context. ACTIVITY_SERVICE value is "activity"
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    returnam; }}; }Copy the code

GetService method calls the get method, IActivityManagerSingleton IActivityManagerSingleton is a Singleton class.

This code USES the AIDL IActivityManager. Java classes are automatically generated by the AIDL tool at compile time, to achieve interprocess communication, the server is the AMS only needs to inherit IActivityManager. A Stub class and implement the corresponding method.

Note that Android8.0 didn’t use AIDL before Android8.0. Instead, it used an aidl-like form of AMS proxy object ActivityManagerProxy to communicate with AMS between processes. Android8.0 removes ActivityManagerNative’s internal class ActivityManagerProxy and replaces it with IActivityManager, which is the local proxy for AMS. Go back to the execStartActivity method of the Instrumentation class and see that the execStartActivity method ends up calling the startActivity method of AMS.

AMS calls to ApplicationThread

Let’s take a look at the code inside AMS

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
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());
}

Copy the code
@Override 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) {// Determine whether the caller process is isolated and throw SecurityException enforceNotIsolatedCaller("startActivity") if it is isolated; / / check if the caller has permission, without permission will be abnormal SecurityException userId. = mUserController handleIncomingUser (Binder. The getCallingPid (), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null); // TODO: Switch to user app stacks here. return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser"); }Copy the code

As you can see, AMS uses ActivityStarter to start activities

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

final 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, Bundle bOptions, boolean ignoreTargetSecurity, int userId, TaskRecord inTask, String reason) { .... final ActivityRecord[] outRecord = new ActivityRecord[1]; int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason); . return res; }}Copy the code

We see startActivityLocked method, this method in ActivityStarter. Call startActivity ago, will do some checking

int startActivityLocked(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, ActivityOptions options, boolean ignoreTargetSecurity, Boolean componentSpecified, ActivityRecord[] outActivity, TaskRecord inTask, String Reason) {// startActivity will not be called directly, If (textutils.isempty (reason)) {throw new IllegalArgumentException("Need to specify a reason."); } mLastStartReason = reason; mLastStartActivityTimeMs = System.currentTimeMillis(); mLastStartActivityRecord[0] = null; mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord, inTask); if (outActivity ! = null) { // mLastStartActivityRecord[0] is set in the call to startActivity above. outActivity[0] = mLastStartActivityRecord[0]; } // Aborted results are treated as successes externally, but we must track them internally. return mLastStartActivityResult ! = START_ABORTED ? mLastStartActivityResult : START_SUCCESS; }Copy the code

The startActivity method is then called

/** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */ 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, ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, TaskRecord inTask) { int err = ActivityManager.START_SUCCESS; // Pull the optional Ephemeral Installer-only bundle out of the options early. final Bundle verificationBundle = options ! = null ? options.popAppVerificationBundle() : null; ProcessRecord callerApp = null; if (caller ! = null) {// Get the callerApp object representing the process Launcher. It is of type ProcessRecord, which describes an application process called callerApp = mService.getRecordForAppLocked(caller); if (callerApp ! = null) { callingPid = callerApp.pid; callingUid = callerApp.info.uid; } else { Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting: " + intent.toString()); err = ActivityManager.START_PERMISSION_DENIED; }}... ActivityRecord r = new startActivity(mService, callerApp, callingPid, callingUid, callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession ! = null, mSupervisor, options, sourceRecord); if (outActivity ! = null) { outActivity[0] = r; }... doPendingActivityLaunchesLocked(false); return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask, outActivity); }Copy the code

Before starting an Activity, the system creates a startActivity object. The ActivityRecord object describes an Activity and records all information about an Activity

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(); result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, outActivity); } finally { ... }... return result; }Copy the code

The startActivityUnchecked method has a lot of code and handles stack manage-related logic.

// Note: This method should only be called from {@link startActivity}. private int startActivityUnchecked(final ActivityRecord r,  ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { ... // If the activity being launched is the same as the one currently at the top, then // we need to check if it should only be launched once. final ActivityStack topStack = mSupervisor.mFocusedStack; final ActivityRecord topFocused = topStack.topActivity(); final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); . FLAG_ACTIVITY_NEW_TASK // Should this be considered a new task? int result = START_SUCCESS; if (mStartActivity.resultTo == null && mInTask == null && ! mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) ! = 0) { newTask = true; / / setTaskFromReuseOrCreateNewTask method can create a new Activity within the task stack result = setTaskFromReuseOrCreateNewTask (taskToAffiliate, preferredLaunchStackId, topStack); } else if (mSourceRecord ! = null) { result = setTaskFromSourceRecord(); } else if (mInTask ! = null) { result = setTaskFromInTask(); } else { // This not being started from an existing activity, and not part of a new task... // just put it in the top task, though these days this case should never happen. setTaskToCurrentTopOrCreateNewTask(); } if (result ! = START_SUCCESS) { return result; }... if (mDoResume) { final ActivityRecord topTaskActivity = mStartActivity.getTask().topRunningActivityLocked(); if (! mTargetStack.isFocusable() || (topTaskActivity ! = null && topTaskActivity.mTaskOverlay && mStartActivity ! = topTaskActivity)) { ... } else { // If the target stack was not previously focusable (previous top running activity // on that stack was not visible) then any prior calls to move the stack to the // will not update the focused stack. If starting the new activity now allows the // task stack to be focusable, then ensure that we now update the focused stack // accordingly. if (mTargetStack.isFocusable() && ! mSupervisor.isFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityUnchecked"); } mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); } } else { mTargetStack.addRecentActivityLocked(mStartActivity); } mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack); mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId, preferredLaunchDisplayId, mTargetStack.mStackId); return START_SUCCESS; }Copy the code

The next call is ActivityStackSupervisor resumeFocusedStackTopActivityLocked method, start from here to handle the stack

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (! readyToResume()) { return false; } if (targetStack ! = null && isFocusedStack(targetStack)) { return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } / / get to start the Activity in the nucleus is not in a stopped state on the top of the ActivityRecord final ActivityRecord r = mFocusedStack. TopRunningActivityLocked (); if (r == null || r.state ! = RESUMED) { mFocusedStack.resumeTopActivityUncheckedLocked(null, null); } else if (r.state == RESUMED) { // Kick off any lingering app transitions form the MoveTaskToFront operation. mFocusedStack.executeAppTransition(targetOptions); } return false; }Copy the code

ActivityStackSupervisor is the help class of ActivityStack, which needs ActivityStack to process the next stack

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

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; result = resumeTopActivityInnerLocked(prev, options); } finally { mStackSupervisor.inResumeTopActivity = false; } final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */); if (next == null || ! next.canTurnScreenOn()) { checkReadyForSleep(); } return result; }Copy the code

ResumeTopActivityInnerLocked content many, we are only concerned with the following code

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { ... mStackSupervisor.startSpecificActivityLocked(next, true, false); . return true; }Copy the code

ActivityStackSupervisor again, call startSpecificActivityLocked method

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // Is this activity's application already running? ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); r.getStack().setLaunchTime(r); if (app ! = null && app.thread ! = null) { try { if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !" android".equals(r.info.packageName)) { // Don't add this if it is a platform component that is marked // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats); } realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e); } // If a dead object exception was thrown -- fall through to // restart the application mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }Copy the code

The next step is realStartActivityLocked, at which point the stack is basically processed and ready to notify ApplicationThread

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { ... app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, 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, ! andResume, mService.isNextTransitionForward(), profilerInfo); . }Copy the code

App. thread refers to IApplicationThread, which is implemented as the inner class ApplicationThread of ActivityThread. ApplicationThread inherits from iApplicationThread.stub

ActivityThread Starts the Activity

The previous section wrote that AMS ultimately notifies the ApplicationThread in various ways. In this step, the ApplicationThread tells the ActivityThread via a message mechanism

frameworks/base/core/java/android/app/ActivityThread.java#ApplicationThread

  @Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }
Copy the code

Let’s look at the code for sendMessage

frameworks/base/core/java/android/app/ActivityThread.java

    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);
        }
        mH.sendMessage(msg);
    }
Copy the code

It sends a Message to an mH object with what h.launch_activity (value 100) and obj for ActivityClientRecord, H is a Handler inside the ActivityThread and when it receives the instruction, H calls the handleLaunchActivity method

private class H extends Handler { public static final int LAUNCH_ACTIVITY = 100; public static final int RELAUNCH_ACTIVITY = 101; . String codeToString(int code) { if (DEBUG_MESSAGES) { switch (code) { case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY"; . } } return Integer.toString(code); } public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { case LAUNCH_ACTIVITY: { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); final ActivityClientRecord r = (ActivityClientRecord) msg.obj; r.packageInfo = getPackageInfoNoCheck( r.activityInfo.applicationInfo, r.compatInfo); handleLaunchActivity(r, null, "LAUNCH_ACTIVITY"); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; case RELAUNCH_ACTIVITY: { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart"); ActivityClientRecord r = (ActivityClientRecord)msg.obj; handleRelaunchActivity(r); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; . } Object obj = msg.obj; if (obj instanceof SomeArgs) { ((SomeArgs) obj).recycle(); } if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what)); }}Copy the code

Let’s first look at the getPackageInfoNoCheck method, which gets the package information for the application and returns the LoadedApk object

public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai, CompatibilityInfo compatInfo) { return getPackageInfo(ai, compatInfo, null, false, true, false); } private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode, boolean registerPackage) { final boolean differentUser = (UserHandle.myUserId() ! = UserHandle.getUserId(aInfo.uid)); synchronized (mResourcesManager) { WeakReference<LoadedApk> ref; if (differentUser) { // Caching not supported across users ref = null; } else if (includeCode) { ref = mPackages.get(aInfo.packageName); } else { ref = mResourcePackages.get(aInfo.packageName); } LoadedApk packageInfo = ref ! = null ? ref.get() : null; if (packageInfo == null || (packageInfo.mResources ! = null && ! packageInfo.mResources.getAssets().isUpToDate())) { if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package " : "Loading resource-only package ") + aInfo.packageName + " (in " + (mBoundApplication ! = null ? mBoundApplication.processName : null) + ")"); packageInfo = new LoadedApk(this, aInfo, compatInfo, baseLoader, securityViolation, includeCode && (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) ! = 0, registerPackage); if (mSystemThread && "android".equals(aInfo.packageName)) { packageInfo.installSystemApplicationInfo(aInfo, getSystemContext().mPackageInfo.getClassLoader()); } if (differentUser) { // Caching not supported across users } else if (includeCode) { mPackages.put(aInfo.packageName, new WeakReference<LoadedApk>(packageInfo)); } else { mResourcePackages.put(aInfo.packageName, new WeakReference<LoadedApk>(packageInfo)); } } return packageInfo; }}Copy the code

Then move on to the handleLaunchActivity method

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) { ... WindowManagerGlobal.initialize(); Activity a = performLaunchActivity(r, customIntent); if (a ! = null) { r.createdConfig = new Configuration(mConfiguration); reportSizeConfigurations(r); Bundle oldState = r.state; // resume handleResumeActivity(r.token, false, r.isForward, ! r.activity.mFinished && ! r.startsNotResumed, r.lastProcessedSeq, reason); if (! r.activity.mFinished && r.startsNotResumed) { if (r.isPreHoneycomb()) { r.state = oldState; } } } else { // If there was an error, for any reason, tell the activity manager to stop us. try { ActivityManager.getService() .finishActivity(r.token, Activity.RESULT_CANCELED, null, Activity.DONT_FINISH_TASK_WITH_ACTIVITY); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); }}}Copy the code

The Activity is created by calling the performLaunchActivity method

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); ActivityInfo aInfo = r.activityInfo; if (r.packageInfo == null) { r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE); ComponentName Component = r.i.nten.getComponent (); . / / create a context ContextImpl appContext = createBaseContextForActivity (r); Activity activity = null; try { java.lang.ClassLoader cl = appContext.getClassLoader(); / / create the Activity Activity = mInstrumentation. NewActivity (cl, component getClassName (), r.i ntent); . } catch (Exception e) { ... } the try {/ / create or obtain application application app = r.p ackageInfo. MakeApplication (false, mInstrumentation); . if (activity ! = null) { ... Associated with the activity 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); if (customIntent ! = null) { activity.mIntent = customIntent; }... / / start the Activity the if (r.i sPersistable ()) {mInstrumentation. CallActivityOnCreate (Activity, r.s Tate, r.p ersistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); }... r.paused = true; mActivities.put(r.token, r); } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { ... } return activity; }Copy the code

PerformLaunchActivity does a number of things, including but not limited to:

  • Create context
  • Create the Activity
  • Get the Application (if not, create it)
  • Associate the context of the activity with the app
  • Start the Activity

The next step is to notify the application layer that the Activity has been created

frameworks/base/core/java/android/app/Instrumentation.java

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

Finally, the onCreate method of the Activity is called, which is where we develop the Activity

frameworks/base/core/java/android/app/Activity.java

final void performCreate(Bundle icicle, PersistableBundle persistentState) { mCanEnterPictureInPicture = true; restoreHasCurrentPermissionRequest(icicle); if (persistentState ! = null) { onCreate(icicle, persistentState); } else { onCreate(icicle); } mActivityTransitionState.readState(icicle); mVisibleFromClient = ! mWindow.getWindowStyle().getBoolean( com.android.internal.R.styleable.Window_windowNoDisplay, false); mFragments.dispatchActivityCreated(); mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions()); }Copy the code

Due to the word limit of digging gold, the following content is put in the next article. After the review, the address of the next article will be posted in the comments section