Android系统启动(四) — Launcher 启动过程

news2024/11/28 16:50:52

1 Launcher 概述

系统启动的最后一步是启动一个应用程序来显示系统中已经安装的应用程序,这个应用程序就叫做 LauncherLauncher 在启动过程中会请求 PackageManagerService 返回系统中已经安装的应用程序信息,并将这些信息封装成一个快捷图标列表显示在系统屏幕上,这样用户就可以通过点击这些快捷图标来启动相应的应用程序。

通俗的讲,Launcher 就是 Android 系统的桌面, 它的作用主要有以下两点:

  • 作为 Android 系统的启动器,用于启动应用程序;
  • 作为 Android 系统的桌面,用于显示和管理应用程序的快捷图标或者其他桌面组件;

2 Launcher 启动过程

SystemServer 进程在启动的过程中会启动 PackageManagerServicePackageManagerService 启动后会将系统中的应用程序安装完成,在此之前已经启动的 ActivityManagerService 会将 Launcher 启动起来。

Launcher 的启动分为三个部分:

  • SystemServer 完成启动 Launcher Activity 的相关配置;
  • Zygote 进程 forkLauncher 进程;
  • 进入 ActivityThread.main 函数,最终完成 LauncheronCreate 操作;

第一阶段 完成 Launcher 的相关配置

图1

SystemServer.startOtherServices 方法中调用 ActivityManagerService.systemReady方法,Launcher 进程的启动就是从这里开始的,以下是相关源码:

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

以下是 ActivityManagerService.systemReady 方法的源码:

// /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
    ...
}

这里的 mAtmInternalActivityTaskManagerInternal 的实例,ActivityTaskManagerInternal 是一个抽象类。 ActivityManagerService 中的内部类 LocalService 实现了 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.startHomeOnAllDisplays 方法中调用了 RootActivityContainer.startHomeOnAllDisplays 方法。RootActivityContainer 的作用是,调用 PackageManagerService 中去查询手机系统中已经安装的应用哪一个符合 Launcher 标准,且返回一个 Intent 对象,并且交给 ActivityStarter

// /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;
}

在注释 2 处调用了 ActivityTaskManagerService.getHomeIntent() 方法来构建一个 categoryCATEGORY_HOMEIntent,表明是一个符合 Launcher 应用的 Intent。在注释 3 处通过调用 resolveHomeActivity 方法解析出需要启动 Activity 的信息。在注释 4 处调用 ActivityTaskManagerService.getActivityStartController() 获取 ActivityStartController,这个类的作用就是做启动前的各项检查,比如,Activity 是否有清单文件注册,Class 文件是否存在等,之后启动 Activity

以下是相关的时序图:

图2

首先,看一下 ActivityTaskManagerService.getHomeIntent() 方法,主要是构建一个符合 Launcher 应用的 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;
}     

在注释 1 处代表的是要启动 Activity 的意图,通常来说,整个系统只会有一个应用在清单文件中配置 CATEGORY_HOME,如果配置了多个,系统在启动的时候就会要求用户手动去选择哪一个应用作为启动应用,如果在系统设置应用中进行配置了,就会选择配置的那个应用。

接着看 RootActivityContainer.resolveIntentInternal 方法:

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

通过 Binder 跨进程通信通知 PackageManagerService 从系统所有已经安装的应用中找到一个符合 homeInentActivity

再看 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);
}

在注释 1 处先获取一个 ActivityStarter ,主要用于启动 Activity,然后把需要的参数设置进去,最后再调用它的 execute() 方法:

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

以下是 ActivityStarter.startActivity 的相关源码,这个方法主要是用来做 Activity 启动之前的安全校验:

// /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
    ...
}

注释 1 处调用了 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
    ...
}

注释 1 处的 ActivityStarter.computeLaunchingTaskFlags() 方法是根据 Activitylauncher modeintent.flag 计算出 Activity 的入栈方式。注释 2 处的 ActivityStarter.computeSourceStack() 计算从哪个栈中启动该 Activity。注释 3 处调用了 RootActivityContainer.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;
}

在注释 1 处调用 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
    }
    ...
}

在注释 1 处调用 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);
    }
}

注释 1 出调用的其实是 ActivityManagerService.startProcess 方法,开始创建进程:

// /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
    }
}

在注释 1 处调用 LocalService.startProcessLocked 方法。在 LocalService.startProcessLocked 方法中又把进程创建的工作委派给了 ProcessList。接着看 ProcessList.startProcessLocked 方法:

// /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";
    ...
}

这几个方法的作用是在进程创建之前,配置一些必要的参数,比如版本号之类的参数。在注释 1 处是一个非常重要的参数,entryPoint 是新进程的入口。所以,Android 应用的程序入口是 ActivityThread

创建进程所需的参数配置完成后,最终会走到 ZygoteProcess 类中:

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

此时还处于 system_server进程,这个类的目的是创建本地的 Socket 连接对象,连接到 Zygote 进程的 Socket 方法,然后通过字符输入流,把创建进程所需要的参数发送过去。

第二阶段:Zygote 进程 fork 一个 Launcher 进程的阶段

system_server 进程的 AMS 服务向 Zygote 进程发出 fork 出一个新进程的请求。由于 Zygote 进程在启动的时候会创建 Java 虚拟机,因此,通过 fork 创建出来的程序进程可以在内部获取一个 Java 虚拟机的实例拷贝。fork 采用 copy-on-write 机制,如果数据不发生变化,子进程和父进程可以共享一份数据,从而省去不少内存。

以下是 ZygoteInit.main 函数:

// /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
	...
    Runnable caller;
	...
    if (startSystemServer) {
        // Zygote fork 出的第一个进程是 system_server
        Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
		
        if (r != null) {
            r.run();
            return;
        }
    }
    ...
    // 循环等待 fork 出其他的应用进程,比如 Launcher,最终通过调用 processOneCommand 来进行进程的处理
    caller = zygoteServer.runSelectLoop(abiList);
    ...
    if (caller != null) {
        // 执行返回的 Runnable 对象,进入子进程
        caller.run();
    }
	...
}

Zygoteforksystem_server 进程,接着进入循环等待,用来接收 Socket 发来的消息,用来 fork 其他进程,比如 Launcher 进程。

// /frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
Runnable runSelectLoop(String abiList) {
    ...
    final Runnable command = connection.processOneCommand(this);
    ...
}

接着调用 ZygoteConnection.processOneCommand 方法:

// /frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
Runnable processOneCommand(ZygoteServer zygoteServer) {
    ...
    int pid = -1;
	...
    // fork 子进程,得到一个新的 pid
    pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
                                   parsedArgs.mRuntimeFlags, rlimits, 
                                   parsedArgs.mMountExternal, parsedArgs.mSeInfo,
                                   parsedArgs.mNiceName, fdsToClose, fdsToIgnore, 
                                   parsedArgs.mStartChildZygote,
                                   parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, 
                                   parsedArgs.mTargetSdkVersion);
	...
    try {
        if (pid == 0) {
            // in child
            zygoteServer.setForkChild();

            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;

            return handleChildProc(parsedArgs, descriptors, childPipeFd,
                                   parsedArgs.mStartChildZygote);
        } else {
            // In the parent. A pid < 0 indicates a failure and will be handled in
            // handleParentProc.
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            handleParentProc(pid, descriptors, serverPipeFd);
            return null;
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

通过调用 Zygote.forkAndSpecializeforkLauncher 进程,并执行 ZygoteConnection.handleChildProc 方法,进入子进程的处理:

// /frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
private Runnable handleChildProc(ZygoteArguments parsedArgs, 
                                 FileDescriptor[] descriptors, FileDescriptor pipeFd, 
                                 boolean isZygote) {
	...
    if (parsedArgs.mInvokeWith != null) {
        WrapperInit.execApplication(parsedArgs.mInvokeWith, parsedArgs.mNiceName, 
                                    parsedArgs.mTargetSdkVersion,
                                    VMRuntime.getCurrentInstructionSet(),
                                    pipeFd, parsedArgs.mRemainingArgs);

        // Should not get here.
        throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
    } else {
        if (!isZygote) {
            // APP 进程将会调用到这里,执行目标类的 main 方法
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                                         parsedArgs.mRemainingArgs, 
                                         null /* classLoader */); // 1
        } else {
            return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                                              parsedArgs.mRemainingArgs, 
                                              null /* classLoader */);
        }
    }

}
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
                                        ClassLoader classLoader) {
    if (RuntimeInit.DEBUG) {
        Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
    }

    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
    RuntimeInit.redirectLogStreams();

    RuntimeInit.commonInit();
    ZygoteInit.nativeZygoteInit();
    return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); // 1
}

进入子进程的操作,最终获得需要执行的 ActivityThread.main 方法,然后把之前传来的 android.app.ActivityThread 传递给 findStaticMain

// /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
                                          ClassLoader classLoader) {
    ...
    // Remaining arguments are passed to the start class's static main
    return findStaticMain(args.startClass, args.startArgs, classLoader);
}

通过反射,拿到 ActivityThread.main 方法:

// /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable findStaticMain(String className, String[] argv,
                                         ClassLoader classLoader) {
    Class<?> cl;

    try {
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
            "Missing class when invoking static main " + className,
            ex);
    }

    Method m;
    try {
        m = cl.getMethod("main", new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {
        throw new RuntimeException(
            "Missing static main on " + className, ex);
    } catch (SecurityException ex) {
        throw new RuntimeException(
            "Problem getting static main on " + className, ex);
    }

    int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
        throw new RuntimeException(
            "Main method is not public and static on " + className);
    }

    /*
           * This throw gets caught in ZygoteInit.main(), which responds
           * by invoking the exception's run() method. This arrangement
           * clears up all the stack frames that were required in setting
           * up the process.
           */
    return new MethodAndArgsCaller(m, argv); // 1
}

把反射得来的的 ActivityThread.main 入口返回给 ZygoteInit.main,通过 caller.run 进行调用:

// /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
static class MethodAndArgsCaller implements Runnable {
    /** method to call */
    private final Method mMethod;

    /** argument array */
    private final String[] mArgs;

    public MethodAndArgsCaller(Method method, String[] args) {
        mMethod = method;
        mArgs = args;
    }

    public void run() {
        try {
            // 调用 ActivityThread.main 
            mMethod.invoke(null, new Object[] { mArgs });
        } catch (IllegalAccessException ex) {
            throw new RuntimeException(ex);
        } catch (InvocationTargetException ex) {
            Throwable cause = ex.getCause();
            if (cause instanceof RuntimeException) {
                throw (RuntimeException) cause;
            } else if (cause instanceof Error) {
                throw (Error) cause;
            }
            throw new RuntimeException(ex);
        }
    }
}

到这里,就执行到了 ActivityThread.main 方法。

第三个阶段:进入 ActivityThread.main,最终完成 Launcher.onCreate 操作

Zygote fork 出了 Launcher 进程,并把接下来的 Launcher 启动任务交给了 ActivityThread 来进行,接下来就从 ActivityThread.main 方法来分析 Launcher 的创建过程:

// /frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
	...
    // 初始化 Looper
    Looper.prepareMainLooper();
	...
    ActivityThread thread = new ActivityThread();
    // 创建 Binder 通道(创建新线程)
    thread.attach(false, startSeq);
	...
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    ...
    // 主线程开始轮训,如果退出,程序关闭
    Looper.loop();
    ...
}

@UnsupportedAppUsage
private void attach(boolean system, long startSeq) {
    ...
    final IActivityManager mgr = ActivityManager.getService();
    try {
        mgr.attachApplication(mAppThread, startSeq);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
    ...
}

ActivityThread.attach 会一直调用 ActivityManaggerService.attachApplication 方法:

// /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);
    }
}
// /frameworks/base/core/java/android/app/ActivityThread.java
public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
        case BIND_APPLICATION:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
            AppBindData data = (AppBindData)msg.obj;
            handleBindApplication(data);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
            ...
    }
    ...
}

@UnsupportedAppUsage
private void handleBindApplication(AppBindData data) {
    ...
    mInstrumentation.callApplicationOnCreate(app);
    ...
}

调度 ActivityThread.Application,并调用了 Application.onCreate 方法,如下所示:

// /frameworks/base/core/java/android/app/Instrumentation.java
public void callApplicationOnCreate(Application app) {
    app.onCreate();
}

继续启动进程创建之前已经加入任务栈的那个 Activity,也就是 Launcher 应用的第一个 Activity

// /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
                                        int pid, int callingUid, long startSeq) {
	...
    boolean badApp = false;
    boolean didSomething = false;

    // See if the top visible activity is waiting to run in this process...
    if (normalMode) {
        try {
            didSomething = mAtmInternal.attachApplication(app.getWindowProcessController()); // 1
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
	...
}

注释 1 处的 mAtmInternalActivityTaskManagerInternal 类型的,这个方法的作用个就是启动 Launcher 应用的第一个 Activity。该方法的实现是在 ActivityTaskManagerService 中:

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

这里进一步交给了 RootActivityContainer;

// /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) {
            // 取出该任务栈中的所有 ActivityRecord,并存储到 mTmpActivityList 中
            stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
            // 取出栈顶的 Activity
            final ActivityRecord top = stack.topRunningActivityLocked();
            final int size = mTmpActivityList.size();
            for (int i = 0; i < size; i++) { // 遍历任务栈中的 Activity
                final ActivityRecord activity = mTmpActivityList.get(i);
                if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
                    && processName.equals(activity.processName)) {
                    try {
                        if (mStackSupervisor.realStartActivityLocked(activity, app,
								top == activity /* andResume */, 
                                 true /* checkConfig */)) { // 1
                            didSomething = true; // 只有该 Activity 是在栈顶,andResume 参数才为 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;
}

注释 1 处调用 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 {
    ...
    final ClientTransaction clientTransaction = ClientTransaction.obtain(
        proc.getThread(), r.appToken);

    final DisplayContent dc = r.getDisplay().mDisplayContent;
    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));

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

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

这里的 LauncherActivityItemResumeActivityItem 等是在 Android 10 的改动,把 Activity 的生命周期拆分成 ActivityLifecycleItem,根据不同的状态让不同的 ActivityLifecycleItem 去执行不同的 Activity 的生命周期,这种设计模式叫做状态机。状态机模式中,见过每一个条件的分支,放入一个独立的类中,去除过多的 if else 分支语句。

在注释 1 处,一旦执行了 ClientLifecycleManager.scheduleTransaction 开启了事务,就会调用到 LaunchActivityItem

class ClientLifecycleManager {
    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        transaction.schedule();
        if (!(client instanceof Binder)) {
            transaction.recycle();
        }
    }
}

一旦执行了 ClientLifecycleManager.scheduleTransaction 开启事务,就会调用 LaunchActivityItem.execute 方法,然后就会调用到 ActivityClientRecord.handleLaunchActivity 方法:

// /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 */);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

ClientTransactionHandlerActivityThread 的父类,是一个抽象类,所以直接去 ActivityThread 中去查看,在 ActivityThread.

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

这个方法就会去真正的启动 Activity,并且返回一个 Activity 对象。当得到这个 Activity 的实例对象之后,

// /frameworks/base/core/java/android/app/ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    activity.mCalled = false;
    if (r.isPersistable()) {
        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    } else {
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    ...
}

查看 Instrumentation.callActivityOnCreate 方法:

// /frameworks/base/core/java/android/app/Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle,
                                 PersistableBundle persistentState) {
    prePerformCreate(activity); // Activity onCreate 预处理
    activity.performCreate(icicle, persistentState); // 执行 onCreate
    postPerformCreate(activity); // Activity onCreate 创建后的一些信息处理
}

Instrumentation.prePerformCreate 方法:

// frameworks/base/core/java/android/app/Activity.java
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    ...
    if (persistentState != null) {
        onCreate(icicle, persistentState);
    } else {
        onCreate(icicle);
    }
    ...
}

同理,如果还往事务中添加了 ResumeActivityItem,相应的也会执行 Activity.onResume 生命周期。

参考

Android系统开机到Launcher启动流程分析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/166476.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阿里系-淘宝接口抓取及相关问题

阿里系-淘宝接口抓取 一、安装charlse抓包工具 官方下载地址 安装证书 二、安装xposed hook框架 Xponsed简介 具体安装步骤 三、安装模块 关闭阿里系ssl验证 开启http模式 支持支付宝、淘宝、淘宝直播各个接口抓取 四、效果如下 接下去一段时间更新阿里系相关接口 文章目录 一、…

搞技术的要不要学习财务知识

越是大型的集团或者企业&#xff0c;公司里面设立的部门就越多&#xff0c;也越细化&#xff0c;各部门之间既相互独立管理&#xff0c;又是相互的辅助支持&#xff0c;所以在工作中经常遇到这样的一个问题&#xff0c;就是做技术的要不要学习财务知识。这个问题其实就是把技术…

折半查找算法[二分查找法]算法的实现和解决整数溢出问题~

算法实现的要求&#xff1a; 折半查找法又称为二分查找法&#xff0c;这种方法对待查找的列表有两个要求&#xff1a; 1&#xff1a;必须采用顺序存储结构 2&#xff1a;必须按关键字大小有序排列算法思想&#xff1a; 将表中间位置记录的关键字与查找关键字进行比较&#x…

synchronized实现原理

0. 前言 造成线程安全问题的主要诱因有两点&#xff0c;一是存在共享数据(也称临界资源)&#xff0c;二是存在多个线程共同操作共享数据。因此为了解决线程安全问题&#xff0c;我们可能需要这样一个方案&#xff0c;当存在多个线程操作共享数据时&#xff0c;需要保证同一时刻…

ICV:2022年稀释制冷机全球市场规模达2.11亿美元,2028年有望出现突破点

全球前沿科技咨询机构ICV于2023年初发布了稀释制冷机&#xff08;DR&#xff09;的市场分析报告&#xff0c;ICV在报告中表示&#xff0c;2019-2015稀释制冷机的年均增长率达到8.59%以上&#xff0c;且增长率逐年上升。2022年全球稀释制冷机市场规模将达到2.11亿美元&#xff0…

从Deepmind最新成果DreamerV3启发的通用AI技术分析

一、背景 本文系个人观点&#xff1a;错漏在所难免&#xff0c;仅供参考 北京时间 1 月 12 日&#xff0c;DeepMind 官方推特发文&#xff0c;正式官宣 DreamerV3&#xff0c;这是首个能在游戏「我的世界」(Minecraft) 中不参考人类数据&#xff0c;就能从头开始收集钻石的通…

1.16中断实验

一.异常处理流程 1.异常处理流程 &#xff08;1&#xff09;保存现场&#xff08;CPU自动完成&#xff09; 将CPSR中状态保存到SPSR_<MODE>中 将CPSR寄存器的状态位T&#xff0c;改为ARM状态 根据需要&#xff0c;进制IRQ,FIQ中断&#xff0c;修改C…

java springboot 项目构建报错解决办法

这里总结了一些常见的springboot 项目构建报错及解决办法 错误: 无效的源发行版:17 错误原因 build.gradle 文件中可以通过下面两项来指定项目运行所需的jdk版本 sourceCompatibility:指定编译编译.java文件的jdk版本 targetCompatibility&#xff1a;确保class文件与target…

ARM 看门狗定时器

一、什么是看门狗、有什么用 (1) 看门狗定时器和普通的定时器并无本质区别。定时器可以设定一个时间&#xff0c;在这个时间完成之前定时器不断计时&#xff0c;时间到的时候&#xff0c;定时器会复位 CPU&#xff08;重启系统&#xff09;。 (2 )系统正常工作的时候当然不希望…

feign漫谈

feign的简单使用。 文章目录什么是feign准备工作三.如何使用3.1 定义pom文件3.2 定义配置文件及启动类注解3.3 定义feign接口什么是feign 远程调用框架 准备工作 需要nacos环境&#xff1a; 涉及到feign调用&#xff0c;就没法抛开注册中心&#xff0c;接下来我们使用主流的…

使用Python创建websocket服务端并给出不同客户端的请求

作者&#xff1a;虚坏叔叔 博客&#xff1a;https://xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; 使用Python创建websocket服务端&#xff0c;并给出不同客户端的请求 一、 WebSocket是啥 WebSocket 和HTTP一样&#xff0c;也是一种通…

java中的位运算符

在Java语言中&#xff0c;提供了7种位运算符&#xff0c;分别是按位与&#xff08;&&#xff09;、按位或&#xff08;|&#xff09;、按位异或&#xff08;^&#xff09;、取反(~)、左移(<<)、带符号右移(>>)和无符号右移(>>>)。位运算符是对long、i…

怎么把两个PDF合并成一个?这几种操作轻松合并

我们在工作中处理过的文件有很多&#xff0c;有时候为了工作更方便&#xff0c;我们通常需要把两个或是多个文件合并成为一个PDF文件&#xff0c;这样只需要打开这一个文件就可以查看全部内容&#xff0c;那么怎么把两个PDF合并成一个呢&#xff1f;这几种操作都可以轻松合并&a…

Dopamine-PEG-NH2氨基聚乙二醇多巴胺,材料改性用科研试剂

英 文 &#xff1a;NH2-PEG-Dopamine/Dopamine-PEG-NH2 中文&#xff1a;氨基聚乙二醇多巴胺 存储条件&#xff1a;-20C&#xff0c;避光&#xff0c;避湿 用 途&#xff1a;仅供科研实验使用&#xff0c;不用于诊治 外观: 固体或粘性液体&#xff0c;取决于分子量 注意事项…

javaEE 初阶 — 文件内容的读写

文章目录数据流1. 字节流1.1 InputStream 概述1.1.1 无参数 read 的使用1.1.2 一个参数 read 的使用1.2 使用 OutputStream 写文件1.2.1 对于关闭文件的解释2. 字符流2.1 Reader 概述2.1.1 read 方法的使用2.2 Writer 概述2.2.1 write 的使用2.3 Scanner 补充数据流 针对文件内…

Cookie和Session以及相关的方法

作者&#xff1a;~小明学编程 文章专栏&#xff1a;JavaEE 格言&#xff1a;热爱编程的&#xff0c;终将被编程所厚爱。 目录 Cookie 什么是Cookie? 为什么要用Cookie? Cookie的原理 Session 什么是Session? 为什么要用Session? Session原理 核心方法 实现用户登…

【Linux编译器】

前言 打怪升级第&#xff1a;22天 一、gcc、g 背景知识&#xff1a; gcc和g都是Linux中的编译器&#xff0c;其中gcc只可以编译C语言文件&#xff0c;g可以编译c文件&#xff0c;当然也可以编译C语言文件&#xff08;c兼容C语言嘛&#xff09;。 由于两者的操作选项基本一样&a…

转换函数和运算符类

我们以下是采用内联函数来进行的#ifndef ___Class_Counter #if 1 #endif ___Class_counter #include <climits> class Counter{unsigned cnt; // unsigned mmm; public:Counter() : cnt(0) {}//构造函数初始化器//Counter(double mmm):mmm(2){}/*void increment() {i…

低代码平台助力汽车行业构筑新基建

编者按&#xff1a;本文分析了汽车行业数字化转型的需求&#xff0c;并列举了汽车行业利用低代码平台数字化转型的场景&#xff0c;最后通过华晨汽车案例展示了低代码在实现业务模板集成方面的表现。关键词&#xff1a;数据集成&#xff0c;低代码平台&#xff0c;汽车行业汽车…

后台生成4位图像验证码

主要依赖&#xff1a; <dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version> </dependency>spring相关依赖参照用到的另行添加。 package com.math.controller;impor…