This is for personal study record only, please verify carefully.

First, basic knowledge

1. Introduction to Binder mechanism

A binder is a means of communication between processes. In the operating system, it is divided into kernel space and user space. Each APP runs in its own user space. Binder mechanism is realized by two APP processes sharing kernel memory. Specific implementation does not do in-depth analysis; A Binder is a Cient process and a Server process that communicate with each other. Cient processes and Server processes depend on specific scenarios. A process can be a Cient process or a Server process.

2. ServiceManager

The ServiceManager is responsible for registering Binder Servers with a container so that when a Client process wants to communicate with the Server process, the ServiceManager can find Binder Servers in lookup tables. Return the Binder Server proxy object to the Client process.

3. ActivityManagerService

ActivityManagerService is a system service process that binds all four components to ActivityManagerService. ActivityManagerService registers itself with the ServiceManager using the following code:

public class ActivityManagerService extends IActivityManager.Stub {
    public void setSystemProcess(a) {
        ServiceManager.addService(Context.ACTIVITY_SERVICE, this./* allowIsolated= */ true,DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO); }}Copy the code

Once registered, other processes can obtain proxies for ActivityManagerService as follows:

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) {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    returnam; }}; }Copy the code

The above code, we can see that ActivityManager encapsulates the calls to ActivityManagerService, through ActivityManager. GerService () can obtain calls to ActivityManagerService.

4. Confused between ActivityThread and ApplicationThread

An ActivityThread is a UI thread that is created when the APP starts. It contains a static main() method like this (more on that later) :

public final class ActivityThread{
    // We will focus on this later
    Instrumentation mInstrumentation;
    
    public static void main(String[] args) {
        // omit some code...
        Looper.prepareMainLooper();
        // ...
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);
        // ...
        Looper.loop();
    }
    
    private void attach(boolean system, long startSeq) {
       mInstrumentation = new Instrumentation();
       // ...
       mInstrumentation.basicInit(this);
       ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
       mInitialApplication = context.mPackageInfo.makeApplication(true.null); }}Copy the code

ApplicationThread is an internal class of ActivityThreads. It is not a Thread. It is used to represent the current APP process (perhaps that is why it is called Thread). Getting another APP process is also done with binder to get its proxy implementation;

private class ApplicationThread extends IApplicationThread.Stub {
    // omit some code...
}
Copy the code

5. Instrumentation

With the new instrumentation, A new set of instruments, such as the following: a new set of instruments, a new set of instruments, a new set of rules, a new set of rules, a new set of rules, a new set of rules, a new set of rules, a new set of rules, a new set of rules. Instrumental music composedCopy the code

The Instrumentation source code is explained as follows:

/** * Base class for implementing application instrumentation code. When running * with instrumentation turned on, this class will be instantiated for you * before any of the application code, allowing you to monitor all of the * interaction the system has with the application. An Instrumentation * implementation is described to the system through an AndroidManifest.xml's * &lt; instrumentation&gt; tag. */Copy the code

All calls related to application can be easily observed by Instrumentation. In other words, all calls to application actually go through Instrumentation; Take a look at the source code and you can see that many functions are completed in it:

public class Instrumentation {
     private ActivityThread mThread = null;
     private MessageQueue mMessageQueue = null;
     private List<ActivityMonitor> mActivityMonitors;
     
     public Application newApplication(ClassLoader cl, String className, Context context) {}
     
     public Activity newActivity(ClassLoader cl, String className, Intent intent) {}

    public void callActivityOnNewIntent(Activity activity, Intent intent) {}
    
    public ActivityResult execStartActivity(a){}}Copy the code

2. Analyze the Activity startup process

For example, App1 wants to start an Activity in App2; The analysis of the Activity startup process is as follows:

1. SampleActivity1 in App1 starts SampleActivity2 in App2

public class SampleActivity1 {
    public void onClick(a) {
        Intent intent = getPackageManager().getLaunchIntentForPackage("com.app2.sample"); startActivity(intent); }}Copy the code

2. Activity source code analysis

public class Activity {
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }
    
    public void startActivity(Intent intent, @Nullable Bundle options) {
        // ...
        startActivityForResult(intent, -1);
    }
    
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
        // omit some code...
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);
        if(ar ! =null) { mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); }}}Copy the code

As you can see, the startActivity of the Activity is eventually called into the Instrumentation;

3. Instrumentation source code analysis

Continue parsing the execStartActivity() method of Instrumentation:

public class Instrumentation {
    /** * you can see some of the more important arguments passed: Context who: SampleActivity1 * 2.ibinder ContextThread: the value is mMainThread getApplicationThread (), namely the current APP process, the AMS process won't be able to communicate with App1 by IBinder process (such as return the results, you need binder communication) * 3. IBinder token indicates that another process needs to communicate with an IBinder token
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        // omit some code...
        try {
            intresult = ActivityTaskManager.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

As you can see, and continue to call the ActivityTaskManager. GetService () startActivity (). Ps. The android – 28 in the source code is called the ActivityManager. GetService () startActivity (), In older versions of the android source code is called the ActivityManagerNative getDefault (), the principle is similar, is call returns a proxy, eventually the system process to carry out the follow-up tune up logic.

4. ActivityTaskManager source code analysis

@SystemService(Context.ACTIVITY_TASK_SERVICE)
public class ActivityTaskManager {
    public static IActivityTaskManager getService(a) {
        return IActivityTaskManagerSingleton.get();
    }

    private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
            new Singleton<IActivityTaskManager>() {
                @Override
                protected IActivityTaskManager create(a) {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                    returnIActivityTaskManager.Stub.asInterface(b); }}; }Copy the code

. It can be seen that ActivityTaskManager getService () call get IBinder proxy continue to perform the following code, which is invoked to continue system process; ActivityTaskManager is a binder service registered during system startup with the following registration code:

@SystemApi
public final class SystemServiceRegistry {
    static {
        registerService(Context.ACTIVITY_TASK_SERVICE, ActivityTaskManager.class,
                new CachedServiceFetcher<ActivityTaskManager>() {
            @Override
            public ActivityTaskManager createService(ContextImpl ctx) {
                return new ActivityTaskManager(
                        ctx.getOuterContext(), ctx.mMainThread.getHandler());
            }});
    }
Copy the code

Next, analyze the startActivity() execution step in the system process;

5. ActivityTaskManagerService source code analysis

public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    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());
    }
    
    int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
        // omit some code...
        / / getActivityStartController (.) obtainStarter returns a ActivityStarter object, continue to analyze ActivityStarter below
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser") .setCaller(caller) .setCallingPackage(callingPackage) .setResolvedType(resolvedType) .setResultTo(resultTo) .setResultWho(resultWho) .setRequestCode(requestCode) .setStartFlags(startFlags) .setProfilerInfo(profilerInfo) .setActivityOptions(bOptions) .setMayWait(userId) .execute(); }}Copy the code

6. ActivityStarter source code analysis

The ActivityStarter handles parameters such as flag and startup mode in the intent.

class ActivityStarter {
    int execute(a) {
        try {
            // ...
            return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                        mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                        mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                        mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                        mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                        mRequest.outActivity, mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup,
                        mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
        } finally{ onExecutionComplete(); }}private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity, boolean restrictedBgActivity) {
        int result = START_CANCELED;
        final ActivityStack startedActivityStack;
        try {
            mService.mWindowManager.deferSurfaceLayout();
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
        }
        // ...
    }
    
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity, boolean restrictedBgActivity) {
        // ...mRootActivityContainer.resumeFocusedStacksTopActivities(); }}Copy the code

I’m going to go to RootActivityContainer;

/**
 * Root node for activity containers.
 * TODO:This class is mostly temporary to separate things out of ActivityStackSupervisor.java. The * intention is to have this Merged with RootWindowContainer. Java as part of unifying the hierarchy. * Looks like this class might be merged into RootWindowContainer, not focused on analysis; * /
class RootActivityContainer {
    boolean resumeFocusedStacksTopActivities( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if(targetStack ! =null&& (targetStack.isTopStackOnDisplay() || getTopDisplayFocusedStack() == targetStack)) { result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); }}}Copy the code

7. ActivityStack source code analysis

ActivityStack is responsible for managing the activity stack and the state of the activity, including how to manage the activity based on the state of the activity stack.

/** * State and management of a single stack of activities. */
class ActivityStack extends ConfigurationContainer {
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mInResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mInResumeTopActivity = true; result = resumeTopActivityInnerLocked(prev, options); }}private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        // ...
        if (next.attachedToProcess()) {
            if(nextNext ! = next) {// Do over!mStackSupervisor.scheduleResumeTopActivities(); }}else {
            // Whoops, need to restart this activity!
            mStackSupervisor.startSpecificActivityLocked(next, true.true); }}}Copy the code

8. StackSupervisor source code analysis

// TODO: This class has become a dumping ground. Let's
// - Move things relating to the hierarchy to RootWindowContainer
// - Move things relating to activity life cycles to maybe a new class called ActivityLifeCycler
// - Move interface things to ActivityTaskManagerService.
// - All other little things to other files.
// RootWindowContainer will also be used to create the RootWindowContainer
public class ActivityStackSupervisor implements RecentTasks.Callbacks {

    void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        final WindowProcessController wpc =
                mService.getProcessController(r.processName, r.info.applicationInfo.uid);

        boolean knownToBeDead = false;
        if(wpc ! =null && wpc.hasThread()) {
            try {
                // Key analysis
                realStartActivityLocked(r, wpc, 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.
            knownToBeDead = true; }}boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc, boolean andResume, boolean checkConfig) {
        // ...
        // Create activity launch transaction
        final ClientTransaction clientTransaction = ClientTransaction.obtain( proc.getThread(), r.appToken);
        // Remember that its callback is the LaunchActivityItem
        clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        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, proc.getReportedProcState(),
                        r.icicle, r.persistentState, results, newIntents,
                        dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
                                r.assistToken));
        / / the Schedule, mService is ActivityTaskManagerServicemService.getLifecycleManager().scheduleTransaction(clientTransaction); }}Copy the code

Above code analysis, launch the activity is encapsulated into a transaction with ClientLifecycleManager ActivityTaskManagerService in the processing process;

9. ClientLifecycleManager source code analysis

class ClientLifecycleManager {
    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        transaction.schedule();
        if(! (clientinstanceof Binder)) {
            // the transaction is executed on client in ActivityThread.transaction.recycle(); }}Copy the code

The code is explicit, which is to execute the contents of ClientTransaction; Next, examine the ClientTransaction code:

public class ClientTransaction implements Parcelable.ObjectPoolItem {
    /** Target client. */
    private IApplicationThread mClient;
    
    public void schedule(a) throws RemoteException {
        / / the key
        mClient.scheduleTransaction(this); }}Copy the code

As you can see from the above code, mCient’s scheduleTransaction() method is finally executed. And the IApplicationThread mClient is coming, this completes the call from the App2 ActivityTaskManagerService process;

ActivityThread source code analysis

Binder agents are used by other processes to access ApplicationThreads as IApplicationThreads. ApplicationThread is an inner class of ActivityThread. ScheduleTransaction () is ultimately implemented by ActivityThread.

/** * This manages the execution of the main thread in an * application process, scheduling and executing activities, * broadcasts, and other operations on it as the activity * manager requests. * inherited ClientTransactionHandler, behind also use analysis to * /
public final class ActivityThread extends ClientTransactionHandler {
    / / the key
    final H mH = new H();
    
    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }
    
    private class ApplicationThread extends IApplicationThread.Stub {
        @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            ActivityThread.this.scheduleTransaction(transaction); }}class H extends Handler {
        // ...
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case BIND_APPLICATION:
                    // ...
                    break;
                case EXIT_APPLICATION:
                    // ...
                    break;
                case RECEIVER:
                    // ...
                case CREATE_SERVICE:
                    // ...
                case BIND_SERVICE:
                   // ...
                case UNBIND_SERVICE:
                    // ...
                case STOP_SERVICE:
                   // ...
                case CONFIGURATION_CHANGED:
                    // ...
                case DUMP_SERVICE:
                    // ...
                / / to omit...
                case EXECUTE_TRANSACTION:
                    / / the key
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                    mTransactionExecutor.execute(transaction);
                    break;
                case RELAUNCH_ACTIVITY:
                    handleRelaunchActivityLocally((IBinder) msg.obj);
                    break;
                case PURGE_RESOURCES:
                    schedulePurgeIdler();
                    break; }}}}Copy the code

The inner class H inherits Handler to send message, and the message is processed by mH. You can see that H’s handleMessage() contains many familiar messages that are handled here; Continue to analyze behind EXECUTE_TRANSACTION, namely mTransactionExecutor. Execute (transaction);

11.TransactionExecutor source code analysis

/** * Class that manages transaction execution in the correct order
public class TransactionExecutor {

    public void execute(ClientTransaction transaction) {
        // Omit part...
        final IBinder token = transaction.getActivityToken();
        
        executeCallbacks(transaction);
        
        executeLifecycleState(transaction);
    }
    
    public void executeCallbacks(ClientTransaction transaction) {
        // The LaunchActivityItem is used as the callback for a transaction
        item.execute(mTransactionHandler, token, mPendingActions);
    }
Copy the code

LaunchActivityItem:

public class LaunchActivityItem extends ClientTransactionItem {
    @Override
    public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments);
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); }}Copy the code

Finally, the handleLaunchActivity is executed by the client, which is the ActivityThread. Why don’t you just start with ActivityThread and go through all the hoops? 😢 Because the startup process is as a transaction process, in addition to creating activities and life cycle callback need to ensure atomicity, so this part is encapsulated as a transaction; Here is actually my guess, next time I will cheat you ~

12. See also ActivityThread

Next, analyze the handleLaunchActivity() for ActivityThread!

public final class ActivityThread extends ClientTransactionHandler {
    @Override
    public Activity handleLaunchActivity(ActivityClientRecord r,
        // ...
        final Activity a = performLaunchActivity(r, customIntent);
        return a;
    }
    
    /** Core implementation of activity launch. */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // omit some code...
        ActivityInfo aInfo = r.activityInfo;
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            // Key code, you can see that the Instrumentation actually creates a new activity
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if(r.state ! =null) { r.state.setClassLoader(cl); }}catch (Exception e) {
            // ...
        }

        try {
            if(activity ! =null) {
                // ...
                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);
                // Instrumentation
                mInstrumentation.callActivityOnCreate(activity, r.state);
                r.activity = activity;
            }
            r.setState(ON_CREATE);
        }

        returnactivity; }}Copy the code

The most important code in the Instrumentation is the newActivity() and callActivityOnCreate() method, the following analysis;

13. See also Instrumentation

public class Instrumentation {

    public Activity newActivity(ClassLoader cl, String className, Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException { String pkg = intent ! =null&& intent.getComponent() ! =null
                ? intent.getComponent().getPackageName() : null;
        AppComponentFactory initializes the Activity
        return getFactory(pkg).instantiateActivity(cl, className, intent);
    }

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

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

As you can see, Instrumentation completes the initialization of the Activity through AppComponentFactory, and then calls the Activity’s performCreate() method;

14. Activity source code analysis

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

This completes the activity launch!

Third, summary