应用启动

原理图

image-20210126183751339

上述流程4——5之间还有一个过程,即当ActivityManagerService调用attachApplicationLocked时会跨进程调用thread.bindApplication通知应用进程发消息并调用handleBindApplication,内部会第一次初始化应用进程的mResources和mClassLoader给LoadedApk

Activity.startActivity

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
        }
    }

Instrumentation.execStartActivity

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
      
                int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);

ActivityManager.getService().startActivity

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
public abstract class Singleton<T> {
    private T mInstance;
    protected abstract T create();
    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

ActivityManagerService.startActivity

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
    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,
            boolean validateIncomingUser) {
        enforceNotIsolatedCaller("startActivity");

        userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // TODO: Switch to user app stacks here.
        return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();

    }
    /**
     * Starts an activity based on the request parameters provided earlier.
     * @return The starter result.
     */
    int execute() {
        return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                        mRequest.resolvedType, mRequest.activityInfo,......;
    }
    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,......) { 
              ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, checkedOptions, sourceRecord);
      
        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity);
    }
    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 {
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
      
          final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                ? mSourceRecord.getTask() : null;

        // Should this be considered a new task?
        int result = START_SUCCESS;
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
        } else if (mSourceRecord != null) {
            result = setTaskFromSourceRecord();
        } else if (mInTask != null) {
            result = setTaskFromInTask();
        } else {
            // This not being started from an existing activity, and not part of a new task...
            // just put it in the top task, though these days this case should never happen.
            setTaskToCurrentTopOrCreateNewTask();
        }
      
       mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,mOptions);
    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || !r.isState(RESUMED)) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        }
        return false;
    }
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }
    @GuardedBy("mService")
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
      mStackSupervisor.startSpecificActivityLocked(next, true, false);
    }
    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        if (app != null && app.thread != null) {
             //进程已经启动
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            }
        }
        //启动应用进程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

startProcessLocked

    @GuardedBy("this")
    final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }
    @GuardedBy("this")
    final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
            boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
        ProcessRecord app;
      
        if (app == null) {
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
        }
        final boolean success = startProcessLocked(app, hostingType, hostingNameStr, abiOverride);
        return success ? app : null;
    }
    @GuardedBy("this")
    private final boolean startProcessLocked(ProcessRecord app,
            String hostingType, String hostingNameStr, String abiOverride) {
        return startProcessLocked(app, hostingType, hostingNameStr,
                false /* disableHiddenApiChecks */, abiOverride);
    }
   /**
     * @return {@code true} if process start is successful, false otherwise.
     */
    @GuardedBy("this")
    private final boolean startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
      ......
                    return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
                    runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
                    startTime);
    }
    @GuardedBy("this")
    private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
            long startTime) {
                      final ProcessStartResult startResult = startProcess(hostingType, entryPoint, app,
                        uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
                        invokeWith, startTime);
    }
    private ProcessStartResult startProcess(String hostingType, String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
            long startTime) {
                      startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith,
                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});
    }
    public static final ZygoteProcess zygoteProcess =
            new ZygoteProcess(ZYGOTE_SOCKET, SECONDARY_ZYGOTE_SOCKET);

public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int runtimeFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String invokeWith,
                                  String[] zygoteArgs) {
        return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
    }

frameworks/base/core/java/android/os/ZygoteProcess.java

ZygoteProcess.start

    /**
     * The name of the socket used to communicate with the primary zygote.
     */
    private final LocalSocketAddress mSocket;

    /**
     * The name of the secondary (alternate ABI) zygote socket.
     */
    private final LocalSocketAddress mSecondarySocket;
    public final Process.ProcessStartResult start(final String processClass,
                                                  final String niceName,
                                                  int uid, int gid, int[] gids,
                                                  int runtimeFlags, int mountExternal,
                                                  int targetSdkVersion,
                                                  String seInfo,
                                                  String abi,
                                                  String instructionSet,
                                                  String appDataDir,
                                                  String invokeWith,
                                                  String[] zygoteArgs) {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
                    zygoteArgs);
    private Process.ProcessStartResult startViaZygote(final String processClass,
                                                      final String niceName,
                                                      final int uid, final int gid,
                                                      final int[] gids,
                                                      int runtimeFlags, int mountExternal,
                                                      int targetSdkVersion,
                                                      String seInfo,
                                                      String abi,
                                                      String instructionSet,
                                                      String appDataDir,
                                                      String invokeWith,
                                                      boolean startChildZygote,
                                                      String[] extraArgs)
                                                      throws ZygoteStartFailedEx {
        synchronized(mLock) {
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }

openZygoteSocketIfNeeded

    /**
     * Tries to open socket to Zygote process if not already open. If
     * already open, does nothing.  May block and retry.  Requires that mLock be held.
     */
    @GuardedBy("mLock")
    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
          if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
                primaryZygoteState = ZygoteState.connect(mSocket);
          }
          if (primaryZygoteState.matches(abi)) {
            return primaryZygoteState;
          }
          // The primary zygote didn't match. Try the secondary.
          if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
                secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
          }
          if (secondaryZygoteState.matches(abi)) {
            return secondaryZygoteState;
          }
              
        public static ZygoteState connect(LocalSocketAddress address) throws IOException {
            DataInputStream zygoteInputStream = null;
            BufferedWriter zygoteWriter = null;
            final LocalSocket zygoteSocket = new LocalSocket();

            zygoteSocket.connect(address);

            //inputStream,读取Zygote发来的数据
            zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());
            //outputStream,写入socket数据
            zygoteWriter = new BufferedWriter(new OutputStreamWriter(zygoteSocket.getOutputStream()), 256);
            String abiListString = getAbiList(zygoteWriter, zygoteInputStream);
            return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
                    Arrays.asList(abiListString.split(",")));
        }
    /**
     * Queries the zygote for the list of ABIS it supports.
     */
    @GuardedBy("mLock")
    private static String getAbiList(BufferedWriter writer, DataInputStream inputStream)
            throws IOException {
        // Each query starts with the argument count (1 in this case)
        writer.write("1");
        // ... followed by a new-line.
        writer.newLine();
        // ... followed by our only argument.
        writer.write("--query-abi-list");
        writer.newLine();
        writer.flush();

        // The response is a length prefixed stream of ASCII bytes.
        int numBytes = inputStream.readInt();
        byte[] bytes = new byte[numBytes];
        inputStream.readFully(bytes);

        return new String(bytes, StandardCharsets.US_ASCII);
    }

zygoteSendArgsAndGetResult

    /**
     * Sends an argument list to the zygote process, which starts a new child
     * and returns the child's pid. Please note: the present implementation
     * replaces newlines in the argument list with spaces.
     *
     * @throws ZygoteStartFailedEx if process start failed for any reason
     */
    @GuardedBy("mLock")
    private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
      
            /**
             * See com.android.internal.os.SystemZygoteInit.readArgumentList()
             * Presently the wire format to the zygote process is:
             * a) a count of arguments (argc, in essence)
             * b) a number of newline-separated argument strings equal to count
             *
             * After the zygote process reads these it will write the pid of
             * the child or -1 on failure, followed by boolean to
             * indicate whether a wrapper process was used.
             */
            final BufferedWriter writer = zygoteState.writer;
            final DataInputStream inputStream = zygoteState.inputStream;
      
            writer.write(Integer.toString(args.size()));
            writer.newLine();

            for (int i = 0; i < sz; i++) {
                String arg = args.get(i);
                writer.write(arg);
                writer.newLine();
            }

            writer.flush();

            // Should there be a timeout on this?
            Process.ProcessStartResult result = new Process.ProcessStartResult();

            // Always read the entire result from the input stream to avoid leaving
            // bytes in the stream for future process starts to accidentally stumble
            // upon.
            result.pid = inputStream.readInt();
            result.usingWrapper = inputStream.readBoolean();
            return result;

Zygote启动AppProcess

参考

ActivityThread.main

final ApplicationThread mAppThread = new ApplicationThread();

Looper.prepareMainLooper();

public static void main(String[] args) {
      Looper.prepareMainLooper();
}

IActivityManager.attachApplication

  ActivityThread thread = new ActivityThread();
  thread.attach(false, startSeq);
private void attach(boolean system, long startSeq) {
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
}

Looper.loop()

Looper.loop();

ActivityManagerService.attachApplication

    @Override
    public final void attachApplication(IApplicationThread thread, long startSeq) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            Binder.restoreCallingIdentity(origId);
        }
    }
    @GuardedBy("this")
    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
      
            AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);
            thread.asBinder().linkToDeath(adr, 0);
            app.deathRecipient = adr;
      
      
            thread.bindApplication(....)
              
            StackSupervisor.attachApplicationLocked(app)//realStartActivityLocked
    }

linkToDeath配置AppDeathRecipient监听appDeath

    private final class AppDeathRecipient implements IBinder.DeathRecipient {
        final ProcessRecord mApp;
        final int mPid;
        final IApplicationThread mAppThread;

        @Override
        public void binderDied() {
            synchronized(ActivityManagerService.this) {
                appDiedLocked(mApp, mPid, mAppThread, true);
            }
        }
    }

thread.bindApplication

class ApplicationThread {  
   public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                String buildSerial, boolean autofillCompatibilityEnabled) {
     sendMessage(H.BIND_APPLICATION, data);
   }
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BIND_APPLICATION:
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    break;
private void handleBindApplication(AppBindData data) { 
  data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
  
  app = data.info.makeApplication(data.restrictedBackupMode, null);
  
  installContentProviders(app, data.providers);
  
  mInstrumentation.callApplicationOnCreate(app);
}

getPackageInfo初始化LoadedApk

    @Override
    public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
            CompatibilityInfo compatInfo) {
        return getPackageInfo(ai, compatInfo, null, false, true, false);
    }
    private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
            ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
            boolean registerPackage) {
              packageInfo =
                    new LoadedApk(this, aInfo, compatInfo, baseLoader,
                            securityViolation, includeCode &&
                            (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
    }

LoadedApk.makeApplication

    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
            if (mApplication != null) {
              return mApplication;
            }
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                initializeJavaContextClassLoader();
            }
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
            appContext.setOuterContext(app);
      
          mActivityThread.mAllApplications.add(app);
          mApplication = app;
    }
    public ClassLoader getClassLoader() {
        synchronized (this) {
            if (mClassLoader == null) {
                createOrUpdateClassLoaderLocked(null /*addedPaths*/);
            }
            return mClassLoader;
        }
    }

Instrumentation.newApplication

    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }
    private AppComponentFactory getFactory(String pkg) {
        if (pkg == null) {
            Log.e(TAG, "No pkg specified, disabling AppComponentFactory");
            return AppComponentFactory.DEFAULT;
        }
        if (mThread == null) {
            Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation,"
                    + " disabling AppComponentFactory", new Throwable());
            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();
    }

AppComponentFactory.instantiateApplication

    public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
            @NonNull String className)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Application) cl.loadClass(className).newInstance();
    }

Application.attach

    /* package */ final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }

installContentProviders

mInstrumentation.callApplicationOnCreate

    public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }

realStartActivityLocked

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    realStartActivityLocked(activity, app, top == activity /* andResume */, true /* checkConfig */))
}

Create activity launch transaction

    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
      
                 // Create activity launch transaction.
                final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                        r.appToken);
                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, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                        profilerInfo));

                // Set desired final state.
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);

                // Schedule transaction.
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
    }
    /**
     * Schedule a transaction, which may consist of multiple callbacks and a lifecycle request.
     * @param transaction A sequence of client transaction items.
     * @throws RemoteException
     *
     * @see ClientTransaction
     */
    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        transaction.schedule();
        if (!(client instanceof Binder)) {
            // If client is not an instance of Binder - it's a remote call and at this point it is
            // safe to recycle the object. All objects used for local calls will be recycled after
            // the transaction is executed on client in ActivityThread.
            transaction.recycle();
        }
    }

ClientTransaction.java

    /** Get the target client of the transaction. */
    public IApplicationThread getClient() {
        return mClient;
    }
    
    /**
     * Schedule the transaction after it was initialized. It will be send to client and all its
     * individual parts will be applied in the following sequence:
     * 1. The client calls {@link #preExecute(ClientTransactionHandler)}, which triggers all work
     *    that needs to be done before actually scheduling the transaction for callbacks and
     *    lifecycle state request.
     * 2. The transaction message is scheduled.
     * 3. The client calls {@link TransactionExecutor#execute(ClientTransaction)}, which executes
     *    all callbacks and necessary lifecycle transitions.
     */
    public void schedule() throws RemoteException {
        mClient.scheduleTransaction(this);
    }
        @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            ActivityThread.this.scheduleTransaction(transaction);
        }
public final class ActivityThread extends ClientTransactionHandler {
}
/**
 * Defines operations that a {@link android.app.servertransaction.ClientTransaction} or its items
 * can perform on client.
 * @hide
 */
public abstract class ClientTransactionHandler {

    // Schedule phase related logic and handlers.

    /** Prepare and schedule transaction for execution. */
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
                case EXECUTE_TRANSACTION:
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                    mTransactionExecutor.execute(transaction);
                    if (isSystem()) {
                        // Client transactions inside system process are recycled on the client side
                        // instead of ClientLifecycleManager to avoid being cleared before this
                        // message is handled.
                        transaction.recycle();
                    }
                    // TODO(lifecycler): Recycle locally scheduled transactions.
                    break;
    public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        executeCallbacks(transaction);
    }
    /** 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 int size = callbacks.size();
        for (int i = 0; i < size; ++i) {
            final ClientTransactionItem item = callbacks.get(i);
            item.execute(mTransactionHandler, token, mPendingActions);

LaunchActivityItem.execute

    @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);
        //ActivityThread实例
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

newActivity

activity.attach

mInstrumentation.callActivityOnCreate

记录ActivityClientRecord

    /**
     * Extended implementation of activity launch. Used when server requests a launch or relaunch.
     */
    @Override
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
      final Activity a = performLaunchActivity(r, customIntent);
    }

    /**  Core implementation of activity launch. */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
            ContextImpl appContext = createBaseContextForActivity(r);
            Activity activity = null;
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
      
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
      
                appContext.setOuterContext(activity);
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);
      
                mInstrumentation.callActivityOnCreate(activity, r.state);
      
            r.activity = activity;
            r.setState(ON_CREATE);

            mActivities.put(r.token, r);
    }
    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);
    }

其他

ContextImpl.createAppContext

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
   if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
   ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
       null);
   context.setResources(packageInfo.getResources());
   return context;
 }

getResources

public Resources getResources() {
   if (mResources == null) {
     final String[] splitPaths;
     try {
       splitPaths = getSplitPaths(null);
    } catch (NameNotFoundException e) {
     // This should never fail.
     throw new AssertionError("null split not found");
    }

    mResources = ResourcesManager.getInstance().getResources(null, mResDir,//main
         splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
         Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
         getClassLoader());//main
   }
   return mResources;
 }

getClassLoader

public ClassLoader getClassLoader() {
   synchronized (this) {
     if (mClassLoader == null) {
       createOrUpdateClassLoaderLocked(null /*addedPaths*/);
     }
     return mClassLoader;
   }
 }

createOrUpdateClassLoaderLocked

private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
 if (mClassLoader == null) {
   mClassLoader = ApplicationLoaders.getDefault().getClassLoader(
     "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
     librarySearchPath, libraryPermittedPath, mBaseClassLoader,
     null /* classLoaderName */);

   mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader);
 }

if (addedPaths != null && addedPaths.size() > 0) {
   //更新PathClassLoader实例
  final String add = TextUtils.join(File.pathSeparator, addedPaths);
   ApplicationLoaders.getDefault().addPath(mClassLoader, add);
   // Setup the new code paths for profiling.
   needToSetupJitProfiles = true;
 }

ApplicationLoaders.getClassLoader

private ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
                  String librarySearchPath, String libraryPermittedPath,
                  ClassLoader parent, String cacheKey,
                  String classLoaderName) {
/*
 \* This is the parent we use if they pass "null" in. In theory
 \* this should be the "system" class loader; in practice we
 \* don't use that and can happily (and more efficiently) use the
 \* bootstrap class loader.
 */
 //ClassLoader.getSystemClassLoader()是PathClassLoader,再getParent为BootClassLoader

ClassLoader baseParent = ClassLoader.getSystemClassLoader().getParent();
/*
 \* If we're one step up from the base class loader, find
 \* something in our cache. Otherwise, we create a whole
 \* new ClassLoader for the zip archive.
 */
 if (parent == baseParent) {
   ClassLoader loader = mLoaders.get(cacheKey);
   if (loader != null) {
     return loader;
   }

  ClassLoader classloader = ClassLoaderFactory.createClassLoader(
     zip, librarySearchPath, libraryPermittedPath, parent,
     targetSdkVersion, isBundled, classLoaderName);
   mLoaders.put(cacheKey, classloader);
   return classloader;
}
ClassLoader loader = ClassLoaderFactory.createClassLoader(zip, null, parent, classLoaderName);
ClassLoaderFactory.createClassLoader
/**
 \* Create a ClassLoader and initialize a linker-namespace for it.
 */
 public static ClassLoader createClassLoader(String dexPath,
     String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
     int targetSdkVersion, boolean isNamespaceShared, String classloaderName) {
   final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent,
       classloaderName);

   String errorMessage = createClassloaderNamespace(classLoader,
                         targetSdkVersion,
                         librarySearchPath,
                         libraryPermittedPath,
                         isNamespaceShared,
                         isForVendor);
   return classLoader;
 }

/**
 \* Same as {@code createClassLoader} below, except that no associated namespace
 \* is created.
 */
 public static ClassLoader createClassLoader(String dexPath,
     String librarySearchPath, ClassLoader parent, String classloaderName) {
   if (isPathClassLoaderName(classloaderName)) {
     return new PathClassLoader(dexPath, librarySearchPath, parent);
   } else if (isDelegateLastClassLoaderName(classloaderName)) {
     return new DelegateLastClassLoader(dexPath, librarySearchPath, parent);
   }

   throw new AssertionError("Invalid classLoaderName: " + classloaderName);
 }

/**
 \* Returns true if {@code name} is the encoding for either PathClassLoader or DexClassLoader.
 \* The two class loaders are grouped together because they have the same behaviour.
 */
 public static boolean isPathClassLoaderName(String name) {
   // For null values we default to PathClassLoader. This cover the case when packages
   // don't specify any value for their class loaders.
   return name == null || PATH_CLASS_LOADER_NAME.equals(name) ||
       DEX_CLASS_LOADER_NAME.equals(name);
 }

private static native String createClassloaderNamespace(ClassLoader classLoader,...)

createAppComponentFactory

private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) {
   if (appInfo.appComponentFactory != null && cl != null) {
     try {
       return (AppComponentFactory) cl.loadClass(appInfo.appComponentFactory)
           .newInstance();
     } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
       Slog.e(TAG, "Unable to instantiate appComponentFactory", e);
     }
   }
   return AppComponentFactory.DEFAULT;
 }
AppComponentFactory
public static final AppComponentFactory DEFAULT = new AppComponentFactory();
public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
     @NonNull String className)
     throws InstantiationException, IllegalAccessException, ClassNotFoundException {
   return (Application) cl.loadClass(className).newInstance();
 }

public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
     @Nullable Intent intent)
     throws InstantiationException, IllegalAccessException, ClassNotFoundException {
   return (Activity) cl.loadClass(className).newInstance();
 }

public @NonNull Service instantiateService(@NonNull ClassLoader cl,
     @NonNull String className, @Nullable Intent intent)
     throws InstantiationException, IllegalAccessException, ClassNotFoundException {
   return (Service) cl.loadClass(className).newInstance();
 }

public @NonNull BroadcastReceiver instantiateReceiver(@NonNull ClassLoader cl,
     @NonNull String className, @Nullable Intent intent)
     throws InstantiationException, IllegalAccessException, ClassNotFoundException {
   return (BroadcastReceiver) cl.loadClass(className).newInstance();
 }

public @NonNull ContentProvider instantiateProvider(@NonNull ClassLoader cl,
     @NonNull String className)
     throws InstantiationException, IllegalAccessException, ClassNotFoundException {
   return (ContentProvider) cl.loadClass(className).newInstance();
 }

ContextImpl.createActivityContext

//ActivityThread
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
    ContextImpl appContext = ContextImpl.createActivityContext(
     this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
    return appContext;
static ContextImpl createActivityContext(ActivityThread mainThread,
     LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
     Configuration overrideConfiguration) {
ClassLoader classLoader = packageInfo.getClassLoader();//main
  
if (packageInfo.getApplicationInfo().requestsIsolatedSplitLoading()) {
   Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "SplitDependencies");
   try {
     classLoader = packageInfo.getSplitClassLoader(activityInfo.splitName);
     splitDirs = packageInfo.getSplitPaths(activityInfo.splitName);

ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
     activityToken, null, 0, classLoader);

final ResourcesManager resourcesManager = ResourcesManager.getInstance();

// Create the base resources for which all configuration contexts for this Activity
 // will be rebased upon.
 context.setResources(resourcesManager.createBaseActivityResources(activityToken,
     packageInfo.getResDir(),
     splitDirs,
     packageInfo.getOverlayDirs(),
     packageInfo.getApplicationInfo().sharedLibraryFiles,
     displayId,
     overrideConfiguration,
     compatInfo,
     classLoader));
 context.mDisplay = resourcesManager.getAdjustedDisplay(displayId,
     context.getResources());
 return context;

LoadedApk

initializeJavaContextClassLoader

private void initializeJavaContextClassLoader() {
ClassLoader contextClassLoader =
   (sharable)
   ? new WarningContextClassLoader()
   : mClassLoader;
 Thread.currentThread().setContextClassLoader(contextClassLoader);

ContextImpl

final @NonNull ActivityThread mMainThread;
 final @NonNull LoadedApk mPackageInfo;
 private @Nullable ClassLoader mClassLoader;

@Override
 public ClassLoader getClassLoader() {
   return mClassLoader != null ? mClassLoader : (mPackageInfo != null ? mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader());
 }

static ContextImpl getImpl(Context context) {
   Context nextContext;
   while ((context instanceof ContextWrapper) &&
       (nextContext=((ContextWrapper)context).getBaseContext()) != null) {
     context = nextContext;
   }
   return (ContextImpl)context;
 }