Android 10.0 Launcher 启动流程

在前面SystemUI启动流程中说到,在SystemServer中会去启动各种系统服务,这里的launcher也是启动的其中一个服务ActivityManagerService去启动的。在android10之前,系统四大组件的启动都是在ActivityManagerService中,在android10中,单独抽出了一个ActivityTaskManagerService,主要负责Activity的管理和调度。这里先来看下ActivityManagerService服务的启动:
frameworks/base/services/java/com/android/server/SystemServer.java

private void startBootstrapServices() {... ...// Activity manager runs the show.traceBeginAndSlog("StartActivityManager");// TODO: Might need to move after migration to WM.ActivityTaskManagerService atm = mSystemServiceManager.startService(ActivityTaskManagerService.Lifecycle.class).getService();mActivityManagerService = ActivityManagerService.Lifecycle.startService(mSystemServiceManager, atm);mActivityManagerService.setSystemServiceManager(mSystemServiceManager);mActivityManagerService.setInstaller(installer);mWindowManagerGlobalLock = atm.getGlobalLock();traceEnd();... ...
}

当SystemServiceManager调用 startService() 时,就会通过反射去创建传进去的class,然后在调用创建对象的 onStart() 方法,这里就是去初始化ActivityTaskManagerService和ActivityManagerService对象,并不会去启动launcher,而且系统服务启动分为三块:
frameworks/base/services/java/com/android/server/SystemServer.java

startBootstrapServices();   // 启动引导服务
startCoreServices();        // 启动核心服务
startOtherServices();       // 启动其他服务

在startOtherServices()中可以看到:
frameworks/base/services/java/com/android/server/SystemServer.java

private void startOtherServices() {... ...// We now tell the activity manager it is okay to run third party// code.  It will call back into us once it has gotten to the state// where third party code can really run (but before it has actually// started launching the initial applications), for us to complete our// initialization.mActivityManagerService.systemReady(() -> {... ...});
}

这就说明在所有服务初始化完成后,在这里会通知ActivityManagerService的systemReady()启动 launcher 的进程。
下面一起来看 launcher 是如何被启动起来的:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {... ...mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");... ...mAtmInternal.resumeTopActivities(false /* scheduleIdle */);... ...
}

mAtmInternal类型是ActivityTaskManagerInternal,这是一个抽象类,其实现是ActivityTaskManagerService的内部类LocalService:
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

final class LocalService extends ActivityTaskManagerInternal {... ...@Overridepublic boolean startHomeOnAllDisplays(int userId, String reason) {synchronized (mGlobalLock) {return mRootActivityContainer.startHomeOnAllDisplays(userId, reason);}}... ...@Overridepublic void resumeTopActivities(boolean scheduleIdle){synchronized (mGlobalLock){mRootActivityContainer.resumeFocusedStacksTopActivities();if(scheduleIdle){mStackSupervisor.scheduleIdleLocked();}}}... ...
}

这里的mRootActivityContainer类型是RootActivityContainer,按照文档上的说明,这是一个临时类,主要是将ActivityStackSupervisor.java中的一部分逻辑分离出来,在android11中,这个类就已经找不到了。替换成了RootWindowContainer,这里我们跟进 mRootActivityContainer.startHomeOnAllDisplays() 方法看,最终会调用到:startHomeOnDisplay() :
frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java

boolean startHomeOnDisplay(int userId,String reason,int displayId,boolean allowInstrumenting,boolean fromHomeKey){// Fallback to top focused display if the displayId is invalid.if(displayId==INVALID_DISPLAY){displayId=getTopDisplayFocusedStack().mDisplayId;}Intent homeIntent=null;ActivityInfo aInfo=null;if(displayId==DEFAULT_DISPLAY){//拿到需要启动launcher的intent,通过resolveHomeActivity解析出需要启动的ActivityhomeIntent=mService.getHomeIntent();aInfo=resolveHomeActivity(userId,homeIntent);}else if(shouldPlaceSecondaryHomeOnDisplay(displayId)){Pair<ActivityInfo, Intent> info=resolveSecondaryHomeActivity(userId,displayId);aInfo=info.first;homeIntent=info.second;}if(aInfo==null||homeIntent==null){return false;}if(!canStartHomeOnDisplay(aInfo,displayId,allowInstrumenting)){return false;}// Updates the home component of the intent.homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName,aInfo.name));homeIntent.setFlags(homeIntent.getFlags()|FLAG_ACTIVITY_NEW_TASK);// Updates the extra information of the intent.if(fromHomeKey){homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY,true);}// Update the reason for ANR debugging to verify if the user activity is the one that// actually launched.final String myReason=reason+":"+userId+":"+UserHandle.getUserId(aInfo.applicationInfo.uid)+":"+displayId;mService.getActivityStartController().startHomeActivity(homeIntent,aInfo,myReason,displayId);return true;
}

这里可以分为两步看:
  1、通过ActivityTaskManagerService的getHomeIntent()获取到需要启动的intent,在通过resolveHomeActivity()解析出需要启动Activity的信息,
  2、mService.getActivityStartController()获取到的是ActivityStartController,这个类的主要作用是用于控制委派启动的Activity。
先来看下ActivityTaskManagerService的getHomeIntent() :
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);}return intent;}

注意看 intent.addCategory(Intent.CATEGORY_HOME) ,这个代表的就是要启动Activity的意图,通常来说,整个系统的只会有一个应用会在清单文件中配置CATEGORY_HOME,如果配置了多个,系统在启动的时候就会要求用户手动去选择哪个作为启动应用,如果在系统设置应用中进行配置了,就会选择配置的那个应用启动。(这个 CATEGORY_HOME 配置,说白了就只有 launcher 程序才会有)。
回到主线,接着看mService.getActivityStartController().startHomeActivity() :
frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java

    void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,TaskDisplayArea taskDisplayArea) {final ActivityOptions options = ActivityOptions.makeBasic();options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);if (!ActivityRecord.isResolverActivity(aInfo.name)) {// The resolver activity shouldn't be put in home stack because when the foreground is// standard type activity, the resolver activity should be put on the top of current// foreground instead of bring home stack to front.options.setLaunchActivityType(ACTIVITY_TYPE_HOME);}final int displayId = taskDisplayArea.getDisplayId();options.setLaunchDisplayId(displayId);options.setLaunchTaskDisplayArea(taskDisplayArea.mRemoteToken.toWindowContainerToken());// The home activity will be started later, defer resuming to avoid unneccerary operations// (e.g. start home recursively) when creating home stack.mSupervisor.beginDeferResume();final ActivityStack homeStack;try {// Make sure home stack exists on display area.homeStack = taskDisplayArea.getOrCreateRootHomeTask(ON_TOP);} finally {mSupervisor.endDeferResume();}mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason).setOutActivity(tmpOutRecord).setCallingUid(0).setActivityInfo(aInfo).setActivityOptions(options.toBundle()).execute();mLastHomeActivityStartRecord = tmpOutRecord[0];if (homeStack.mInResumeTopActivity) {// If we are in resume section already, home activity will be initialized, but not// resumed (to avoid recursive resume) and will stay that way until something pokes it// again. We need to schedule another resume.mSupervisor.scheduleResumeTopActivities();}}/*** @return A starter to configure and execute starting an activity. It is valid until after*         {@link ActivityStarter#execute} is invoked. At that point, the starter should be*         considered invalid and no longer modified or used.*/ActivityStarter obtainStarter(Intent intent, String reason) {return mFactory.obtain().setIntent(intent).setReason(reason);}

这里主要是先获取一个ActivityStarter(主要用于启动Activity),然后把需要的参数设置进去,最后再调用它的ActivityStarter.execute()方法:
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

int execute() {try {... ...final LaunchingState launchingState;synchronized (mService.mGlobalLock) {final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo);// 通过ActivityMetricsLogger.notifyActivityLaunching创建LaunchingState并记录创建Activity开始的时间launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mRequest.intent, caller);}... ...// 执行启动请求res = executeRequest(mRequest);... ...// Notify ActivityMetricsLogger that the activity has launched.// ActivityMetricsLogger will then wait for the windows to be drawn and populate// WaitResult.// 通过ActivityMetricsLogger.notifyActivityLaunched记录Activity启动完成的时间mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,mLastStartActivityRecord);// 同时将Request.waitResult添加到ActivityStackSupervisor的mWaitingActivityLaunched中,等待窗口绘制完成return getExternalResult(mRequest.waitResult == null ? res: waitForResult(res, mLastStartActivityRecord));        } finally {onExecutionComplete();}}

通过上面代码我们知道,启动是在 executeRequest() 方法里:
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

    private int executeRequest(Request request) {... ...//调用 startActivityUncheckedmLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,restrictedBgActivity, intentGrants);return mLastStartActivityResult;}

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, Task inTask,boolean restrictedBgActivity, NeededUriGrants intentGrants) {int result = START_CANCELED;... ...try {//延时布局mService.deferWindowLayout();//执行startActivityInnerresult = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);} finally {//恢复布局mService.continueWindowLayout();}... ...return result;}

ActivityStarter.startActivityInner()
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

int startActivityInner() { ... ...if (mDoResume) {//ActivityRecord 记录着 Activity 信息final ActivityRecord topTaskActivity =mStartActivity.getTask().topRunningActivityLocked();if (!mTargetStack.isTopActivityFocusable()|| (topTaskActivity != null && topTaskActivity.isTaskOverlay()&& mStartActivity != topTaskActivity)) {mTargetStack.getDisplay().mDisplayContent.executeAppTransition();} else {//执行resumeFocusedStacksTopActivitiesmRootWindowContainer.resumeFocusedStacksTopActivities(mTargetStack, mStartActivity, mOptions);}}... ...return START_SUCCESS;}

RootWindowContainer.resumeFocusedStacksTopActivities()
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

boolean resumeFocusedStacksTopActivities(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {... ...//如果是栈顶Activity,启动resumeTopActivityUncheckedLockedif (targetStack != null && (targetStack.isTopStackInDisplayArea()|| getTopDisplayFocusedStack() == targetStack)) {result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);}... ...if (!resumedOnDisplay) {//获取栈顶的 ActivityRecordfinal ActivityStack focusedStack = display.getFocusedStack();if (focusedStack != null) {//执行resumeTopActivityUncheckedLockedresult |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);}else if (targetStack == null) {result |= resumeHomeActivity(null /* prev */, "no-focusable-task",display.getDefaultTaskDisplayArea());}}return result;
}

ActivityStack.resumeTopActivityUncheckedLocked()
frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {if (mInResumeTopActivity) {// Don't even start recursing.return false;}boolean result = false;try {mInResumeTopActivity = true;// 执行 resumeTopActivityInnerLocked,// 最终调用到 ActivityStackSupervisor.startSpecificActivity()result = resumeTopActivityInnerLocked(prev, options);final ActivityRecord next = topRunningActivity(true /* focusableOnly */);if (next == null || !next.canTurnScreenOn()) {checkReadyForSleep();}} finally {mInResumeTopActivity = false;}return result;}

ActivityStackSupervisor.startSpecificActivity()
frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java

    void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {// Is this activity's application already running?final WindowProcessController wpc =mService.getProcessController(r.processName, r.info.applicationInfo.uid);boolean knownToBeDead = false;//进程存在if (wpc != null && wpc.hasThread()) {try {//真正启动Activity方法realStartActivityLocked(r, wpc, andResume, checkConfig);return;} catch (RemoteException e) {Slog.w(TAG, "Exception when starting activity "+ r.intent.getComponent().flattenToShortString(), e);}// If a dead object exception was thrown -- fall through to// restart the application.knownToBeDead = true;}r.notifyUnknownVisibilityLaunchedForKeyguardTransition();final boolean isTop = andResume && r.isTopRunningActivity();//进程不存在 mService =ATMSmService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");}

startSpecificActivity() 这个方法是关键方法,如果进程已经存在直接执行 realStartActivityLocked 去启动 Activity,进程不存在则通过AMS去创建 Socket,然后通知 Zygote 去 fork 进程。由于这里第一次创建,所以会走到 startProcessAsync() 。
Launcher启动流程调用栈:

创建Socket建立连接
ActivityTaskManagerService.startProcessAsync()
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

    void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,String hostingType) {try {if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"+ activity.processName);}// Post message to start process to avoid possible deadlock of calling into AMS with the// ATMS lock held.final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,isTop, hostingType, activity.intent.getComponent());mH.sendMessage(m);} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}}

通过handler发消息执行ActivityManagerInternal.startProcess() ,内部又转调用ActivityManagerService.startProcessLocked() :
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,ApplicationInfo info, boolean knownToBeDead, int intentFlags,HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,boolean isolated, boolean keepIfLarge) {return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,keepIfLarge, null /* ABI override */, null /* entryPoint */,null /* entryPointArgs */, null /* crashHandler */);
}

mProcessList类型是ProcessList,这是一个进程管理类,描述了进程的adj值,当系统资源吃紧时,就会根据这里描述的adj去判断杀死哪个应用来释放资源,可以通过adb shell dumpsys meminfo来查看当前所有进程的分类情况,接着来看下ProcessList.startProcessLocked():
frameworks/base/services/core/java/com/android/server/am/ProcessList.java

    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) {ProcessRecord app;... ...checkSlow(startTime, "startProcess: stepping in to startProcess");final boolean success = startProcessLocked(app, hostingRecord, abiOverride);checkSlow(startTime, "startProcess: done starting proc!");return success ? app : null;}boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,boolean disableHiddenApiChecks, boolean mountExtStorageFull,String abiOverride) {... ...try {... ...// Start the process.  It will either succeed and return a result containing// the PID of the new process, or else throw a RuntimeException.final String entryPoint = "android.app.ActivityThread";return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,startTime);} catch (RuntimeException e) {Slog.e(ActivityManagerService.TAG, "Failure starting process " + app.processName, e);// Something went very wrong while trying to start this process; one// common case is when the package is frozen due to an active// upgrade. To recover, clean up any active bookkeeping related to// starting this process. (We already invoked this method once when// the package was initially frozen through KILL_APPLICATION_MSG, so// it doesn't hurt to use it again.)mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),false, false, true, false, false, app.userId, "start failure");return false;}}boolean startProcessLocked(HostingRecord hostingRecord,String entryPoint,ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,String seInfo, String requiredAbi, String instructionSet, String invokeWith,long startTime) {... ...final Process.ProcessStartResult startResult = startProcess(app.hostingRecord,entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal,app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime);... ...}private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,String seInfo, String requiredAbi, String instructionSet, String invokeWith,long startTime) {try {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +app.processName);checkSlow(startTime, "startProcess: asking zygote to start proc");final Process.ProcessStartResult startResult;if (hostingRecord.usesWebviewZygote()) {... ...} else if (hostingRecord.usesAppZygote()) {final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);startResult = appZygote.getProcess().start(entryPoint,app.processName, uid, uid, gids, runtimeFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, null, app.info.packageName,/*useUsapPool=*/ false,new String[] {PROC_START_SEQ_IDENT + app.startSeq});} else {... ...}checkSlow(startTime, "startProcess: returned from zygote!");return startResult;} finally {Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}}

这里有几个我们需要关注的点,一个是第二个方法定义的entryPoint=“android.app.ActivityThread”,这个就是后面创建进程时会通过反射调用到的类,再来看最后一个方法,这里会执行else if语句,也就是执行ZygoteProcess的start()方法。最终到 ZygoteProcess 的attemptUsapSendArgsAndGetResult 通过 Socket 通信,fork 一个新的 Launcher 进程,调用过程如图:

ZygoteProcess.attemptZygoteSendArgsAndGetResult()
frameworks/base/core/java/android/os/ZygoteProcess.java

    private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {try {final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;zygoteWriter.write(msgStr);把应用进程的一些参数写给前面连接的zygote进程zygoteWriter.flush();//进入Zygote进程,处于阻塞状态//从socket中得到zygote创建的应用pid,赋值给 ProcessStartResult的对象Process.ProcessStartResult result = new Process.ProcessStartResult();result.pid = zygoteInputStream.readInt();result.usingWrapper = zygoteInputStream.readBoolean();return result;} catch (IOException ex) {zygoteState.close();}}

Zygote进程处理
ZygoteInit.main
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {Runnable caller;if (startSystemServer) {//Zygote Fork出的第一个进程 SystmeServerRunnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);if (r != null) {r.run();return;}}//循环等待fork出其他的应用进程,比如Launchercaller = zygoteServer.runSelectLoop(abiList);...if (caller != null) {caller.run(); //执行runSelectLoop返回的Runnable对象,进入子进程}
}

ZygoteServer.runSelectLoop
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

Runnable runSelectLoop(String abiList) {while (true) {int pollReturnValue;try {//epoll机制 循环pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);} catch (ErrnoException ex) {throw new RuntimeException("poll failed", ex);}...//来了消息后,调用processOneCommand()来进行进程的处理final Runnable command =  connection.processOneCommand(this);} 
}

ZygoteConnection.processOneCommand
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

Runnable processOneCommand(ZygoteServer zygoteServer) {//fork进程,得到新进程pid//pid=0 表示Zygote  fork子进程成功//pid > 0 表示子进程 的真正的PIDpid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList,parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);try {//fork成功,第一次返回的pid = 0if (pid == 0) {return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);} else {handleParentProc(pid, serverPipeFd);return null;}
}

ZygoteConnection.handleChildProc
这里主要执行到 ZygoteInit.zygoteInit,zygoteInit 进行一些环境的初始化、启动Binder进程等操作,最终反射执行 ActivityThread.main
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

    private Runnable handleChildProc(ZygoteArguments parsedArgs,FileDescriptor pipeFd, boolean isZygote) {closeSocket();Zygote.setAppProcessName(parsedArgs, TAG);if (!isZygote) {//App进程将会调用到这里,最终反射执行ActivityThread.mainreturn ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, null /* classLoader */);} else {return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mRemainingArgs, null /* classLoader */);}}

Zygote进程调用栈:

ActivityThread中处理
Zygote fork出了 Launcher 的进程,并把接下来的 Launcher 启动任务交给了 ActivityThread 来进行,接下来我们就从 ActivityThread.main方法来分析 Launcher 的创建过程。
frameworks/base/core/java/android/app/ActivityThread.java

    public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");... ...//创建主线程LooperLooper.prepareMainLooper();... ...ActivityThread thread = new ActivityThread();//执行attach... ...thread.attach(false, startSeq);//开启循环... ...Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}

这里就是android层面划分为一个应用进程的开始,初始化一个looper,也就是android中说的主线程,并开始looper循环,这里调用到了ActivitThread.attach() :
frameworks/base/core/java/android/app/ActivityThread.java

    private void attach(boolean system, long startSeq) {sCurrentActivityThread = this;mSystemThread = system;if (!system) {... ...// 这里会拿到ActivityManagerService的代理final IActivityManager mgr = ActivityManager.getService();try {//应用的句柄发给AMS,从而使AMS可以管理新进程mgr.attachApplication(mAppThread, startSeq);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}... ...} else {// 在前面讲Zygote进程的时候,里面创建ActivityThread就会执行到这里}//当系统配置发生变更时会执行这个回调ViewRootImpl.ConfigChangedCallback configChangedCallback= (Configuration globalConfig) -> {... ...};ViewRootImpl.addConfigCallback(configChangedCallback);}

这里会执行if语句里面的内容,mAppThread的类型是ApplicationThread,这个类的主要作用是在ActivityManagerService中回调回ActivityThread中来,mgr是ActivityManagerService的代理,在执行它的ActivityManagerService.attachApplication() 方法:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

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

ActivityManagerService.attachApplicationLocked()
调用AMS的 attachApplication(),最终层层调用到 ActivityStackSupervisor 的 realStartActivityLocked,真正准备去启动Activity。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    private final boolean attachApplicationLocked(IApplicationThread thread,int pid, int callingUid, long startSeq) {... ...//这里会去调用ActivityThrea的bindApplication(),也就是会去创建Applicationthread.bindApplication(... ...)... ...//如果当前的Application记录仍然依附到之前的进程中,则清理掉if (app.thread != null) {handleAppDiedLocked(app, true, true);}... ...// See if the top visible activity is waiting to run in this process...if (normalMode) {try {//调用ActivityTaskManagerService的attachApplication(),最终层层调用到ActivityStackSupervisor.java的 realStartActivityLocked()didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());} catch (Exception e) {Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);badApp = true;}}... ...}

这里通过AMS最终会调用到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 {//确保所有的Activity执行了onPause才会往下继续执行if (!mRootActivityContainer.allPausedActivitiesComplete()) {// While there are activities pausing we skipping starting any new activities until// pauses are complete. NOTE: that we also do this for activities that are starting in// the paused state because they will first be resumed then paused on the client side.if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,"realStartActivityLocked: Skipping start of r=" + r+ " some activities pausing...");return false;}... ...try {... ...try{... ...// Create activity launch transaction.final ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.appToken);final DisplayContent dc = r.getDisplay().mDisplayContent;//在回调序列的末尾添加一条消息clientTransaction.addCallback(LaunchActivityItem.obtain(... ...));// Set desired final state.final ActivityLifecycleItem lifecycleItem;if (andResume) {lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());} else {lifecycleItem = PauseActivityItem.obtain();}//添加最后执行的生命周期状态clientTransaction.setLifecycleStateRequest(lifecycleItem);// 这里其实就是执行ClientTransaction的schedule()方法mService.getLifecycleManager().scheduleTransaction(clientTransaction);... ...} catch (RemoteException e) {if (r.launchFailed) {// 第二次启动失败,finish activity并放弃启动Slog.e(TAG, "Second failure launching "+ r.intent.getComponent().flattenToShortString() + ", giving up", e);proc.appDied();stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,"2nd-crash", false);return false;}//第一次启动失败,尝试重启进程r.launchFailed = true;proc.removeActivity(r);throw e;}} finally {endDeferResume();}... ...return true;}

ActivityThread调用栈:

小结

至此已经走到 realStartActivityLocked,接下来就是 Activity 的启动流程,Activity 启动下篇文章会单独分析。总结一下 Launcher 启动流程,Launcher的启动经过了三个阶段:
  1、SystemServer 创建AMS和ATMS,通过 SystemReady 进入 LauncherActivity 的调用
  2、Zygote 进程 fork 出 Launcher 进程,通过 Socket 进行通信
  3、进入 ActivityThread 的处理,完成 Launcher 的 Acitivty 启动

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最短路问题中的朴素版Dijkstra算法

最短路问题的朴素版Dijkstra算法 题目 最短路问题需要用到下面的算法&#xff08;n代表点的数量&#xff0c;m代表边的数量&#xff09; 朴素版和堆优化版的Dijkstra算法的区别是&#xff0c;朴素版比较适合稠密图&#xff0c;堆优化版适合稀疏图&#xff0c;稠密图代表它的边…

python | TypeError: list indices must be integers or slices, not tuple

python | TypeError: list indices must be integers or slices, not tuple 在Python编程中&#xff0c;TypeError: list indices must be integers or slices, not tuple 是一个常见的错误。此错误通常发生在尝试使用非整数&#xff08;如元组&#xff09;作为列表索引时。本…

RK3568笔记四十九:W25Q64驱动开发(硬件SPI1)

若该文为原创文章&#xff0c;转载请注明原文出处。 一、SPI介绍 串行外设接口 (Serial Peripheral interface) 简称 SPI&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并 且在芯片的管脚上只占用四根线&#xff0c;节约了芯片的管脚。 …

Python写UI自动化--playwright(在UI元素上悬停)

要在UI元素上执行鼠标悬停&#xff08;hover&#xff09;动作&#xff0c;可以使用page.hover()方法。这个方法使鼠标指针移动到指定的元素上&#xff0c;就像用户将鼠标悬停在该元素上一样。这对于触发那些依赖于鼠标悬停事件的行为&#xff08;如显示下拉菜单、提示框或其他动…

[极客大挑战 2019]PHP1

打开题目 游戏界面 猜测php里面有文件&#xff0c;我们可以用dirsearch 扫描一下这个服务器 执行命令 dirsearch -u http://2999dfd5-1d43-4a81-a088-9e41c9dccab4.node4.buuoj.cn/ -e php > test.log 最后在log文件中找到一个 200 www.zip 浏览器输入payload下载下来 …

操作系统_内存管理学习心得

1. 操作系统结构 1.1 内核 计算机是由各种外部硬件设备组成的,比如内存、cpu、 硬盘等,如果每个应用都要和这些硬件设备对接通信协议&#xff0c;那这样太累了&#xff0c;所以这个中间人就由内核来负责,让内核作为应用连接硬件设备的桥梁,应用程序只需关心与内核交写&#x…

C++ | Leetcode C++题解之第283题移动零

题目&#xff1a; 题解&#xff1a; class Solution { public:void moveZeroes(vector<int>& nums) {int n nums.size(), left 0, right 0;while (right < n) {if (nums[right]) {swap(nums[left], nums[right]);left;}right;}} };

SpringBoot集成GraalVM创建高性能原生镜像

1. GraalVM 原生镜像的介绍 GraalVM原生镜像为部署和运行Java应用程序提供了一种新的方式。与Java虚拟机相比&#xff0c;原生镜像可以以更小的内存占用和更快的启动时间运行。 它们非常适用于使用容器镜像部署的应用程序&#xff0c;当与 "功能即服务"&#xff08…

短剧系统源码分享,快速搭建部署上线教程

一、短剧系统是什么&#xff1f; 短剧制作平台&#xff0c;作为一站式综合解决方案&#xff0c;集剧本创作、角色设计、场景搭建、视频编辑、便捷发布及深度数据分析能力于一身。该平台精准定位于助力企业利用短剧形式强化品牌传播力并驱动商业价值增长&#xff0c;无论企业是…

什么是IO多路复用?其原理和用途是什么?

什么是IO&#xff1f; IO&#xff1a;Input/Output&#xff0c;即数据的读取&#xff08;接收&#xff09;/写入&#xff08;发送&#xff09;操作&#xff0c;针对不同的数据存储媒介&#xff0c;大致可以分为网络 IO 和磁盘 IO 两种。在 Linux 系统中&#xff0c;为了保证系…

关于Excel表格隔行取列的方法

关于Excel表格隔行取列的方法 1、场景显示2、参考文章 1、场景显示 ①处的公式&#xff1a; INDEX($B3:$G3,(COLUMN(A1)*2)) $B与$G可以限制列不变&#xff1b; COLUMN(A1)返回1&#xff1b; 含义&#xff1a; 在选定区域选择偶数列的数据&#xff1b; 如果是奇数列的话是(COL…

查看RAM和Flash

0 Preface/Foreword 1 查看方法 1.1 map文件中查看 1.1.1 RAM可用情况 在map文件中&#xff0c;搜索字符串&#xff1a;free_ramcp 该字段表示剩余可用的RAM大小&#xff0c;前面对应的是hexadecimal的数值&#xff08;单位Byte&#xff09;&#xff0c;就是剩余可用的RA…

乱弹篇(39)请珍惜懂你的人

今日清晨&#xff0c;笔者照常去到古镇味江河畔垂钓&#xff0c;呼吸着凉爽晨风轻轻吹拂而来的大自然氧吧生产出的优质氧气......忽地&#xff0c;记起已经许久未履行义务了&#xff0c;所以本“人民体验官”今天要推广人民日报官方微博文化产品《有个真朋友是一生的福气》。 截…

Redis:十大数据类型

键&#xff08;key&#xff09; 常用命令 1. 字符串&#xff08;String&#xff09; 1.1 基本命令 set key value 如下&#xff1a;设置kv键值对&#xff0c;存货时长为30秒 get key mset key value [key value ...]mget key [key ...] 同时设置或者获取多个键值对 getrange…

实验21.实现 printf

已完成实验 已完成实验链接 简介 实验 21. 实现 printf 总结 简化系统调用和中断&#xff0c;用 eax 代表调用号参数&#xff0c;ebx,ecx,edx 来代表参数(syscall.c kernel.s) 添加 write 的系统调用接口(syscall.c, syscall-init.c, print.s) 注意&#xff1a;要更改 p…

基于N32L406MB EasyFlash参数(key-value)记录库移植

EasyFlash 感谢作者的分享https://github.com/armink/EasyFlash EasyFlash是一款开源的轻量级嵌入式Flash存储器库&#xff0c;方便开发者更加轻松的实现基于Flash存储器的常见应用开发 三大实用功能 ENV快速保存产品参数(key-value)&#xff0c;支持 写平衡&#xff08;磨…

最小例程上加OLED显示

最小例程上加OLED显示 本工程代码链接: https://ww0.lanzoul.com/i8lNa265gj7g 失效联系:qq2958360390 我们其实就加上这几个文件, 然后会调用就可以了, 具体的就看江协科技的OLED, 讲的很清楚, 我们这里只说应用, 我们的重点在使用. 下面跟着我来, 复制黏贴: 更详细请看哔哩…

从零开始学习机器学习,掌握AI未来的关键!

从零开始学习机器学习 1. 介绍1.1 人工智能&#xff08;AI&#xff09;概述1.2 机器学习在人工智能中的应用1.3 机器学习基础概念 2. 监督学习2.1 什么是监督学习2.2 回归分析2.3 分类问题2.4 模型评估和选择 3. 无监督学习3.1 什么是无监督学习3.2 聚类算法3.3 降维技术 4. 深…

(39)智能电池

文章目录 前言 1 通过任务规划器进行设置 2 补充信息 3 限制条件 4 参数说明 前言 虽然还不是很普遍&#xff0c;但智能电池更容易从飞行器上安装和拆卸&#xff0c;并且能够提供更多关于电池状态的信息&#xff0c;包括容量、单个电池电压、温度等。 ArduPilot 支持几种…

qt的信号槽连接成功,但是就是无法触发槽函数。你必须使用connect的第5个参数,Qt::QueuedConnection

signals:void sends(); public slots:void sl();//这种是默认自动连接&#xff0c;故第五个参数不用写connect(this,&MainWindow::sends,this,&MainWindow::sl);emit sends();void sl() {}如果connect连接成功&#xff0c;但是无法触发槽函数。你应该使用第五个参数&…