Startup process of root Activity
There are two types of Activity startup: one is the startup process of root Activity, and the other is the startup process of ordinary Activity. Root Activity refers to the first Activity started by the application, so the startup process of root Activity can also be understood as the startup process of the application in general. Normal activities refer to activities other than the first Activity launched by the application. The starting process of the root Activity is divided into three parts: the Launcher requesting AMS process, the calling process from AMS to ApplicationThread, and the ActivityThread starting Activity
Launcher requests AMS process
After the Launcher is started, the shortcut icons of installed applications will be displayed on the desktop. The shortcut icons of these applications are the entry to start the root Activity. The whole sequence flow is as follows:
Launcher.startActivitySafely() -> Activity.startActivity() -> Activity.startActivityForResult() -> Instrumentation.execStartActivity() -> ActivityManager.startActivity() -> IActivityManager.startActivity() -> AMS
-
Launcher.startActivitySafely()
( /packages/apps/Launcher3/src/com/android/launcher3/Launcher.java)
-
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK): set FLAG to intent.FLAG_ Activity_ NEW_ Task, so that the root Activity will be started in the new task stack
-
startActivity(intent, opsBundle): call the startActivity method, which is implemented in the Activity
-
-
Activity.startActivity()
In the statrActivity() method, the startActivityForResult() method will be called, and its second parameter is - 1, which means that the Launcher does not need to know the result of Activity startup
-
Activity.startActivityForResult()
-
if(mParent == null){}: mParent is of type Activity and represents the parent class of the current Activity. Since the root Activity has not been created yet, mParent == null holds. Then call the execStartActivity method of Instrumentation, which is mainly used to monitor the interaction between the application and the system
-
-
Instrumentation.execStartActivity()
-
int result = ActivityManager.getService() / / get the proxy object of AMS
.startActivity(....); // Call the startactivity method (the final call is the startactivity method of AMS)
-
-
ActivityManager.getService()
//The getServices method calls the get method of IActivityManagerSingleton public static IActivityManager getService(){ return IActivityManagerSingleton.get(); } private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>(){ @Override protected IActivityManager create(){ //Get the Service reference named "activity", that is, the reference of AMS of IBinder type final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); //Convert it to an object of type IActivityManager (this code uses AIDL) final IActivityManager am = IActivityManager.Stub.asInterface(b); return am; } }
The IActivityManager.java class is automatically generated by the AIDL tool at compile time (frameworks/base/cpre/java/android/app/IActivityManager.aidl). To realize inter process communication, AMS, that is, the server side, only needs to inherit the IActivityManager.Stub class and implement the corresponding methods
Calling procedure from AMS to ApplicationThread
ActivityManagerService.java
After the Launcher requests AMS, the code logic has entered AMS
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.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(..., UserHandler.getCallingUserId()); } //The startActivityAsUser() method has one more parameter UserHandler.getCallingUserId() than the startActivity method. This method will obtain the UserId of the caller, and AMS will determine the permissions of the caller according to this UserId public final int startActivityAsUser(..., int userId){ //Judge whether the caller is isolated. If it is isolated, a SecurityException exception will be thrown enforceNotIsolatedCaller("startActivity"); //Check the caller's permission. If there is no permission, a SecurityException exception will be thrown userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null); return mActivityStarter.startActivityMayWait(...,null, "startActivityAsUser"); }
ActivityStarter
Activity starter is a newly added class in Android 7.0. It is a control class for loading activities. It will collect all logic to decide how to convert Intent and Flags into activities, and associate activities with tasks and stacks
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java //inTask: it is a TaskRecord type and represents the stack of the started Activity //Reason: it is a String type and represents the reason for starting final int stratActivityMayWait(..., TaskRecord inTask, String reason){ ... int res = startActivityLocked(...); ... return res; } int startActivityLocked(..., String reason){ //The reason for judging startup is not empty if(TextUtils.isEmpty(reason)){ throw new IllegalArgumentException("Need to specify a reason."); } ... mLastStartActivityResult = startActivity(...); } private int startActivity(IApplicationThread caller, ...){ //The caller points to the ApplicationThread object of the application where the Launcher is located if(caller != null){ //Get the Launcher process: call the getRecordForAppLocked method of AMS to get a callerApp object representing the Launcher process callerApp = mService.getRecordForAppLocked(caller); } //Create a description class ActivityRecord for the Activity to be started //ActivityRecord is used to describe an Activity and record all the information of an Activity ActivityRecord r = new ActivtiyRecord(...); if(outAcitivity != null){ //Assign the created ActivityRecord to the outActivity of ActivityRecord [] type, and this outActivity will be passed as a parameter outActivity[0] = r; } ... return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask, outActivity); } private int startActivity(...){ try{ mService.mWindowManager.deferSurfaceLayout(); result = startActivityUnchecked(...); } ... return result; } //It mainly deals with the logic related to stack management private int startActivityUnchecked(...){ ... //The mLauncher we set earlier is FLAG_ACTIVITY_NEW_TASK if(mStartActivity.resultTo == null && mInTask == null && !mAddingToTask && (mLauncherFlags & FLAG_ACTIVITY_NEW_TASK) != 0){ nweTask = true; //Create a new TaskRecord to describe an Activity task stack, that is, a new Activity task stack will be created inside the settaskfromreusorcreatewtask method result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, preferredLaunchStackId, topStack); } ... //Call the resumeFocusedStackTopActivityLocked method of ActivityStackSupervisor mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); }
ActivityStackSupervisor.java
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions){ ... //Get the top of the stack where the Activity to be started is not the ActivityRecord in the stopped state final ActivityRecord r = mFocusedStack.topRunningActivityLocked(); //The ActivityRecord is not null, or the state of the Activity to be started is not the RESUMED state if(r == null || r.state != RESUMED){ //Method calling ActivityStack mFocusedStack.resumeTopActivityUncheckedLocked(null, null); } } ActivityStack.java boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options){ ... result = resumeTopActivityInnerLocked(prev, options); ... return result; } //This method has a lot of code. We only need to pay attention to calling the startSpecificActivityLocked method of ActivityStackSupervisor private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options){ ... mStackSupervisor.startSpecificActivityLocked(next, true, true); } ActivityStackSupervisor.java void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig){ //Gets the application process of the Activity to be started ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); //Determine whether the application process where the Activity to be started is already running if(app != null && app.thread != null){ ... //The second parameter represents the ProcessRecord of the application process where the Activity to be started is located realStartActivityLocked(r, app, andResume, checkConfig); } } 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, new Configuration(mService.mConfiguration), new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo); }
app.thread refers to iaapplicationthread. Its implementation is the internal class ApplicationThread of ActivityThread, where ApplicationThread inherits iaapplicationthread.stub. app refers to the application process of the incoming Activity to be started. Therefore, the code in realStartActivityLocked is to start the Activity in the target application process. The current code logic runs in the process where AMS is located (SystemServer process), and binders communicate with the application process through ApplicationThread. In other words, ApplicationThread is the communication bridge between the process where AMS is located (SystemServer process) and the application process
ActivityThread starts the process of activity
Start process
ActivityThread.java
scheduleLaunchActivity() -> sendMessage()
H.java
handleMessage() -> handleLaunchActivity()
ActivityThread.java
performLaunchActivity -> callActivityOnCreate()
Instrumentation.java
performCreate()
Activity.java
onCreate()
In the whole process, we mainly focus on the method performLauncherActivity(). For the specific implementation, you can read the source code