Android system startup (4) — Launcher startup process

1 Launcheroverview

The last step in system startup is to start an application to display the applications already installed in the system, this application is called Launcher. LauncherDuring the startup process, it will be requested PackageManagerServiceto return the installed application program information in the system, and the information will be packaged into a shortcut icon list and displayed on the system screen, so that the user can start the corresponding application program by clicking these shortcut icons.

In layman's terms, Launcherit is Androidthe desktop of the system, and its functions mainly include the following two points:

  • As Androidthe launcher of the system, it is used to start the application program;
  • As Androidthe desktop of the system, it is used to display and manage shortcut icons of applications or other desktop components;

2 Launcherstart process

SystemServerThe process will be started during the startup process PackageManagerService, and PackageManagerServicethe application programs in the system will be installed after startup, and the ones that have been started before ActivityManagerServicewill be Launcherstarted.

LauncherThe startup is divided into three parts:

  • SystemServerComplete the relevant configuration Launcherof the startup Activity;
  • Zygoteprocess forkout process Launcher;
  • Enter ActivityThread.mainthe function, and finally complete the operation Launcherof Activity.onCreate;

LauncherThe relevant configuration completed in the first stage

figure 1

SystemServer.startOtherServicesCall the method in the method , ActivityManagerService.systemReadythe Launcherstart of the process starts from here, the following is the relevant source code:

// /frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
    
    
    ...
    mActivityManagerService.systemReady(() -> {
    
     // 1
        Slog.i(TAG, "Making services ready");
        traceBeginAndSlog("StartActivityManagerReadyPhase");
        mSystemServiceManager.startBootPhase(
            SystemService.PHASE_ACTIVITY_MANAGER_READY);
        traceEnd();
        }
       ...}                                                      

The following is ActivityManagerService.systemReadythe source code of the method:

// /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public ActivityTaskManagerInternal mAtmInternal;
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
    
    
    ...
    // 启动 Home Activity,即 Launcher 应用的入口 Activity,这里指的是,在所有屏幕上启动 Launcher。因为 Android 10 开始支持多屏幕,比如手机屏幕、虚拟投屏、外接屏幕
    mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady"); // 1
    ...
}

Here mAtmInternalis ActivityTaskManagerInternalan instance of , ActivityTaskManagerInternalwhich is an abstract class. ActivityManagerServiceThe inner class in LocalServiceimplements ActivityTaskManagerInternal:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
final class LocalService extends ActivityTaskManagerInternal {
    
    
    ...
    @Override
    public boolean startHomeOnAllDisplays(int userId, String reason) {
    
    
        synchronized (mGlobalLock) {
    
    
            return mRootActivityContainer.startHomeOnAllDisplays(userId, reason);
        }
    }
    ...
}

LocalService.startHomeOnAllDisplaysThe method was called in the method RootActivityContainer.startHomeOnAllDisplays. RootActivityContainerThe role of is to call PackageManagerServiceto query which of the installed applications in the mobile phone system meets Launcherthe standard, and return a Intentobject, and give it toActivityStarter :

// /frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean startHomeOnAllDisplays(int userId, String reason) {
    
    
    boolean homeStarted = false;
    for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
    
    
        final int displayId = mActivityDisplays.get(i).mDisplayId;
        homeStarted |= startHomeOnDisplay(userId, reason, displayId); // 1
    }
    return homeStarted;
}

boolean startHomeOnDisplay(int userId, String reason, int displayId) {
    
    
    return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,false /* fromHomeKey */);
}

boolean startHomeOnDisplay(int userId, String reason, int displayId, 
                           boolean allowInstrumenting, boolean fromHomeKey) {
    
    
    ...
    Intent homeIntent = null;
    ActivityInfo aInfo = null;
    if (displayId == DEFAULT_DISPLAY) {
    
    
        // 构建一个 category 为 CATEGORY_HOME 的 Intent,表明是 HomeActivity
        homeIntent = mService.getHomeIntent(); // 2
        // 通过 PMS 从系统所有已安装的引用中找到一个符合 homeIntent 的 Activity
        aInfo = resolveHomeActivity(userId, homeIntent); // 3
    } else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) {
    
    
        ...
    }
    ...
    // 启动 Launcher
    mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, 
                                                            myReason, displayId); // 4
    return true;
}

2The method is called at the comment ActivityTaskManagerService.getHomeIntent()to build a for category, indicating that it is a conforming application . Parse the information that needs to be started by calling the method at the comment . Call Get at the comment . The function of this class is to do various checks before startup, such as whether there is a list file registered, whether the file exists, etc., and then start .CATEGORY_HOMEIntentLauncherIntent3resolveHomeActivityActivity4ActivityTaskManagerService.getActivityStartController()ActivityStartControllerActivityClassActivity

The following is the relevant timing diagram:

figure 2

First, take a look at ActivityTaskManagerService.getHomeIntent()the method, which is mainly to build a conforming Launcherapplication Intent:

// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
Intent getHomeIntent() {
    
    
    Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
    intent.setComponent(mTopComponent);
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); 
    if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
    
    
        intent.addCategory(Intent.CATEGORY_HOME); // 1
    }
    return intent;
}     

The comment 1represents Activitythe intention to start. Generally speaking, there is only one application configured in the manifest file for the entire system CATEGORY_HOME. If multiple applications are configured, the system will require the user to manually select which application to use when starting. Start the application. If it is configured in the system settings application, the configured application will be selected.

Then look at RootActivityContainer.resolveIntentInternalthe method:

// /frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
                                          int flags, int userId, 
                                          boolean resolveForStart, 
                                          int filterCallingUid) {
    
    
    try {
    
    
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");

        if (!sUserManager.exists(userId)) return null;
        final int callingUid = Binder.getCallingUid();
        flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart);
        mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                                                      false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");

        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
                                                                      flags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/);
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

        final ResolveInfo bestChoice =
            chooseBestActivity(intent, resolvedType, flags, query, userId);
        return bestChoice;
    } finally {
    
    
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
}

Find a matching application from all installed applications in the system through Bindercross-process communication notification .PackageManagerServicehomeInentActivity

Look at the code of again ActivityStartController.startHomeActivity:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, 
                       int displayId) {
    
    
    final ActivityOptions options = ActivityOptions.makeBasic();
    options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
    if (!ActivityRecord.isResolverActivity(aInfo.name)) {
    
    
        options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
    }
    options.setLaunchDisplayId(displayId);
    mLastHomeActivityStartResult = 
        obtainStarter(intent, "startHomeActivity: " + reason) // 1
        .setOutActivity(tmpOutRecord)
        .setCallingUid(0)
        .setActivityInfo(aInfo)
        .setActivityOptions(options.toBundle())
        .execute(); // 2
    mLastHomeActivityStartRecord = tmpOutRecord[0];
    final ActivityDisplay display =
        mService.mRootActivityContainer.getActivityDisplay(displayId);
    final ActivityStack homeStack = display != null ? display.getHomeStack() : null;
    if (homeStack != null && homeStack.mInResumeTopActivity) {
    
     
        mSupervisor.scheduleResumeTopActivities();
    }
}

ActivityStarter obtainStarter(Intent intent, String reason) {
    
     // 3
    return mFactory.obtain().setIntent(intent).setReason(reason);
}

1First get one at the comment ActivityStarter, which is mainly used for startup Activity, then set the required parameters, and finally call its execute()method:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
int execute() {
    
    
    try {
    
    
        if (mRequest.mayWait) {
    
    
           ...
        } else {
    
    
            return startActivity(...);
        }
    } finally {
    
    
        onExecutionComplete();
    }
}

The following is ActivityStarter.startActivitythe relevant source code of , this method is mainly used for Activitysecurity verification before startup:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int startActivity(...) {
    
    
    mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
    int err = ActivityManager.START_SUCCESS;
    // Pull the optional Ephemeral Installer-only bundle out of the options early.
    final Bundle verificationBundle
        = options != null ? options.popAppVerificationBundle() : null;
    WindowProcessController callerApp = null;
    if (caller != null) {
    
    
        callerApp = mService.getProcessController(caller);
        if (callerApp != null) {
    
    
            callingPid = callerApp.getPid();
            callingUid = callerApp.mInfo.uid;
        } else {
    
    
            Slog.w(TAG, "Unable to find app for caller " + caller
                   + " (pid=" + callingPid + ") when starting: "
                   + intent.toString());
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }
	...
    final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, 
                                  startFlags, true /* doResume */, checkedOptions, 
                                  inTask, outActivity, restrictedBgActivity);
    ...
}

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord, 
                          IVoiceInteractionSession voiceSession, 
                          IVoiceInteractor voiceInteractor, int startFlags, 
                          boolean doResume, ActivityOptions options, 
                          TaskRecord inTask, ActivityRecord[] outActivity,
                          boolean restrictedBgActivity) {
    
    
    ...
    result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, 
                                    startFlags, doResume, options, inTask, 
                                    outActivity, restrictedBgActivity); // 1
    ...
}

Code 1called at comment :ActivityStarter.startActivityUnchecked

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, 
                                   ActivityRecord sourceRecord, 
                                   IVoiceInteractionSession voiceSession, 
                                   IVoiceInteractor voiceInteractor, int startFlags, 
                                   boolean doResume, ActivityOptions options, 
                                   TaskRecord inTask, ActivityRecord[] outActivity, 
                                   boolean restrictedBgActivity) {
    
    
	...
    final int preferredWindowingMode = mLaunchParams.mWindowingMode;
    computeLaunchingTaskFlags(); // 1
    computeSourceStack(); // 2
    mIntent.setFlags(mLaunchFlags);
    ActivityRecord reusedActivity = getReusableIntentActivity();
	...
    mRootActivityContainer.resumeFocusedStacksTopActivities(); // 3
    ...
}

1The method at the comment ActivityStarter.computeLaunchingTaskFlags()is the stacking method calculated based Activityon the launcher modeand of . The calculation at the comment starts from which stack . The method is called at the comment :intent.flagActivity2ActivityStarter.computeSourceStack()Activity3RootActivityContainer.resumeFocusedStacksTopActivities

// /frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean resumeFocusedStacksTopActivities() {
    
    
    return resumeFocusedStacksTopActivities(null, null, null);
}

boolean resumeFocusedStacksTopActivities(
    ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    
    
	...
    if (targetStack != null && (targetStack.isTopStackOnDisplay()
                                || getTopDisplayFocusedStack() == targetStack)) {
    
    
        result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }

    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
    
    
        ...
        if (!resumedOnDisplay) {
    
    
            final ActivityStack focusedStack = display.getFocusedStack(); 
            if (focusedStack != null) {
    
    
                focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); // 1
            }
        }
    }

    return result;
}

1Call the method at the comment ActivityStack.resumeTopActivityUncheckedLocked:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    
    
    ...
    result = resumeTopActivityInnerLocked(prev, options);
    ...
}

@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, 
                                             ActivityOptions options) {
    
    
    ...
    if (anim) {
    
    
        next.applyOptionsLocked();
    } else {
    
    
        next.clearOptionsLocked();
    }
    
    mStackSupervisor.mNoAnimActivities.clear();
    
    if (next.attachedToProcess()) {
    
     // 待启动的进程是否创建完成,如果没有就会到 else 中
        ...
    }  else {
    
    
         mStackSupervisor.startSpecificActivityLocked(next, true, true); // 1
    }
    ...
}

1Called at comment ActivityStackSupervisor.startSpecificActivityLocked:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r, boolean andResume,
                                 boolean checkConfig) {
    
    
    ...
    try {
    
    
        ...
        final Message msg = PooledLambda.obtainMessage(
            ActivityManagerInternal::startProcess,  // 1
            mService.mAmInternal, r.processName, r.info.applicationInfo, 
            knownToBeDead, "activity", r.intent.getComponent());
        mService.mH.sendMessage(msg);
    } finally {
    
    
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
}

Note 1that the call is actually ActivityManagerService.startProcessthe method, which starts to create a process:

// /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final class LocalService extends ActivityManagerInternal {
    
    
    @Override
    public void startProcess(String processName, ApplicationInfo info,
                             boolean knownToBeDead, String hostingType, 
                             ComponentName hostingName) {
    
    
        try {
    
    
            if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
    
    
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
                                 + processName);
            }
            synchronized (ActivityManagerService.this) {
    
    
                startProcessLocked(processName, info, knownToBeDead, 
                                   0 /* intentFlags */,
                                   new HostingRecord(hostingType, hostingName),
                                   false /* allowWhileBooting */, 
                                   false /* isolated */,
                                   true /* keepIfLarge */); // 1
            }
        } finally {
    
    
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
    }
    
    @GuardedBy("this")
    final ProcessRecord startProcessLocked(String processName,
                                           ApplicationInfo info, 
                                           boolean knownToBeDead, int intentFlags,
                                           HostingRecord hostingRecord, 
                                           boolean allowWhileBooting, 
                                           boolean isolated, boolean keepIfLarge) {
    
    
        return mProcessList.startProcessLocked(processName, info, knownToBeDead, 
                                               intentFlags,
                                               hostingRecord, allowWhileBooting, 
                                               isolated, 0 /* isolatedUid */, 
                                               keepIfLarge,
                                               null /* ABI override */, 
                                               null /* entryPoint */, 
                                               null /* entryPointArgs */,
                                               null /* crashHandler */); // 2
    }
}

1Call the method at the comment LocalService.startProcessLocked. In LocalService.startProcessLockedthe method, the work of process creation is delegated to ProcessList. Then look at ProcessList.startProcessLockedthe method:

// /frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@GuardedBy("mService")
final void startProcessLocked(ProcessRecord app, HostingRecord hostingRecord) {
    
    
    startProcessLocked(app, hostingRecord, null /* abiOverride */);
}

@GuardedBy("mService")
final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
                                 String abiOverride) {
    
    
    return startProcessLocked(app, hostingRecord, false /* disableHiddenApiChecks */,
                              false /* mountExtStorageFull */, abiOverride);
}

@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
                           boolean disableHiddenApiChecks, 
                           boolean mountExtStorageFull,
                           String abiOverride) {
    
    
    ...
    final String entryPoint = "android.app.ActivityThread"; // 1
    return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
                              runtimeFlags, mountExternal, seInfo, requiredAbi, 
                              instructionSet, invokeWith, startTime);
}

@GuardedBy("mService")
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
                                       boolean knownToBeDead, int intentFlags, 
                                       HostingRecord hostingRecord,
                                       boolean allowWhileBooting, boolean isolated, 
                                       int isolatedUid, boolean keepIfLarge,
                                       String abiOverride, String entryPoint, 
                                       String[] entryPointArgs, Runnable crashHandler) {
    
    
    if (!isolated) {
    
    
        app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
        checkSlow(startTime, "startProcess: after getProcessRecord");
        ...
    }
    final String entryPoint = "android.app.ActivityThread";
    ...
}

The function of these methods is to configure some necessary parameters before the process is created, such as version number and other parameters. In the comment 1is a very important parameter, entryPointwhich is the entry point of the new process. So, Androidthe program entry of the application is ActivityThread.

After the configuration of the parameters required to create a process is completed, it will eventually go to ZygoteProcessthe class:

private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
                                                  @Nullable final String niceName,
                                                  final int uid, final int gid,
                                                  @Nullable final int[] gids,
                                                  int runtimeFlags, int mountExternal,
                                                  int targetSdkVersion,
                                                  @Nullable String seInfo,
                                                  @NonNull String abi,
                                                  @Nullable String instructionSet,
                                                  @Nullable String appDataDir,
                                                  @Nullable String invokeWith,
                                                  boolean startChildZygote,
                                                  @Nullable String packageName,
                                                  boolean useUsapPool,
                                                  @Nullable String[] extraArgs)
   throws ZygoteStartFailedEx {
    
    
    synchronized (mLock) {
    
    
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                          useUsapPool, argsForZygote);
    }
}

At this time, it is still in system_serverthe process. The purpose of this class is to create a local Socketconnection object, connect to the method Zygoteof the process Socket, and then send the parameters needed to create the process through the character input stream.

Phase 2: ZygoteThe process receives the request and creates Launchera process

Refer to the application process startup process

Phase Three: Entry ActivityThread.main, Final Completion Launcher.onCreateOperations

Zygote forkExit Launcherthe process, and hand over the next Launcherstartup task ActivityThreadto , and then analyze the creation process from ActivityThread.mainthe method . LauncherThe following is the timing diagram for ActivityThreadstartup Activity:

ActivityThread starts Activity sequence diagram

ActivityThread.mainThe method is the program entry, the following is the relevant code:

// /frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
    
    
    ...
    Looper.prepareMainLooper();
	...
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq); // 1

    if (sMainThreadHandler == null) {
    
    
        sMainThreadHandler = thread.getHandler();
    }
	...  
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

1Call the method at the comment ActivityThread.attach, the following is the relevant source code:

// /frameworks/base/core/java/android/app/ActivityThread.java
@UnsupportedAppUsage
private void attach(boolean system, long startSeq) {
    
    
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
    
    
        ...
        final IActivityManager mgr = ActivityManager.getService(); // 1
        try {
    
    
            mgr.attachApplication(mAppThread, startSeq); // 2
        } catch (RemoteException ex) {
    
    
            throw ex.rethrowFromSystemServer();
        }
        ...
    } else {
    
    
        ...
    }
    ...
}

1Get ActivityManagerServicean instance of at the annotation and 2call ActivityManagerService.attachApplicationthe method at the annotation:

// /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
    
    
    if (thread == null) {
    
    
        throw new SecurityException("Invalid application interface");
    }
    synchronized (this) {
    
    
        // 通过 Binder 获取传入的 pid 信息
        int callingPid = Binder.getCallingPid(); 
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq); // 1
        Binder.restoreCallingIdentity(origId);
    }
}

public ActivityTaskManagerInternal mAtmInternal;
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
                                        int pid, int callingUid, long startSeq) {
    
    
    ...
    didSomething = mAtmInternal.attachApplication(app.getWindowProcessController()); // 2
    ...
}

1The method is called at the annotation ActivityManagerService.attachApplicationLocked. 2The at the comment mAtmInternalis ActivityTaskManagerInternala variable of type, ActivityTaskManagerServicethe internal class LocalServicein inherits from ActivityTaskManagerInternal, the following is the relevant source code:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
final class LocalService extends ActivityTaskManagerInternal {
    
    
    @HotPath(caller = HotPath.PROCESS_CHANGE)
    @Override
    public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
    
    
        synchronized (mGlobalLockWithoutBoost) {
    
    
            return mRootActivityContainer.attachApplication(wpc); // 1
        }
    }
}

1The method is called at the comment RootActivityContainer.attachApplication:

// frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean attachApplication(WindowProcessController app) throws RemoteException {
    
    
    final String processName = app.mName;
    boolean didSomething = false;
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
    
    
        final ActivityDisplay display = mActivityDisplays.get(displayNdx);
        final ActivityStack stack = display.getFocusedStack();
        if (stack != null) {
    
    
            stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
            final ActivityRecord top = stack.topRunningActivityLocked();
            final int size = mTmpActivityList.size();
            for (int i = 0; i < size; i++) {
    
    
                final ActivityRecord activity = mTmpActivityList.get(i);
                if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
                    && processName.equals(activity.processName)) {
    
    
                    try {
    
    
                        // 1
                        if (mStackSupervisor.realStartActivityLocked(activity, app,
                                                            top == activity /* andResume */, 
                                                                     true /* checkConfig */)) {
    
    
                            didSomething = true;
                        }
                    } catch (RemoteException e) {
    
    
                        Slog.w(TAG, "Exception in new application when starting activity "
                               + top.intent.getComponent().flattenToShortString(), e);
                        throw e;
                    }
                }
            }
        }
    }
    if (!didSomething) {
    
    
        ensureActivitiesVisible(null, 0, false /* preserve_windows */);
    }
    return didSomething;
}

1Call the method at the comment ActivityStackSupervisor.realStartActivityLocked:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
                                boolean andResume, boolean checkConfig) throws RemoteException {
    
    
	...
    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.icicle, r.persistentState, results, 
                         newIntents, dc.isNextTransitionForward(),
                         proc.createProfilerInfoIfNeeded(), r.assistToken)); // 1

	...
    // Schedule transaction.
    mService.getLifecycleManager().scheduleTransaction(clientTransaction); // 2 
	...
}

2The method at comment ActivityTaskManagerService.getLifecycleManagerreturns ClientLifecycleManagerthe instance. The following is ClientLifecycleManager.scheduleTransactionthe relevant source code:

// /frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    
    
    final IApplicationThread client = transaction.getClient();
    transaction.schedule(); // 1
    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(); 
    }
}

1The method is called at the comment ClientTransaction.schedule:

// /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
private IApplicationThread mClient; 
public void schedule() throws RemoteException {
    
    
    mClient.scheduleTransaction(this); // 1
}

1The in the comment mClientis IApplicationThreadan instance, here is ApplicationThreadthe internal class of , the following is the relevant source code ApplicationThread:ActivityThread

// /frameworks/base/core/java/android/app/ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
    
    
    @Override
    public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    
    
        ActivityThread.this.scheduleTransaction(transaction); // 1
    }
}

1The method is called in the comment ActivityThread.this.scheduleTransaction, ActivityThreadwhich is inherited from ClientTransactionHandler, so the method is called here ClientTransactionHandler.scheduleTransaction. The following is the relevant source code:

// /frameworks/base/core/java/android/app/ClientTransactionHandler.java
void scheduleTransaction(ClientTransaction transaction) {
    
    
    transaction.preExecute(this);
    sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); // 1
}

1The in the comment ActivityThread.His Handlera subclass of , the following is ActivityThread.sendMessagethe source code of the method and ActivityThread.H.EXECUTE_TRANSACTIONrelated processing about :

// /frameworks/base/core/java/android/app/ActivityThread.java
void sendMessage(int what, Object obj) {
    
    
    sendMessage(what, obj, 0, 0, false);
}

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    
    
    if (DEBUG_MESSAGES) {
    
    
        Slog.v(TAG,
               "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj);
    }
    Message msg = Message.obtain();
    msg.what = what;
    msg.obj = obj;
    msg.arg1 = arg1;
    msg.arg2 = arg2;
    if (async) {
    
    
        msg.setAsynchronous(true);
    }
    mH.sendMessage(msg);
}

class H extends Handler {
    
    
    ...
    public static final int EXECUTE_TRANSACTION = 159;
	...
    public void handleMessage(Message msg) {
    
    
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
    
    
            ...
            case EXECUTE_TRANSACTION:
                final ClientTransaction transaction = (ClientTransaction) msg.obj;
                mTransactionExecutor.execute(transaction); // 1
                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;
				...
        }
    }
}

method 1called at annotationTransactionExecutor.execute

// /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) {
    
    
    ...
    executeCallbacks(transaction); // 1

    executeLifecycleState(transaction);
    mPendingActions.clear();
    if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}

@VisibleForTesting
public void executeCallbacks(ClientTransaction transaction) {
    
    
    ...
    final int size = callbacks.size();
    for (int i = 0; i < size; ++i) {
    
    
        final ClientTransactionItem item = callbacks.get(i);
        ...
        item.execute(mTransactionHandler, token, mPendingActions); // 2
        ..
    }
}

2The method is called at the comment , which is implemented ClientTransactionItem.executein its subclass , the following is the method:LaunchActivityItemLaunchActivityItem.execute

// /frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java) 
@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);
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */); // 1
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

1The in the comment clientis ClientTransactionHandlera subclass of ActivityThread, view ActivityThread.handleLauncherActivitythe source code of , mainly calling ActivityThread.performLaunchActivitythe method:

// /frameworks/base/core/java/android/app/ActivityThread.java
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
                                     PendingTransactionActions pendingActions, 
                                     Intent customIntent) {
    
    
    ...
    WindowManagerGlobal.initialize();
    
	// 1 启动 Activity
    final Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
    
    
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        if (!r.activity.mFinished && pendingActions != null) {
    
    
            pendingActions.setOldState(r.state);
            pendingActions.setRestoreInstanceState(true);
            pendingActions.setCallOnPostCreate(true);
        }
    } else {
    
    
        // If there was an error, for any reason, tell the activity manager to stop us.
        try {
    
    
            // 停止 Activity 的启动
            ActivityTaskManager.getService()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
    
    
            throw ex.rethrowFromSystemServer();
        }
    }

    return a;
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    
    
    ActivityInfo aInfo = r.activityInfo; // 2 获取 ActivityInfo 类
    if (r.packageInfo == null) {
    
    
        // 3 获取 APK 文件描述类 LoadApk
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                                       Context.CONTEXT_INCLUDE_CODE); 
    }

    ComponentName component = r.intent.getComponent(); // 4
    ...
    // 5 创建要启动的 Activity 的上下文环境
    ContextImpl appContext = createBaseContextForActivity(r); 
    Activity activity = null;
    try {
    
    
        java.lang.ClassLoader cl = appContext.getClassLoader();
        // 6 用类加载器创建该 Activity 的实例
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
        ...
    } catch (Exception e) {
    
    
        ...
    }

    try {
    
    
        // 7 创建 Application
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        ...
        if (activity != null) {
    
    
            ...
            // 8 初始化 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,
                            r.assistToken);
            ...
            if (r.isPersistable()) {
    
    
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); // 9
            } else {
    
    
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            ...
        }
        ...
    } catch (SuperNotCalledException e) {
    
    
        throw e;

    } catch (Exception e) {
    
    
        ....
    }
    return activity;
}

The comment 1calls ActivityThread.performLaunchActivitythe method to start Activity. Comments are used to 2obtain ActivityInfoand store code and AndroidManifestset Activityand Receivernode information, for example, Activityand . Get the description class of the file at the comment . Obtain the class of the to be started at the comment , and save the package name and class name of the class in the class. Used at comments to create the context in which to start . According to the class name stored in the comment , use the class loader to create the instance of the . The comment is used to create , and the method will be called inside the method. Call the method initialization at the annotation , and the object ( ) will be created in the method and associated with itself. Call the method at the comment to start :themelaunchMode3APKLoadedApk4ActivityComponentNameComponentNameActivity5Activity6ComponentNameActivityActivity7ApplicationLoadedApk.makeApplicationApplication.onCreate8Activity.attachActivityActivity.attachWindowPhoneWindowActivity9Instrumentation.callActivityOnCreateActivity

// /frameworks/base/core/java/android/app/Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle,
                                 PersistableBundle persistentState) {
    
    
    prePerformCreate(activity);
    activity.performCreate(icicle, persistentState); // 1
    postPerformCreate(activity);
}

1The method is called at the comment Activity.performCreate, Activity.performCreateand the method is called in the method Activity.onCreate. At this point, the root Activityis started. The following is the relevant source code:

// /frameworks/base/core/java/android/app/Activity.java
@UnsupportedAppUsage
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    
    
    dispatchActivityPreCreated(icicle);
    mCanEnterPictureInPicture = true;
    restoreHasCurrentPermissionRequest(icicle);
    // 1
    if (persistentState != null) {
    
    
        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());
    dispatchActivityPostCreated(icicle);
}

@MainThread
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);

    if (mLastNonConfigurationInstances != null) {
    
    
        mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
    }
    if (mActivityInfo.parentActivityName != null) {
    
    
        if (mActionBar == null) {
    
    
            mEnableDefaultActionBarUp = true;
        } else {
    
    
            mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
        }
    }
    if (savedInstanceState != null) {
    
    
        mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
        mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID,
                                                    View.LAST_APP_AUTOFILL_ID);

        if (mAutoFillResetNeeded) {
    
    
            getAutofillManager().onCreate(savedInstanceState);
        }

        Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
        mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
                                   ? mLastNonConfigurationInstances.fragments : null);
    }
    mFragments.dispatchCreate();
    dispatchActivityCreated(savedInstanceState);
    if (mVoiceInteractor != null) {
    
    
        mVoiceInteractor.attachActivity(this);
    }
    mRestoredFromBundle = savedInstanceState != null;
    mCalled = true;

}

public void onCreate(@Nullable Bundle savedInstanceState,
                     @Nullable PersistableBundle persistentState) {
    
    
    onCreate(savedInstanceState);
}

reference

Android system startup to Launcher startup process analysis

Guess you like

Origin blog.csdn.net/xingyu19911016/article/details/128697566