catalogue
3.2 IActivityTaskManagerSingleton
4,ActivityTaskManagerService.java
4.3 startActivityAsUser() has more parameters than the above
4.4 getActivityStartController()
5,ActivityStartController.java
7.1 resumeFocusedTasksTopActivities()
8.1 resumeTopActivityUncheckedLocked()
8.2 resumeTopActivityInnerLocked()
9,ActivityTaskSupervisor.class
9.2.1 realStartActivityLocked()
9.2.2 ClientLifecycleManager.scheduleTransaction()
9.2.3 ClientTransaction.schedule()
9.2.4 ApplicationThread.scheduleTransaction()
9.2.5 ClientTransactionHandler.scheduleTransaction()
9.2.6 ActivityThread.H.handleMessage()
9.2.7 TransactionExecutor.execute()
9.2.8 TransactionExecutor.executeCallbacks()
9.2.9 TransactionExecutor.cycleToPath()
9.2.10 TransactionExecutor.performLifecycleSequence()
9.2.11 ClientTransactionHandler.handleLaunchActivity()
9.2.12 ActivityThread.handleLaunchActivity()
9.2.13 ActivityThread.performLaunchActivity()
9.2.14 Instrumentation.newActivity()
9.2.15 Instrumentation.callActivityOnCreate()
9.3.1 ATMS.startProcessAsync()
9.3.2 ActivityManagerInternal.startProcess()
9.3.3 ActivityManagerService.LocalService.startProcess()
9.3.4 ActivityManagerService.startProcessLocked()
9.3.5 ProcessList.startProcessLocked()
9.3.6 ProcessList.startProcess()
9.3.9 ZygoteProcess.startViaZygote()
9.3.10 ZygoteProcess.openZygoteSocketIfNeeded(abi)
9.4.11 ZygoteProcess.zygoteSendArgsAndGetResult()
9.4.12 ZygoteProcess.attemptZygoteSendArgsAndGetResult()
9.4.14 ZygoteService.runSelectLoop()
9.4.15 ZygoteConnection.processOneCommand()
Start a picture
Source code version: Android 11(SDK 30)
Classes involved
-
Instrumentation: responsible for the establishment and life cycle control of applications and activities.
-
ActivityTaskManager: this class provides information about and interacts with an Activity and its containers, such as tasks, stacks, and displays.
-
Activity taskmanagerservice: a system service used to manage activities and their containers (tasks, displays, etc.). Before this job was AMS, it is now separated from AMS.
-
ActivityStartController: controller used to delegate Activity startup.
-
ActivityStarter: specifically responsible for the startup operation of an Activity. Its main functions include parsing Intent, creating ActivityRecord, and creating TaskRecordflex if possible
-
Activity stack: the stack management of activities in ATMS, which is used to record the sequence relationship and status information of started activities. Determine whether a new process needs to be started through the ActivityStack.
-
RootWindowContainer: the Root WindowContainer of the device.
-
TaskRecord: a concept of "Task" abstracted from ATMS, which is a stack for recording activityrecords. A "Task" contains several activityrecords. ATMS uses TaskRecord to ensure the sequence of Activity startup and exit.
-
Activity stack Supervisor: responsible for the management of all activity stacks. Three activity stacks, mHomeStack, mFocusedStack and mLastFocusedStack, are managed internally. Among them, mHomeStack manages the activity stack related to the Launcher; mFocusedStack manages the activity stack currently displayed in the foreground; mLastFocusedStack manages the activity stack last displayed in the foreground activity.
-
Activity Supervisor: manages the activity task stack.
-
ActivityThread: the ActivityThread runs in the UI thread (main thread), the real entrance of the App.
-
Application thread: used to realize the interaction between ATMS and ActivityThread.
-
ApplicationThreadProxy: the proxy of ApplicationThread on the server. ATMS communicates with ActivityThread through this agent.
-
Client lifecycle manager: the ability to combine multiple client lifecycle transaction requests and / or callbacks and execute them as a single transaction.
-
TransactionExecutor: classes that manage transaction execution in the correct order.
1,Activity.java
1.1 startActivity()
@Override public void startActivity(Intent intent) { //Then look inside this.startActivity(intent, null); } @Override public void startActivity(Intent intent, @Nullable Bundle options) { ... if (options != null) { startActivityForResult(intent, -1, options); } else { startActivityForResult(intent, -1); } }
Finally, the startActivityForResult method is called, and the - 1 passed in indicates that the result of startActivity does not need to be obtained.
1.2 startActivityForResult()
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { //mParent represents the parent class of the current activity, if (mParent == null) { options = transferSpringboardActivityOptions(options); //ActivityThread mMainThread; Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); ... } else { ... } }
startActivityForResult calls the Instrumentation.execStartActivity method. The rest is left to the Instrumentation class.
mMainThread is of ActivityThread type. ActivityThread can be understood as a process, which is the process where the Activity is located.
Obtain a reference of ApplicationThread through mMainThread, which is used to realize inter process communication. Specifically, the system process where AMS is located notifies the application process of a series of operations.
There are descriptions of Instrumentation, ActivityThread, ApplicationThread and other classes above.
2,Instrumentation.java
frameworks/base/core/java/android/app/Instrumentation.java
/** * Base class for implementing application instrumentation code. */ public class Instrumentation { ... }
2.1 execStartActivity()
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { ... try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(who); int result = ActivityTaskManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); //Check the results of starting the Activity checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; }
In Instrumentation, ActivityTaskManager.getService().startActivity() is called. Let's take a closer look.
3,ActivityTaskManage.java
frameworks/base/core/java/android/app/ActivityTaskManager.java
@TestApi @SystemService(Context.ACTIVITY_TASK_SERVICE) public class ActivityTaskManager { ... }
3.1 getService()
/** @hide */ public static IActivityTaskManager getService() { return IActivityTaskManagerSingleton.get(); }
3.2 IActivityTaskManagerSingleton
@UnsupportedAppUsage(trackingBug = 129726065) private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton = new Singleton<IActivityTaskManager>() { @Override protected IActivityTaskManager create() { //Proxy object (dynamic proxy) final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE); return IActivityTaskManager.Stub.asInterface(b); } };
This actually returns a ActivityTaskManagerService, which presents a cross process (from the app process > system_service process) and then calls its startActivity method.
In fact, this is to call the startActivity method of ATMS through AIDL and return the result of iaactivitytaskmanager.startActivity: the Activity has been started normally and successfully.
So far, the focus of startActivity has successfully shifted from application process (app) to ATMS of system_service.
4,ActivityTaskManagerService.java
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
public class ActivityTaskManagerService extends IActivityTaskManager.Stub { ... }
4.1 startActivity()
@Override public final int startActivity(IApplicationThread caller, String callingPackage, String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) { return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, UserHandle.getCallingUserId()); }
4.2 startActivityAsUser()
@Override public int startActivityAsUser(IApplicationThread caller, String callingPackage, String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) { return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId, true /*validateIncomingUser*/); }
4.3 startActivityAsUser() has more parameters than the above
//Here's the point private int startActivityAsUser(IApplicationThread caller, String callingPackage, @Nullable String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) { assertPackageMatchesCallingUid(callingPackage); enforceNotIsolatedCaller("startActivityAsUser"); userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser, Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser"); // Switch to the user app stack here. return getActivityStartController().obtainStarter(intent, "startActivityAsUser") .setCaller(caller) .setCallingPackage(callingPackage) .setCallingFeatureId(callingFeatureId) .setResolvedType(resolvedType) .setResultTo(resultTo) .setResultWho(resultWho) .setRequestCode(requestCode) .setStartFlags(startFlags) .setProfilerInfo(profilerInfo) .setActivityOptions(bOptions) .setUserId(userId) .execute(); }
4.4 getActivityStartController()
ActivityStartController getActivityStartController() { return mActivityStartController; }
5,ActivityStartController.java
/** * Controller for delegating activity launches. */ public class ActivityStartController { ... }
5.1 obtainStarter();
/** * @return A starter to configure and execute starting an activity. It is valid until after * {@link ActivityStarter#execute} is invoked. At that point, the starter should be * considered invalid and no longer modified or used. */ ActivityStarter obtainStarter(Intent intent, String reason) { return mFactory.obtain().setIntent(intent).setReason(reason); }
6,ActivityStarter.java
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
/** * Controller for interpreting how and then launching an activity. * * This class collects all the logic for determining how an intent and flags should be turned into * an activity and associated task and stack. */ class ActivityStarter { ... }
6.1 execute()
/** * Parse the necessary information according to the request parameters provided earlier and execute the request to start the activity. * @return The starter result. */ int execute() { ... res = executeRequest(mRequest); ... }
6.2 executeRequest()
/** * Activity What preparations need to be made before starting? * The normal Activity startup process will be through startActivityUnchecked reach startActivityInner. */ private int executeRequest(Request request) { ... //Record of Activity ActivityRecord sourceRecord = null; ActivityRecord resultRecord = null; ... //Activity Stack management mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession, request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask, restrictedBgActivity, intentGrants); ... return mLastStartActivityResult; }
As you can see from the above code, after several methods of invocation, the object of ActivityStarter type is finally obtained through obtainStarter method, and then its execute() method is called.
In the execute() method, its internal executeRequest() method is called again.
Let's move on to startActivityUnchecked();
6.3 startActivityUnchecked()
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants) { .... try { ... result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants); } finally { ... } postStartActivityProcessing(r, result, startedActivityRootTask); return result; }
6.4 startActivityInner()
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants) { setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor, restrictedBgActivity); //Calculation start mode computeLaunchingTaskFlags(); computeSourceRootTask(); //Set startup mode mIntent.setFlags(mLaunchFlags); ... // Here comes the key point mRootWindowContainer.resumeFocusedTasksTopActivities( mTargetRootTask, mStartActivity, mOptions, mTransientLaunch); ... return START_SUCCESS; }
This is mRootWindowContainer. This is RootWindowContainer.
7,RootWindowContainer.java
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
/** Root {@link WindowContainer} for the device. */ class RootWindowContainer extends WindowContainer<DisplayContent> implements DisplayManager.DisplayListener { ... }
7.1 resumeFocusedTasksTopActivities()
boolean resumeFocusedTasksTopActivities( Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions, boolean deferPause) { ... boolean result = false; if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea() || getTopDisplayFocusedRootTask() == targetRootTask)) { result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions, deferPause); } ... return result; }
Of course, the targetRootTask seen here is an instance of the Task object. Let's track this method.
8,Task.java
frameworks/base/services/core/java/com/android/server/wm/Task.java
class Task extends WindowContainer<WindowContainer> { ... }
8.1 resumeTopActivityUncheckedLocked()
@GuardedBy("mService") boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options, boolean deferPause) { ... someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause); ... return someActivityResumed; }
8.2 resumeTopActivityInnerLocked()
@GuardedBy("mService") private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options, boolean deferPause) { ... try { .... } catch (Exception e) { .... //a key mTaskSupervisor.startSpecificActivity(next, true, false); return true; } .... return true; }
mTaskSupervisor: is an instance of the ActivityTaskSupervisor object. Let's take a look at its startSpecificActivity() method.
9,ActivityTaskSupervisor.class
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
public class ActivityTaskSupervisor implements RecentTasks.Callbacks { ... }
9.1 startSpecificActivity()
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) { // this Activity of Application (process) Is it already running? final WindowProcessController wpc = mService.getProcessController(r.processName, r.info.applicationInfo.uid); boolean knownToBeDead = false; if (wpc != null && wpc.hasThread()) { try { //Process started //Note 1: start the activity realStartActivityLocked(r, wpc, andResume, checkConfig); return; } catch (RemoteException e) { } } r.notifyUnknownVisibilityLaunchedForKeyguardTransition(); final boolean isTop = andResume && r.isTopRunningActivity(); //Note 2: the process was not started mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity"); }
Note 1: process started.
Note 2: the process was not started.
9.2 process started
9.2.1 realStartActivityLocked()
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc, boolean andResume, boolean checkConfig) throws RemoteException { ... //establish Activity Activated transaction final ClientTransaction clientTransaction = ClientTransaction.obtain( proc.getThread(), r.appToken); final boolean isTransitionForward = r.isTransitionForward(); clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), System.identityHashCode(r), r.info, mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(), results, newIntents, r.takeOptions(), isTransitionForward, proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController, r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken, r.getLaunchedFromBubble())); // Set desired final state. final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(isTransitionForward); } else { lifecycleItem = PauseActivityItem.obtain(); } clientTransaction.setLifecycleStateRequest(lifecycleItem); // Schedule transaction. mService.getLifecycleManager().scheduleTransaction(clientTransaction); ... return true; }
This mService is an instance of ActivityTaskManagerService(ATMS). mService. Getlifecycle manager() returns a clientllifecycle manager object. If you want to see what scheduleTransaction() is, you can only find it.
9.2.2 ClientLifecycleManager.scheduleTransaction()
frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java
//Here we introduce a startup Activity of transaction void scheduleTransaction(ClientTransaction transaction) throws RemoteException { final IApplicationThread client = transaction.getClient(); //Note 1 transaction.schedule(); if (!(client instanceof Binder)) { // If client If it is not an instance of Binder, it is a remote call, and the object can be safely recycled. // After a transaction is executed on the client in the ActivityThread, all objects used for local calls are reclaimed. transaction.recycle(); } }
From the method, we can see that transaction is a ClientTransaction. Let's go straight to him.
9.2.3 ClientTransaction.schedule()
/** Target client. */ private IApplicationThread mClient; public void schedule() throws RemoteException { mClient.scheduleTransaction(this); }
When we see the iaapplicationthread, let's go straight to the ApplicationThread.
9.2.4 ApplicationThread.scheduleTransaction()
frameworks/base/core/java/android/app/ActivityThread.java
ApplicationThread belongs to the inner class of ActivityThread.
public final class ActivityThread extends ClientTransactionHandler implements ActivityThreadInternal { ... private class ApplicationThread extends IApplicationThread.Stub { ... @Override public void scheduleTransaction(ClientTransaction transaction) throws RemoteException { ActivityThread.this.scheduleTransaction(transaction); } ... } ... }
There is no scheduleTransaction method in the ActivityThread class. In this case, you can directly find its parent class ClientTransactionHandler.
9.2.5 ClientTransactionHandler.scheduleTransaction()
frameworks/base/core/java/android/app/ClientTransactionHandler.java
public abstract class ClientTransactionHandler { /** Prepare and schedule transaction for execution. */ void scheduleTransaction(ClientTransaction transaction) { transaction.preExecute(this); sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); } }
From here, we can see that he sent an ActivityThread. H. execute by calling the sendMessage() method_ For the transaction message, let's go back to its subclass ActivityThread.
9.2.6 ActivityThread.H.handleMessage()
H here is the inner class of ActivityThread.
// An executor that performs multi-step transactions. private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this); class H extends Handler { public void handleMessage(Message msg) { switch (msg.what) { ... case EXECUTE_TRANSACTION: final ClientTransaction transaction = (ClientTransaction) msg.obj; mTransactionExecutor.execute(transaction); if (isSystem()) { transaction.recycle(); } break; ... } } }
mTransactionExecutor here is the executor of transactions.
9.2.7 TransactionExecutor.execute()
frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) { ... executeCallbacks(transaction); ... }
9.2.8 TransactionExecutor.executeCallbacks()
/** Cycle through all states requested by callbacks and execute them at proper times. */ @VisibleForTesting public void executeCallbacks(ClientTransaction transaction) { final List<ClientTransactionItem> callbacks = transaction.getCallbacks(); ... final IBinder token = transaction.getActivityToken(); ActivityClientRecord r = mTransactionHandler.getActivityClient(token); ... final int size = callbacks.size(); for (int i = 0; i < size; ++i) { ... if (postExecutionState != UNDEFINED && r != null) { // a key final boolean shouldExcludeLastTransition = i == lastCallbackRequestingState && finalState == postExecutionState; cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction); } } }
The focus of this method is cycleToPath(), let's continue.
9.2.9 TransactionExecutor.cycleToPath()
private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState, ClientTransaction transaction) { final int start = r.getLifecycleState(); //IntArray: implements a growing array of int primitives. //Get the path to execute the life cycle this time final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState); performLifecycleSequence(r, path, transaction); }
9.2.10 TransactionExecutor.performLifecycleSequence()
/** Transition the client through previously initialized state sequence. */ private void performLifecycleSequence(ActivityClientRecord r, IntArray path, ClientTransaction transaction) { final int size = path.size(); for (int i = 0, state; i < size; i++) { state = path.get(i); switch (state) { case ON_CREATE: mTransactionHandler.handleLaunchActivity(r, mPendingActions, null /* customIntent */); break; case ON_START: mTransactionHandler.handleStartActivity(r, mPendingActions, null /* activityOptions */); break; case ON_RESUME: mTransactionHandler.handleResumeActivity(r, false /* finalStateRequest */, r.isForward, "LIFECYCLER_RESUME_ACTIVITY"); break; case ON_PAUSE: mTransactionHandler.handlePauseActivity(r, false /* finished */, false /* userLeaving */, 0 /* configChanges */, mPendingActions, "LIFECYCLER_PAUSE_ACTIVITY"); break; case ON_STOP: mTransactionHandler.handleStopActivity(r, 0 /* configChanges */, mPendingActions, false /* finalStateRequest */, "LIFECYCLER_STOP_ACTIVITY"); break; case ON_DESTROY: mTransactionHandler.handleDestroyActivity(r, false /* finishing */, 0 /* configChanges */, false /* getNonConfigInstance */, "performLifecycleSequence. cycling to:" + path.get(size - 1)); break; case ON_RESTART: mTransactionHandler.performRestartActivity(r, false /* start */); break; default: throw new IllegalArgumentException("Unexpected lifecycle state: " + state); } } }
Here we finally see the familiar content, the life cycle of Activity, so excited ha ha.
Here we are on_ Take create as an example. As can be seen from the above code_ Create is actually an int value (constant), which we won't describe here. mTransactionHandler is an instance of ClientTransactionHandler. Look directly at the handleLaunchActivity() method.
9.2.11 ClientTransactionHandler.handleLaunchActivity()
frameworks/base/core/java/android/app/ClientTransactionHandler.java
public abstract class ClientTransactionHandler { ... /** Perform activity launch. */ public abstract Activity handleLaunchActivity(@NonNull ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent); ... }
It can be seen from the above that handleLaunchActivity() is an abstract method. ActivityThread is its subclass. You can only find its subclass ActivityThread to see the specific implementation.
9.2.12 ActivityThread.handleLaunchActivity()
/** * Extended implementation of activity launch. Used when server requests a launch or relaunch. */ @Override public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) { // Creating activity Previous initialization if (ThreadedRenderer.sRendererEnabled && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) { HardwareRenderer.preload(); } //initialization Activity of WindowManager, each Activity Will correspond to a "window". WindowManagerGlobal.initialize(); // Tips GraphicsEnvironment Activity Starting in process. GraphicsEnvironment.hintActivityLaunch(); //Focus here: Activity Core implementation of startup. final Activity a = performLaunchActivity(r, customIntent); ... return a; }
performLaunchActivity(), the core implementation of Activity startup. Let's look down
9.2.13 ActivityThread.performLaunchActivity()
/** Core implementation of activity launch. */ private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... ContextImpl appContext = createBaseContextForActivity(r); Activity activity = null; try { java.lang.ClassLoader cl = appContext.getClassLoader(); //Note 1: Newly instantiated Activity Object. activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); ... } catch (Exception e) { ... } //Important: call activity.attach(). //establish Activity And Context The link between. //establish PhoneWindow Object, and with Activity Perform associated operations. 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, r.assistToken, r.shareableActivityToken); //The persistableMode property is set to: ActivityInfo.PERSIST_ACROSS_REBOOTS(persistAcrossReboots); //Note 2: Execution Activity of onCreate() method. if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } return activity; }
First of all, let's see that M instrumentation is actually instrumentation. It is also useful in the startactivity forresult section of this article. Instrumentation is responsible for the establishment and life cycle control of applications and activities.
Here we use his two methods. Let's have a look.
9.2.14 Instrumentation.newActivity()
/** * @param cl The classloader used to instantiate the object. * @param className realization Activity The name of the class of the object. * @param intent Specifies the name of the activity class to instantiate Intent Object. * * @return Newly instantiated Activity Object. */ public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { String pkg = intent != null && intent.getComponent() != null ? intent.getComponent().getPackageName() : null; return getFactory(pkg).instantiateActivity(cl, className, intent); }
pkg is the package name of intent.
getFactory(pkg) obtains AppComponentFactory through the obtained package name. Then call its instantiateActivity() method to get Activity.
9.2.14.1 Instrumentation.getFactory()
private AppComponentFactory getFactory(String pkg) { if (pkg == null) { ... return AppComponentFactory.DEFAULT; } if (mThread == null) { .... return AppComponentFactory.DEFAULT; } LoadedApk apk = mThread.peekPackageInfo(pkg, true); // This is in the case of starting up "android". if (apk == null) apk = mThread.getSystemContext().mPackageInfo; return apk.getAppFactory(); }
9.2.14.2 AppComponentFactory.instantiateActivity()
frameworks/base/core/java/android/app/AppComponentFactory.java
/** * For control manifest Element instantiated interface. * * @see #instantiateApplication * @see #instantiateActivity * @see #instantiateClassLoader * @see #instantiateService * @see #instantiateReceiver * @see #instantiateProvider */ public class AppComponentFactory { ... }
instantiateActivity()
/** * This method is only used to provide hooks for instantiation. * It does not provide for Activity Object. * The returned object will not be initialized to Context And should not be used with others android API Interaction. */ public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className, @Nullable Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return (Activity) cl.loadClass(className).newInstance(); }
Here, get the instance of Activity through reflection.
9.2.15 Instrumentation.callActivityOnCreate()
/** * implement A call to the Activity#onCreate method. * * @param activity Creating activity . * @param icicle Pass a previously frozen state (or null) to onCreate() . */ public void callActivityOnCreate(Activity activity, Bundle icicle) { prePerformCreate(activity); //a key activity.performCreate(icicle); postPerformCreate(activity); }
From here, you can see that you are about to enter the interior of the Activity.
9.2.15.1 Activity.performCreate()
final void performCreate(Bundle icicle) { performCreate(icicle, null); } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) final void performCreate(Bundle icicle, PersistableBundle persistentState) { ... //a key if (persistentState != null) { onCreate(icicle, persistentState); } else { onCreate(icicle); } ... }
As you can see here, the process in the startSpecificActivity() method has started, which is the end. startActivity started successfully. In combination with 9.2.13 ActivityThread.performLaunchActivity(), we can see that the attach() method call in the Activity is earlier than the onCreate() method.
Let's go back to 9.1 startSpecificActivity() to check the process that has not been started.
9.3 process not started
Since the process is not started, it must be started first. Let's keep watching.
final ActivityTaskManagerService mService; void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) { .... mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity"); }
From here, we can see that mService is actually ATMS. Let's go.
9.3.1 ATMS.startProcessAsync()
void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop, String hostingType) { try { ... // Publish a message to start the process to avoid holding ATMS Called in case of lock AMS Deadlock may occur. final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess, mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead, isTop, hostingType, activity.intent.getComponent()); mH.sendMessage(m); } finally { Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } }
9.3.2 ActivityManagerInternal.startProcess()
frameworks/base/core/java/android/app/ActivityManagerInternal.java
/** * Activity manager local system service interface. */ public abstract class ActivityManagerInternal { /** Starts a given process. */ public abstract void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead, boolean isTop, String hostingType, ComponentName hostingName); }
This is an abstract class. Let's find its implementation class ActivityManagerService.LocalService.
9.3.3 ActivityManagerService.LocalService.startProcess()
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback, ActivityManagerGlobalLock { ... @VisibleForTesting public final class LocalService extends ActivityManagerInternal implements ActivityManagerLocal { ... @Override public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead, boolean isTop, String hostingType, ComponentName hostingName) { try { synchronized (ActivityManagerService.this) { // If the process is called top App, please set a prompt so that when starting the process, the highest priority can be applied immediately to avoid attaching top Before the app process, the cpu was preempted by other processes. startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */, new HostingRecord(hostingType, hostingName, isTop), ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */, false /* isolated */); } } finally { } } } }
9.3.4 ActivityManagerService.startProcessLocked()
/** * Process management. */ final ProcessList mProcessList; @GuardedBy("this") final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, boolean keepIfLarge) { return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */); }
As you can see, the mProcessList here is ProcessList.
9.3.5 ProcessList.startProcessLocked()
frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@GuardedBy("mService") final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) { ... final boolean success = startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride); checkSlow(startTime, "startProcess: done starting proc!"); return success ? app : null; } ------------Split line------------- @GuardedBy("mService") final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord, int zygotePolicyFlags, String abiOverride) { return startProcessLocked(app, hostingRecord, zygotePolicyFlags, false /* disableHiddenApiChecks */, false /* disableTestApiChecks */, false /* mountExtStorageFull */, abiOverride); } ------------Split line------------- /** * @return {@code true} if process start is successful, false otherwise. */ @GuardedBy("mService") boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord, int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks, boolean mountExtStorageFull, String abiOverride) { ... return startProcessLocked(hostingRecord, entryPoint, app, uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startTime); } ------------Split line------------- @GuardedBy("mService") boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal, String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime) { ... //Finally get to the point. final Process.ProcessStartResult startResult = startProcess(hostingRecord, entryPoint, app, uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startTime); handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper, startSeq, false); ... }
After repeated calls, you finally see the key code startProcess().
9.3.6 ProcessList.startProcess()
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal, String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime) { ... final Process.ProcessStartResult startResult; if (hostingRecord.usesWebviewZygote()) { //Should the process start from webview zygote produce startResult = startWebView(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, app.info.packageName, app.mDisabledCompatChanges, new String[]{PROC_START_SEQ_IDENT + app.startSeq}); } else if (hostingRecord.usesAppZygote()) { //Should the process be from the application zygote Generated in final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app); // We cannot isolate application data from stored data because the parent zygote This has already been done. startResult = appZygote.getProcess().start(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, app.info.packageName, /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap, false, false, new String[]{PROC_START_SEQ_IDENT + app.startSeq}); } else { startResult = Process.start(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags, isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs, new String[]{PROC_START_SEQ_IDENT + app.startSeq}); } ... }
In either case, Process.start() will be called;
9.3.7 Process.start()
frameworks/base/core/java/android/os/Process.java
/** * State associated with the zygote process. */ public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess(); public static ProcessStartResult start(@NonNull final String processClass, @Nullable final String niceName, int uid, int gid, @Nullable int[] gids, int runtimeFlags, int mountExternal, int targetSdkVersion, @Nullable String seInfo, @NonNull String abi, @Nullable String instructionSet, @Nullable String appDataDir, @Nullable String invokeWith, @Nullable String packageName, int zygotePolicyFlags, boolean isTopApp, @Nullable long[] disabledCompatChanges, @Nullable Map<String, Pair<String, Long>> pkgDataInfoMap, @Nullable Map<String, Pair<String, Long>> whitelistedDataInfoMap, boolean bindMountAppsData, boolean bindMountAppStorageDirs, @Nullable String[] zygoteArgs) { return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges, pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData, bindMountAppStorageDirs, zygoteArgs); }
Zygote here_ Process is ZygoteProcess. Call its start() method.
9.3.8 ZygoteProcess.start()
frameworks/base/core/java/android/os/ZygoteProcess.java
/** * Start a new process. * If the process is enabled, a new process is created and processClass is executed there Static main() Function. * After the function returns, the process will continue to run. * * If the process is not enabled, a new thread is created in the caller process and called there processclass of main(). * * niceName Parameter, if not an empty string, is a custom name that is provided to the process instead of being used processClass. * This allows you to create processes that are easy to identify, even if you use the same basic processClass To start them. * * When invokeWith Not for null When, the process will be used as a new app instead of zygote fork Start. * Please note that this applies only to uid 0 Or when runtimeFlags contain DEBUG_ENABLE_DEBUGGER Time. * * @param processClass Class used as the main entry point for the process. * @param niceName A more readable name for the process. * @param uid The user under which the process will run ID. * @param gid The group under which the process will run ID. * @param gids Additional groups associated with the process ID. * @param runtimeFlags Additional signs. * @param targetSdkVersion Application objectives SDK edition. * @param seInfo null-ok New process SELinux Information. * @param abi Not empty. This application should use ABI. * @param instructionsSet null-Determine the instruction set to use. * @param appDataDir null-ok The data directory for the application. * @param invokeWith null-ok The command to call. * @param packageName null-ok The package name to which this process belongs. * @param zygotePolicyFlags Flag that determines how to start the application. * @param isTopApp Whether the process is started for a high priority application. * @param disabledCompatChanges Disable compatibility changes for the process being started null-ok List. * @param pkgDataInfoMap Mapping from related package names to private data directory volumes UUID and inode Number. * @param allowlistedDataInfoList Mapping from allowed package names to private data directory volumes UUID and inode Number. * @param bindMountAppsData zygote Need to mount CE and DE data * @param bindMountAppStorageDirs zygote Do you need to mount Android/obb And Android/data. * * @param zygoteArgs provide for Zygote Additional parameters for the process. * @return An object that describes the result of an attempt to start a process. * @throws RuntimeException A fatal startup failure occurred */ //There are a lot of parameters passed from the previous method, so I won't describe them much public final Process.ProcessStartResult start(...) { ... return startViaZygote(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false, packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges, pkgDataInfoMap, allowlistedDataInfoList, bindMountAppsData, bindMountAppStorageDirs, zygoteArgs); ... }
9.3.9 ZygoteProcess.startViaZygote()
//There are a lot of parameters passed from the previous method, so I won't describe them much private Process.ProcessStartResult startViaZygote(...) throws ZygoteStartFailedEx { ... synchronized(mLock) { // The USAP pool can not be used if the application will not use the systems graphics // driver. If that driver is requested use the Zygote application start path. return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), zygotePolicyFlags, argsForZygote); } }
Before looking at zygoteSendArgsAndGetResult(), let's look at openzygotesocketifneed (ABI).
9.3.10 ZygoteProcess.openZygoteSocketIfNeeded()
/** * Try opening a session Socket to have compatibility ABI of Zygote Process (if not already open). If compatible session If the socket has been opened, the session socket. * * This feature may block and you may have to try to connect to more than one Zygotes To find the right one Zygotes. Need to keep mLock. */ @GuardedBy("mLock") private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { try { attemptConnectionToPrimaryZygote(); ... } ------------Split line------------- /** * If Primary If Zygote does not exist or is disconnected, create one for it ZygoteState. */ @GuardedBy("mLock") private void attemptConnectionToPrimaryZygote() throws IOException { if (primaryZygoteState == null || primaryZygoteState.isClosed()) { primaryZygoteState = ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress); ... } } ------------Split line------------- static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress, @Nullable LocalSocketAddress usapSocketAddress) throws IOException { ... //Create LocalSocket final LocalSocket zygoteSessionSocket = new LocalSocket(); //Connect the zygoteSessionSocket to the endpoint. //Can only be called on instances that are not connected. zygoteSessionSocket.connect(zygoteSocketAddress); ... }
After opening the ZygoteSocket, let's take a look at zygoteSendArgsAndGetResult();
9.4.11 ZygoteProcess.zygoteSendArgsAndGetResult()
@GuardedBy("mLock") private Process.ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args) throws ZygoteStartFailedEx { ... String msgStr = args.size() + "\n" + String.join("\n", args) + "\n"; return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr); }
9.4.12 ZygoteProcess.attemptZygoteSendArgsAndGetResult()
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult( ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx { try { final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter; final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream; //Write, call zygote(ZygoteInit). zygoteWriter.write(msgStr); zygoteWriter.flush(); // Always read the entire result from the input stream to avoid leaving // bytes in the stream for future process starts to accidentally stumble // upon. Process.ProcessStartResult result = new Process.ProcessStartResult(); //Read and block result.pid = zygoteInputStream.readInt(); result.usingWrapper = zygoteInputStream.readBoolean(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } return result; } catch (IOException ex) { zygoteState.close(); Log.e(LOG_TAG, "IO Exception while communicating with Zygote - " + ex.toString()); throw new ZygoteStartFailedEx(ex); } }
9.4.13 ZygoteInit.main()
@UnsupportedAppUsage public static void main(String[] argv) { ... // zygote Permanent cycle. caller = zygoteServer.runSelectLoop(abiList); }
9.4.14 ZygoteService.runSelectLoop()
/** * function zygote Process selection loop. Accept new connections when they occur and read them one at a time spawn-request Value command. * @param abiList this zygote Supportive ABI List. */ Runnable runSelectLoop(String abiList) { ... //Session socket accepted from the Zygote server socket ZygoteConnection connection = peers.get(pollIndex); //adopt fork start-up Child process (application) final Runnable command = connection.processOneCommand(this); ... }
9.4.15 ZygoteConnection.processOneCommand()
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
Runnable processOneCommand(ZygoteServer zygoteServer) { ... pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote, parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList, parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs); ... }
fork out a new process (APP). The program entry of an app is ActivityThread.main().
9.4.15 ActivityThread.main()
frameworks/base/core/java/android/app/ActivityThread.java
When the ActivityThread is initialized, a message loop has been created, so it is not necessary to specify a loop when creating a Handler in the main thread. If you use a Handler in other threads, you need to create a message loop using loop. Prepare() and loop. Loop().
public static void main(String[] args) { ... //Initializes the of the current process Looper object Looper.prepareMainLooper(); ... ActivityThread thread = new ActivityThread(); //Create Application here thread.attach(false, startSeq); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // call Looper of loop Method to open an infinite loop. Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
Looper: take out the Message from the MessageQueue, and then process the task specified in the Message (startActivity).
At this point, whether you call startActivity() to start the page or startActivity() to start the interface of other processes is completed.
If you have any questions, please correct them.