preface
There are two kinds of Activity startup processes. One is the root Activity startup process, that is, clicking an application icon on the Launch interface to start the application. The root Activity refers to the first Activity started by the application. The other is the normal Activity startup process, where we normally call the startActivity method to start an Activity. This article discusses the second method, the startActivity method, which you know is used to start an Activity. Have you ever wondered how it starts underneath? How are Activity lifecycle methods called back? How many processes are involved in its startup? Next we through a source to understand the Activity about the startup process, and then answer these questions.
The source code of this article is based on Android8.0. The source file location of this article is as follows: frameworks/base/core/java/android/app/Activity.java Frameworks/base/services/core/Java/com/android/server/am / *. Java (* represents ActivityManagerService ActivityStack ActivityStarter, ActivityStackSupervisor ActivityStack)Copy the code
Activity::startActivity()
There are several ways to overload startActivity, as follows:
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if(options ! =null) {
startActivityForResult(intent, -1, options);
} else {
// We don't normally pass options to startActivity, so if options is empty, it will go to this branch
// The second requestCode parameter is -1, which means you don't need to know the result of the Activity launch
startActivityForResult(intent, -1); }}// Find that the startActivityForResult method with two parameters ends up calling the startActivityForResult method with three parameters
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
Copy the code
You can see that startActivity ends up calling the startActivityForResult method.
1, the Activity: : startActivityForResult ()
Here we come to the startActivityForResult method with three parameters, as follows:
//Activity.java
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
//mParent is always empty
if (mParent == null) {
/ /...
//1. Call the execStartActivity method of Instrumentation
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
/ /...
// The requestCode is -1
if (requestCode >= 0) {
mStartedActivity = true;
}
/ /...
} else {
/ /...
}
Copy the code
In the above code, it goes into the mParent==null branch. MParent is the Activity type, which is only assigned in the LocalActivityManger constructor. It was always empty during our startActivity (see mParent on startActivity in this article for details on why mParent was always empty). Let’s focus on comment 1 here, and call the execStartActivity method of Instrumentation, a class that monitors the application’s interaction with the system, and note the two parameters passed to the execStartActivity method:
- 1, mMainThread. GetApplicationThread () : ApplicationThread types, mMainThread is ActivityThread type, it is the application of the entrance to the class, and mMainThread. GetApplicationThread () is to obtain a ApplicationThread, This is an inner class for ActivityThread that implements iApplicationThread.stub as follows:
//ActivityThread.java::ApplicationThread
private class ApplicationThread extends IApplicationThread.Stub {
/ /...
}
Copy the code
The IApplicationThread. Java class is automatically generated by IApplicationThread. Aidl using the AIDL tool at compile time. The IApplicationThread automatically generates an iApplicationThread. Stub class that inherits from Binder, which implements the IBinder interface. And IApplicationThread.Stub implements the IActivityManager interface. To communicate between processes, ApplicationThreads simply extend the iApplicationThread. Stub class and implement the corresponding methods, so that the main ActivityThread can provide remote services through ApplicationThread. Keep in mind this ApplicationThread, which plays an important role in the Activity launch process.
- 2. MToken: It is of type IBinder and represents the token of the current Activity. It saves the ActivityRecord information of the Activity it is in
2, Instrumentation: : execStartActivity ()
Let’s move on to the execStartActivity method for Instrumentation, as follows:
//Instrumentation.java
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
// Remember the ApplicationThread mentioned above, which is converted to IApplicationThread and used below as an argument to the startActivity method
IApplicationThread whoThread = (IApplicationThread) contextThread;
/ /...
try {
/ /...
// the startActivity method of ActivityManagerService is actually called
intresult = ActivityManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target ! =null ? target.mEmbeddedID : null,
requestCode, 0.null, options);
This method throws an exception when a Activiy cannot be started correctly
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
Copy the code
We see note 1, ActivityManager. GetService () returns the ActivityManagerService (AMS) below the local agent in the application process, the method in the ActivityManager, as follows:
//ActivityManager.java
public static IActivityManager getService(a) {
/ / IActivityManagerSingleton is Singleton type, Singleton wrapper class is a Singleton
// The first time its get method is called, it initializes the AMS Binder object through the create method and returns the previously created object in subsequent calls
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create(a) {
//ServiceManager is the ServiceManager, where the IBinder type AMS reference is obtained via getService
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
// This translates the IBinder type AMS reference into a local proxy for AMS in the application process using the asInterface method
final IActivityManager am = IActivityManager.Stub.asInterface(b);
returnam; }};Copy the code
The iActivityManager.java class shown above is similar in meaning to applicationThread.java mentioned earlier. To communicate between processes, AMS simply inherits the iActivityManager. Stub class and implements the corresponding methods to provide remote services, as follows:
//ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub{
/ /...
}
Copy the code
So continue to return to the Instrumentation execStartActivity method, ActivityManager. GetService () returns the local agency of the AMS note AMS is in system process SystemServer, So note 1 is actually calling AMS’s startActivity method through Binder’s IPC.
The sequence diagram of the whole process is as follows:
From here, the start of the Activity is moved from the application process to AMS.
AMS::startActivity()
The AMS startActivity method is as follows:
//AMS.java
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
The simple return startActivityAsUser method, the method in the last more than a UserHandle. GetCallingUserId () parameters, AMS permissions according to the caller. Let’s look at the other parameters:
- Caller: IApplicationThread. At this point it has been converted to a local proxy for ApplicationThread, which occurs in the Binder IPC described above, just like the AMS local proxy conversion mentioned above.
- CallingPackage: the name of the package in which the calling Activity is located, which has been passed in previously
- Intent: The intent passed from the previous startActivity
- ResolvedType: from the above, intent. ResolveTypeIfNeeded ()
- ResultTo: IBinder type, remember the mToken mentioned above? This is an ActivityRecord of the caller’s Activity that is passed in from above
- ResultWho: String type, the mEmbeddedID of the calling Activity, which has been passed from the previous
- RequestCode: always passed from above, always -1
- StartFlags: 0 is passed from above
- ProfilerInfo: The profilerInfo type, passed from above, equals null
- BOptions: Bundle type, passed from above, equal to null
Let’s move on to AMS’s startActivityAsUser method.
1, the AMS: : startActivityAsUser ()
The startActivityAsUser method is as follows:
//AMS.java
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) {
/ /...
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null.null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null.null, bOptions, false, userId, null.null."startActivityAsUser");
}
Copy the code
Two judgments are omitted: 1, whether the caller process is isolated, and 2, whether the caller has permissions, which are not important. Simply continue to return the below mActivityStarter. StartActivityMayWait method, mActivityStarter ActivityStarter type, it is loaded in AMS Activity control class, All the logic is gathered to determine how to convert intEnts and Flags into activities and associate activities with tasks and stacks. There are a few more parameters passed to the startActivityMayWait method.
- CallingUid: The second argument, equal to -1
- InTask: The penultimate parameter, of type TaskRecord, represents the stack on which the Activity is to be started, null, indicating that it has not been created
- Reason: The last last parameter is “startActivityAsUser”, which indicates the reason for starting
- Some of the other arguments are passed in null and some are passed in from above
Take a look at the startActivityMayWait method in ActivityStarter.
2, ActivityStarter: : startActivityMayWait ()
Take a look at the source code for this method as follows:
//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, IActivityContainer iContainer, TaskRecord inTask, String reason) {
/ /...
// Construct a new intent object from the incoming intent, so that the intent is not affected even if it is modified
intent = new Intent(intent);
/ /...
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
if(rInfo == null) {/ /...
}
// Parse the intent to collect information about the Activity to which the intent points
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
/ /...
final ActivityRecord[] outRecord = new ActivityRecord[1];
//1. Focus here, call its own startActivityLocked method
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, outRecord, container, inTask, reason);
/ /...
return res;
}
Copy the code
ActivityInfo collects information about the Activity to start (see this article for ResolveInfo and ActivityInfo to get Android app and system information), but focus on note 1. Again, the startActivityLocked method in ActivityStarter is called. A few more parameters are passed to startActivityLocked (callingPid, etc.). For the introduction of PID and UID, you can see the functions and differences of UID and PID in Android phones in this article.
Now look at the startActivityLocked method.
2.1, ActivityStarter: : startActivityLocked ()
The source code for this method is as follows:
//ActivityStarter.java
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, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask, String reason) {
// Void the "startActivityAsUser" argument
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
mLastStartReason = reason;
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord[0] = null;
// the startActivity method is called
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
container, inTask);
if(outActivity ! =null) {
outActivity[0] = mLastStartActivityRecord[0];
}
return mLastStartActivityResult;
}
Copy the code
Note 1, which focuses on note 1, calls the startActivity method in ActivityStarter, which takes one extra parameter, mLastStartActivityRecord, MLastStartActivityRecord is an array type of ActivityRecord. ActivityRecord is a class that holds all information about an Activity.
Now look at the startActivity method in ActivityStarter.
2.2, ActivityStarter: : startActivity ()
//ActivityStarter.java
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, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
/ /...
// Get the caller's process record. Caller is the ApplicationThread object that represents the caller's process
ProcessRecord callerApp = null;
if(caller ! =null) {
// Here we call AMS's getRecordForAppLocked method to get the callerApp representing the caller's process
callerApp = mService.getRecordForAppLocked(caller);
if(callerApp ! =null) {
// Get the pid and uid of the caller process and assign values
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else{ err = ActivityManager.START_PERMISSION_DENIED; }}// One of the parameters to the startActivity method below, which represents information about the caller's Activity
ActivityRecord sourceRecord = null;
if(resultTo ! =null) {
sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
/ /...
}
/ /...
// Create an information description class ActivityRecord for the Activity to be started
ActivityRecord r = newActivityRecord(mService, callerApp, callingPid, callingUid, callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession ! =null,
mSupervisor, container, options, sourceRecord);
//outActivity is of type ActivityRecord[], passed in from above. ActivityRecord is assigned to it here, and is passed as a parameter to the startActivity method below
if(outActivity ! =null) {
outActivity[0] = r;
}
/ /...
//1. Call its own startActivity method
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}
Copy the code
The startActivity code above is very long and leaves out a lot. The caller process described above is, in this case, equivalent to the application process. ProcessRecord is used to describe information about an application process. Note 1 calls ActivityStarter’s startActivity method, which has far fewer parameters, to record all information about an Activity to start. Most of the information about the Activity to be started is encapsulated in the ActivityRecord class, passed in as a parameter r.
Now look at the startActivity method of ActivityStarter.
2.3, ActivityStarter: : startActivity ()
The code for this method is as follows:
//ActivityStarter.java
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();
//1. Call the startActivityUnchecked method
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
} finally {
/ /...
mService.mWindowManager.continueSurfaceLayout();
}
/ /...
return result;
}
Copy the code
The startActivityUnchecked method of ActivityStarter is called.
2.4, ActivityStarter: : startActivityUnchecked ()
The code for this method is as follows:
//ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) {
// All the above parameters are passed in except for outActivity, which is assigned to the member variables of ActivityStarter, such as mDoResume = doResume, mStartActivity = r
//mStartActivity is the information about the Activity to be started
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
// Calculate the mode to start the Activity and assign it to mLaunchFlags
computeLaunchingTaskFlags();
/ /...
// Set the boot mode
mIntent.setFlags(mLaunchFlags);
/ /...
boolean newTask = false;
// Create a new Activity stack
int result = START_SUCCESS;
if (mStartActivity.resultTo == null && mInTask == null&&! mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) ! =0) {
/ / 1.1 here will take the setTaskFromReuseOrCreateNewTask within a method to create a new Activity task stack
newTask = true;
result = setTaskFromReuseOrCreateNewTask(
taskToAffiliate, preferredLaunchStackId, topStack);
} else if(mSourceRecord ! =null) {
The mTargetStack is assigned to the caller's Activity's task stack within the setTaskFromSourceRecord method
result = setTaskFromSourceRecord();
} else if(mInTask ! =null) {
MInTask is assigned to mTargetStack directly within setTaskFromInTask (mInTask = null)
result = setTaskFromInTask();
} else {
//1.4. The preceding conditions are not met, but this rarely happens
setTaskToCurrentTopOrCreateNewTask();
}
if(result ! = START_SUCCESS) {return result;
}
/ /...
//mDoResume equals the doResume passed in above, which is true
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if(! mTargetStack.isFocusable() || (topTaskActivity ! =null&& topTaskActivity.mTaskOverlay && mStartActivity ! = topTaskActivity)) {// The Activity doesn't show up here because the Activity hasn't gotten focus or the Activity's stack overflows
/ /...
} else {
// This is where you would normally go
if(mTargetStack.isFocusable() && ! mSupervisor.isFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityUnchecked");
}
/ / 2 call mSupervisor resumeFocusedStackTopActivityLocked method, the main concern heremSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); }}else {
/ /...
}
return START_SUCCESS;
}
Copy the code
The startActivityUnchecked method above is also quite long. This method handles the logic related to Activity stack management, If you’re not familiar with this information, check out these two articles: Full Parsing of Android Tasks and return stacks, ActivityTask, and Activity stack management. One or more ActivityRecords form a TaskRecord, which records the Activity stack, and ActivityStack contains one or more TaskRecords. The mTargetStack in the above code is of type ActivityStack. Let’s look at comment 1. Comment 1 will determine whether a new Activity stack needs to be created based on conditions such as mLaunchFlags. The conditions discussed in this article are limited to when an application calls the startActivity of an Activity to start another Activity. By default, the Activity starts in standard mode and does not create a new task stack, so it goes to the condition branch of 1.2. Then we could see note 2, here will call mSupervisor. ResumeFocusedStackTopActivityLocked method, mSupervisor ActivityStackSupervisor type, ActivityStackSupervisor is used to manage ActivityStack. The process of starting an Activity moves from ActivityStack to ActivityStackSupervisor.
Let’s take a look at below ActivityStackSupervisor resumeFocusedStackTopActivityLocked method.
3, ActivityStackSupervisor: : resumeFocusedStackTopActivityLocked ()
The source code for this method is as follows:
//ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
/ /...
// Get the ActivityRecord at the top of the stack where the Activity to start is located
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
//1, r is null or is in a RESUMED state
if (r == null|| r.state ! = RESUMED) {/ / 2, attention here, called ActivityStack resumeTopActivityUncheckedLocked method
mFocusedStack.resumeTopActivityUncheckedLocked(null.null);
} else if (r.state == RESUMED) {
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
Copy the code
First, it gets the ActivityRecord at the top of the stack where the Activity to be started is and assigns it to R. Because the Activity to be started hasn’t been started yet, the top of the stack is the caller. The caller starts the Activity. Note 1 must be changed from RESUME to another state such as STPO. = RESUMED conditions, at this time is to go with 2, 2 call mFocusedStack resumeTopActivityUncheckedLocked method, mFocusedStack is ActivityStack type. The process of starting an Activity goes from ActivityStackSupervisor back to ActivityStack.
Let’s take a look at below ActivityStack resumeTopActivityUncheckedLocked method.
3.1, ActivityStack: : resumeTopActivityUncheckedLocked ()
The source code for this method is as follows:
//ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
/ /...
boolean result = false;
try {
/ / 1, here, here called the resumeTopActivityInnerLocked method itself
result = resumeTopActivityInnerLocked(prev, options);
} finally {
/ /...
}
/ /...
return result;
}
Copy the code
Let’s look at note 1, simple call resumeTopActivityInnerLocked methods.
3.1.1, ActivityStack: : resumeTopActivityInnerLocked ()
The source code for this method is as follows:
//ActivityStack.java
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
/ /...
// Get information about the Activity to start
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */)
/ /...
if(next.app ! =null&& next.app.thread ! =null) {
/ /...
}else{
/ /...
/ / 1, attention here, call the ActivityStackSupervisor startSpecificActivityLocked method
mStackSupervisor.startSpecificActivityLocked(next, true.true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
Copy the code
The topRunningActivityLocked method gets information about the Activity to be started next. Because the Activity to be started is not yet part of any process, its ProcessRecord is null and goes to the else branch. So note 1 call the ActivityStackSupervisor startSpecificActivityLocked method, ActivityStackSupervisor again.
The following ActivityStackSupervisor startSpecificActivityLocked method.
3.2, ActivityStackSupervisor: : startSpecificActivityLocked ()
The source code for this method is as follows:
//ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Get the application process in which the Activity is to be started
ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
// The application process in which the Activity is to be started exists
if(app ! =null&& app.thread ! =null) {
try {
/ /...
Call realStartActivityLocked (realStartActivityLocked)
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
/ /...}}/ /...
}
Copy the code
When the Activity is already running, it calls realStartActivityLocked in comment 1. Note that there is an extra argument to pass in the app representing the Activity.
Now look at the realStartActivityLocked methods for ActivityStackSupervisor.
3.3, ActivityStackSupervisor: : realStartActivityLocked ()
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException {
/ /...
//1. Assign the application process information to the ActivityRecord of the Activity to be started
r.app = app;
/ /...
try{
/ /...
ProcessRecord is the ProcessRecord type, app. Thread is the IApplicationThread type
// App. thread is the local proxy for AMS's ApplicationThread, as described earlier
// The scheduleLaunchActivity method of ApplicationThread is actually called
app.thread.scheduleLaunchActivity(newIntent(r.intent), r.appToken, System.identityHashCode(r), r.info, mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, ! andResume, mService.isNextTransitionForward(), profilerInfo);/ /...
}catch (RemoteException e) {
/ /...
}
/ /...
return true;
}
Copy the code
As the name indicates, realStartActivity, going around, this is where the Activity is actually started. Note 1 app refers to the application process that passed in the Activity to be started from the front, We assign it to the app field of the Activity’s ActivityRecord, so that the Activity belongs to the application process. Note 2: App. thread is the ApplicationThread we’ve been talking about. So Binder’s IPC calls the scheduleLaunchActivity method in ApplicationThread.
The sequence diagram of the whole process is as follows:
The current code logic is executed in the process where AMS is located, and from there the Activity startup process is eventually returned to the ApplicationThread where the application process is located.
conclusion
This article was originally written about the startup of the Activity, but it was too long to write here, so the startup process of the Activity in the application process will be moved to the next article. This article briefly introduces the process of requesting AMS to start an Activity and the process of launching an Activity in AMS. Now let’s answer some questions given at the beginning:
- 1. What is the startup process of an Activity?
This article answers half of the question, starting with the application calling a startActivity method, where the application process asks AMS to start the Activity, where the Activity completes its preparations, and then returns to the application process to start the Activity lifecycle. This article explains how an application process starts asking AMS to start an Activity, and then completes a series of preparations in AMS. This process is represented by a sequence diagram as follows:
- 2. How are Activity lifecycle methods called back?
This article does not answer that question, which will be answered in the next article.
- 3. How many processes are involved in its startup?
The startActivity method is used to start an Activity. Therefore, the process involved in this process can be shown in the following figure:
In the figure, AppProcess represents the application process and systemServer represents the AMS process. The two processes communicate with each other through Binder. For example, ApplicationThread and AMS implement their own Stub classes, so the application process startActivity requests AMS to start the Activity. When AMS is ready, Send the scheduleLaunchActivity request to tell the application that it is ready to start the Activity.
How many processes will be involved in the first Activity launching process mentioned in the introduction, that is, clicking an application icon on the Launch interface to start an application? The answer is four, as shown here:
As you can see, it involves the Launcher process, the SystemServer process, the App process, and the Zygote process. (For simple information about these processes, see the Android architecture from a process perspective here.) The first step is to click the App icon, which is running in the process Launcher. The Launcher sends a startActivity request to AMS through the AMS local agent. After RECEIVING the request, AMS finds that the process to start the Activity does not exist. The Zygote Process receives the request and forks a new child, the App Process, into activityThread. main, which runs in the App Process. The App process initiates the attachApplication request to AMS through the AMS local agent. After AMS receives the request, it performs some preparations (notifying the Activity to create the Application). The ApplicationThread sends a scheduleLaunchActivity request to the App process. Upon receiving the request, the App process performs a lifecycle callback for the Activity.
The process after the scheduleLaunchActivity method in ApplicationThread will be left for the next article.
Reading source code is really a long process, and when others write so simple, but when they go to write, only to find things to consider a lot, so this is a cumulative process, so read the source code, it is best to follow the previous article to read, so understand faster.
Reference article:
Exploring the Art of Android Development
StartActivity Startup process analysis