当前位置: 首页 > news >正文

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 启动

相关文章:

Android 10.0 Launcher 启动流程

在前面SystemUI启动流程中说到&#xff0c;在SystemServer中会去启动各种系统服务&#xff0c;这里的launcher也是启动的其中一个服务ActivityManagerService去启动的。在android10之前&#xff0c;系统四大组件的启动都是在ActivityManagerService中&#xff0c;在android10中…...

OPenCV高级编程——OpenCV视频读写及录制技术详解

目录 引言 一、视频读取技术 VideoCapture 类 构造函数 常用方法 二、视频写入技术 VideoWriter 类 构造函数 常用方法 三、视频录制技术 1. 包含OpenCV头文件 2. 初始化VideoCapture对象 3. 设置视频编码器 4. 读取和写入视频帧 5. 释放资源 6. 编码格式选择 …...

jenkins获取sonarqube质量门禁结果

前景 在使用 Jenkins 集成 SonarQube 时&#xff0c;获取质量门禁&#xff08;Quality Gate&#xff09;结果非常重要。SonarQube 的质量门禁是一种质量控制机制&#xff0c;用于评估代码质量是否符合预设的标准。以下是获取质量门禁结果的意义和作用&#xff1a; 评估代码质量…...

【AI-12】浅显易懂地说一下损失函数

什么是损失函数&#xff1f; 咱们可以把损失函数想象成一个衡量你做的事情“好不好”的尺子。 比如说你在预测明天的天气&#xff0c;你给出的预测结果和实际的天气情况之间会有差别。损失函数就是用来计算这个差别有多大的。 如果你的预测结果和实际情况非常接近&#xff0c;…...

Python和java中super的使用用法(有点小语法上的差距,老忘就在这里置顶了)

文章目录 1 在 Java 中&#xff1a;2 在 Python 中&#xff1a; 在 Java 和 Python 中&#xff0c;子类调用父类方法的语法略有不同&#xff1a; 1 在 Java 中&#xff1a; 使用 super 关键字&#xff1a;在子类中&#xff0c;可以使用 super 关键字来调用父类的方法。super …...

在 QML 中使用 C++ 类和对象

1.实现 C 类&#xff0c;从 QObject 或 QObject 的派生类继承 类中第一行添加 Q_OBJECT 宏 2.修饰成员函数或属性 Q_INVOKABLE 宏用来定义可通过元对象系统访问的方法 Q_PROPERTY 宏用来定义可通过元对象系统访问的属性 信号或者槽&#xff0c;都可以直接在 QML 中访问 3. 在…...

什么是接口?

在前后端开发的语境中&#xff0c;接口&#xff08;Interface&#xff09;是一个非常重要的概念&#xff0c;它充当了前端&#xff08;通常是浏览器端或移动端应用&#xff09;与后端&#xff08;通常是服务器端的应用程序&#xff09;之间进行数据交换的桥梁。接口定义了双方交…...

传统自然语言处理(NLP)与大规模语言模型(LLM)详解

自然语言处理&#xff08;NLP&#xff09;和大规模语言模型&#xff08;LLM&#xff09;是理解和生成人类语言的两种主要方法。本文将介绍传统NLP和LLM的介绍、运行步骤以及它们之间的比较&#xff0c;帮助新手了解这两个领域的基础知识。 传统自然语言处理&#xff08;NLP&…...

实现Obsidian PC端和手机端(安卓)同步

步骤 1&#xff1a;在PC端设置Obsidian 安装Obsidian和Git&#xff1a;确保你的PC上已经安装了Obsidian和Git。你可以从Obsidian官网和Git官网下载并安装。 克隆GitHub代码库&#xff1a;在PC上打开命令行&#xff08;例如Windows的命令提示符或Mac/Linux的终端&#xff09;&a…...

基于大模型的 Agent 进行任务规划的10种方式

基于大模型的 Agent 基本组成应该包含规划&#xff08;planning)&#xff0c;工具&#xff08;Tools)&#xff0c;执行(Action)&#xff0c;和记忆(Memory)四个方面&#xff0c;本节将从 Agent 的概念、ReAct 框架、示例、以及一些论文思路来具体聊下任务规划的话题&#xff0c…...

计算机网络01

文章目录 浏览器输入URL后发生了什么&#xff1f;Linux 系统是如何收发网络包的&#xff1f;Linux 网络协议栈Linux 接收网络包的流程Linux 发送网络包的流程 浏览器输入URL后发生了什么&#xff1f; URL解析 当在浏览器中输入URL后&#xff0c;浏览器首先对拿到的URL进行识别…...

基于SpringBoot微服务架构下前后端分离的MVVM模型浅析

基于SpringBoot微服务架构下前后端分离的MVVM模型浅析 “A Brief Analysis of MVVM Model in Front-end and Back-end Separation based on Spring Boot Microservices Architecture” 完整下载链接:基于SpringBoot微服务架构下前后端分离的MVVM模型浅析 文章目录 基于Spring…...

44444444444

4444444444444444...

数据结构与算法-二分搜索树节点的查找

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、二分搜…...

C++|设计模式(七)|⭐️观察者模式与发布/订阅模式,你分得清楚吗

本文内容来源于B站&#xff1a; 【「观察者模式」与「发布/订阅模式」&#xff0c;你分得清楚吗&#xff1f;】 文章目录 观察者模式&#xff08;Observer Pattern&#xff09;的代码优化观察者模式 与 发布订阅模式 他们是一样的吗&#xff1f;发布订阅模式总结 我们想象这样一…...

计算机毕业设计选题推荐-学院教学工作量统计系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...

人机交互不仅仅是科技问题

人机交互不仅仅局限于物理和数理科学的应用&#xff0c;还涉及到更广泛的管理、文理、哲学、艺术、伦理以及法律等领域。下面这些领域在人机协同和智能系统应用中扮演着重要角色&#xff1a; 智能系统在企业管理、资源分配、决策支持等方面的应用&#xff0c;可以帮助管理者优化…...

Lua Debug.GetInfo

在 Lua 中&#xff0c;debug.getinfo 函数的第一个参数指定了要获取信息的函数的级别。这个级别是一个整数&#xff0c;表示调用栈的深度。以下是一些常见的级别和它们的含义&#xff1a; - 1&#xff1a;当前函数&#xff08;即调用 debug.getinfo 的函数&#xff09;。 - 2&a…...

每日刷题(最短路、图论)

目录 游戏 思路 代码 魔法 思路 代码 P1364 医院设置 思路 代码 P1144 最短路计数 思路 代码 游戏 I-游戏_河南萌新联赛2024第&#xff08;三&#xff09;场&#xff1a;河南大学 (nowcoder.com) 思路 利用dijkstra去寻找起点到其余所有点的最短路径&#xff0c;当…...

远程服务器训练网络之tensorboard可视化

cd到tensorboard events存储的位置 启动tensorboard tensorboard --logdir./ 得到运行结果&#xff1a; TensorBoard 1.13.1 at http://work:6006 (Press CTRLC to quit) 创建tunnel映射到本地&#xff0c;在本地ssh&#xff0c;最好使用公网地址 ssh -N -L 8080:localhost:60…...

MySQL锁详解

锁是计算机在执行多线程或线程时用于并发访问同一共享资源时的同步机制&#xff0c;MySQL中的锁是在服务器层或者存储引擎层实现的&#xff0c;保证了数据访问的一致性与有效性。 MySQL锁&#xff1a; 按粒度分为&#xff1a;全局锁、表级锁、页级锁、行级锁。按模式分为&…...

面试问题记录:

1&#xff0c;hashmap扩容的时候&#xff0c;链表超长但不满足转变成红黑树的条件时&#xff1a; 【HashMap】链表和红黑树互相转换的几种情况和数组的扩容机制_hashmap红黑树转链表条件-CSDN博客 2&#xff0c;cglib与proxy区别 JDK 动态代理和 CGLIB 动态代理对比_动态代理…...

vue如何在组件中监听路由参数的变化

使用 watch 监听 $route 对象 的变化&#xff0c;从而捕捉路由参数的变化 beforeRouteUpdate 导航守卫 当前组件路由更新时调用 beforeRouteUpdate 钩子只在组件被复用时调用&#xff0c;即当组件实例仍然存在时。如果组件是完全重新创建的&#xff0c;那么应该使用 beforeR…...

antd中form表单校验文件上传

antd中文件上传需要单独设置this.model中得数据 this.$set(this.model, filePath,上传成功后返回得文件路径地址)...

商家转账到零钱2024最新开通必过攻略

微信支付商家转账到零钱功能申请设置了人工审核的门槛&#xff0c;本意是为了防止没有合规使用场景的商户滥用该功能&#xff0c;但这也让相当多的真实用户被一次次拒之门外。结合过去6年开通此类产品的经验&#xff0c;今天我们就以2024年最新的的商家转账到零钱的开通流程做一…...

2024全新Thinkphp聊天室H5实时聊天室群聊聊天室自动分配账户完群组/私聊/禁言等功能/全开源运营版本

全开源运营版本聊天室H5实时聊天室群聊聊天室自动分配账户完群组/私聊/禁言等功能 运营版本的聊天室&#xff0c;可以添加好友&#xff0c;建立群组&#xff0c;私聊&#xff0c;禁言功能 H5TP5.0mysqlPHP 源码开源不加密...

(一)javascript中class类

在 JavaScript 中使用 class 语法可以定义类的结构&#xff0c;其中可以包括静态属性/方法、私有属性/方法、公共属性/方法和受保护属性/方法。这些概念有助于封装和数据隐藏&#xff0c;使得代码更加模块化和安全。下面我会解释这些不同的属性和方法&#xff0c;以及如何在类中…...

【注意力MHA,MQA,GQA,MLA】

注意力机制优化简明图解 1. 多头注意力&#xff08;MHA&#xff09; 图示&#xff1a; Input --> [Attention Head 1]--> [Attention Head 2]--> [Attention Head 3]--> ...--> [Attention Head N]--> [Concatenate] --> Output公式&#xff1a; Outpu…...

《从零开始做个摸鱼小网站! · 序》灵感来源

序 大家好呀&#xff0c;我是summo&#xff0c;这次来写写我在上班空闲(摸鱼)的时候做的一个小网站的事。去年阿里云不是推出了个活动嘛&#xff0c;2核2G的云服务器一年只要99块钱&#xff0c;懂行的人应该知道这个价格在业界已经是非常良心了&#xff0c;虽然优惠只有一年&a…...

计算机基础(Windows 10+Office 2016)教程 —— 第5章 文档编辑软件Word 2016(上)

文档编辑软件Word 2016 5.1 Word 2016入门5.1.1 Word 2016 简介5.1.2 Word 2016 的启动5.1.3 Word 2016 的窗口组成5.1.4 Word 2016 的视图方式5.1.5 Word 2016 的文档操作5.1.6 Word 2016 的退出 5.2 Word 2016的文本编辑5.2.1 输入文本5.2.3 插入与删除文本5.2.4 复制与移动文…...

有关做学校网站的毕业论文/重大军事新闻最新消息

由多个作业、进程共同使用的设备称为共享设备。 对共享设备采用共享分配方式&#xff0c;即进行动态分配&#xff0c;当进程提出资源申请&#xff0c;由设备管理模块进行分配&#xff0c;进程使用完毕后&#xff0c;立即归还。转载于:https://www.cnblogs.com/luo841997665/p/4…...

wordpress创建配置文件/活动推广方式都有哪些

258. Add Digits Digit root 数根问题 /*** param {number} num* return {number}*/ var addDigits function(num) {var b (num-1) % 9 1 ;return b; };//之所以num要-1再1;是因为特殊情况下&#xff1a;当num是9的倍数时&#xff0c;09的数字根和0的数字根不同。 性质说明 …...

昭通建设局网站/网站一键生成

strip_whitespace() php读取txt文件并分割行替换空字符串 $handler opendir(zhuzhuoquan);//文件夹名 $ii0; $str ; while( ($filename readdir($handler)) ! false ) { if($filename . || $filename.. || $filenameviews) continue;$ii;//echo $ii.. .$filename.<br…...

长沙优化网站排名/广告联盟怎么加入

页面间对象传递的方法 request&#xff0c;session&#xff0c;application&#xff0c;cookie 等转载于:https://www.cnblogs.com/zhaozhaozhang/p/5856750.html...

上海的网站建设公司/360推广平台登录入口

本篇文章主要与大家简要分享一下&#xff0c;我在AD学习过程中的一些学习笔记&#xff0c;本篇文章主要关于PCB布局设计部分。 本系列文章链接&#xff1a; ----------------------------------------------------------------------------- Altium Designer 2020 学习笔记&a…...

精准引流推广团队/网站优化外包价格

本文链接&#xff1a;http://user.qzone.qq.com/21909166/blog/25评论/阅读(0/12)三个真心的笑容有一個家財萬貫的富翁快死了&#xff0c;死神來接他走&#xff0c;他問死神:「我死後會上天 堂還是地獄&#xff1f;」 死神跟他說&#xff1a;「地獄。」 富翁很不服氣&#xff0…...