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