最近在为自己Moto G定制Rom,顺便重新读了一遍Android 7.0的相关源码,特此记录当做笔记.

在开始正文之前,首先要明白冷启动和热启动.所谓冷启动就是启动该应用时,后台没有该应用的进程,此时系统会创建一个进程分配给它(AMS通过Socket和Zygote通信,Zygote通过forkAndSpecialize()方法向Linux内核申请新进程),之后会创建和初始化Application,然后通过反射执行ActivityThread中的main方法.而热启动则是,当启动应用的时候,后台已经存在该应用的进程,比如按home键返回主界面再打开该应用,此时会从已有的进程中来启动应用,这种方式下,不会重新走Application这一步.

那今天我们主要分析的是应用冷启动的过程.在分析过程中,我发现从Android 2.3到Android 7.0的启动流程总体变化不大,所以,无论你目前是用何版本,下文多是通用的.另外,在本文中,我省略掉了有关Binder这一部分,以便大部分人都能顺利阅读.


从Launcher点击开始

Launcher就是我们所说的桌面,它本质也是一个apk,当我们点击桌面上的图标时,会调用Activity的startActivity(),最终调用startActivityForResult():

    public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {if (mParent == null) {Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);// 省略多行代码} else {// 省略多行代码}}

startActivityForResult将创建过程委托给Instrumenttation的execStartActivity():

    public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {//重点关注IApplicationThreadIApplicationThread whoThread = (IApplicationThread) contextThread;Uri referrer = target != null ? target.onProvideReferrer() : null;if (referrer != null) {intent.putExtra(Intent.EXTRA_REFERRER, referrer);}if (mActivityMonitors != null) {synchronized (mSync) {final int N = mActivityMonitors.size();for (int i=0; i<N; i++) {final ActivityMonitor am = mActivityMonitors.get(i);if (am.match(who, null, intent)) {am.mHits++;if (am.isBlocking()) {return requestCode >= 0 ? am.getResult() : null;}break;}}}}try {intent.migrateExtraStreamToClipData();intent.prepareToLeaveProcess();// 重点关注ActivityManagerNativeint result = ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);checkStartActivityResult(result, intent);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null;}

在该方法签名中,我们看到第二个参数contextThread是IBinder类型,继续往下看,发现contextThread实则是IApplicationThread的实现类.简单来看IApplicationThread的定义:

public interface IApplicationThread extends IInterface {void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,int configChanges, boolean dontReport) throws RemoteException;void scheduleStopActivity(IBinder token, boolean showWindow,int configChanges) throws RemoteException;void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs)throws RemoteException;void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;void scheduleLaunchActivity(Intent intent, IBinder token, int ident,ActivityInfo info, Configuration curConfig, Configuration overrideConfig,CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,int procState, Bundle state, PersistableBundle persistentState,List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException;void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed,Configuration config, Configuration overrideConfig) throws RemoteException;void scheduleNewIntent(List<ReferrerIntent> intent, IBinder token) throws RemoteException;void scheduleDestroyActivity(IBinder token, boolean finished,int configChanges) throws RemoteException;void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,int resultCode, String data, Bundle extras, boolean sync,int sendingUser, int processState) throws RemoteException;// 省略多个方法void scheduleBindService(IBinder token,Intent intent, boolean rebind, int processState) throws RemoteException;void scheduleUnbindService(IBinder token,Intent intent) throws RemoteException;//省略多个方法void scheduleStopService(IBinder token) throws RemoteException;//省略多个方法void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,ComponentName testName, ProfilerInfo profilerInfo, Bundle testArguments,IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection,int debugMode, boolean openGlTrace, boolean restrictedBackupMode, boolean persistent,Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,Bundle coreSettings) throws RemoteException;void scheduleExit() throws RemoteException;// 省略多行代码void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,int resultCode, String data, Bundle extras, boolean ordered,boolean sticky, int sendingUser, int processState) throws RemoteException;void scheduleLowMemory() throws RemoteException;void scheduleActivityConfigurationChanged(IBinder token, Configuration overrideConfig)throws RemoteException;//省略多个方法void scheduleTrimMemory(int level) throws RemoteException;//省略多个方法}

通过大体的阅读IApplicationThread中代码,我们隐约有些熟悉,比如schedulePauseActivity方法应该就是负责Activity中Pause()执行的,scheduleLaunchActivity()应该是负责Activity创建的,scheduleBindService()负责Service绑定的,到现在,我们心里应该会想到IApplicationThread的真正实现类ApplicationThread(位于ActivityThread.java中)就是负责Activity,Service等的创建或其他操作,先来简单的看起其类关系图:

我们继续看Instrumentation的execStartActivity()方法:

int result = ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);

此时启动Activity这一操作交给了ActivityManagerNative.getDefault()的startActivity()方法.ActivityManagerNative是一个抽象类,继承了Binder,同时它又实现了IActivityManager接口,其实现类是ActivityManagerService(AMS).

ActivityManagerNative.getDefault()方法返回IActivityManager类型对象,其实现类是ActivityManagerProxy,其构造函数接受一个IBinder类型,其实就是ActivityManagerService对象,此时你应该发现ActivityManagerNative,IActivityManager以及ActivityManagerProxy三者之间的联系如下:

通过上图,我们看到这三者就是一个典型的代理模式:ActivityManagerProxy就是ActivityManagerService的远程代理,那么此时ActivityManagerNative的作用也就很明显:返回AMS的远程代理对象,这样Launcher应用就能和AMS服务通信了.

我们用一张图来简单的描述上述整个流程:

进入ActivityManagerService

现在我们跳到AMS的startActivity()方法继续往下看:

    @Overridepublic int startActivity(IBinder whoThread, String callingPackage,Intent intent, String resolvedType, Bundle options) {checkCaller();int callingUser = UserHandle.getCallingUserId();TaskRecord tr;IApplicationThread appThread;synchronized (ActivityManagerService.this) {tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);if (tr == null) {throw new IllegalArgumentException("Unable to find task ID " + mTaskId);}appThread = ApplicationThreadNative.asInterface(whoThread);if (appThread == null) {throw new IllegalArgumentException("Bad app thread " + appThread);}}//交给mStackSupervisor继续return mStackSupervisor.startActivityMayWait(appThread, -1, callingPackage, intent,resolvedType, null, null, null, null, 0, 0, null, null,null, options, false, callingUser, null, tr);}

首先我们注意到该方法的第一个参数是IBinder类型,其实质就是前边ApplicationThread的实例,也就是ActivityThread中的mAppThread对象.接下来交给ActivityStackSupervisor实例的startActivityMayWait()继续启动:

final int startActivityMayWait(IApplicationThread caller, int callingUid,String callingPackage, Intent intent, String resolvedType,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode, int startFlags,ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,Bundle options, boolean ignoreTargetSecurity, int userId,IActivityContainer iContainer, TaskRecord inTask) {// Refuse possible leaked file descriptorsif (intent != null && intent.hasFileDescriptors()) {throw new IllegalArgumentException("File descriptors passed in Intent");}boolean componentSpecified = intent.getComponent() != null;// Don't modify the client's object!intent = new Intent(intent);// Collect information about the target of the Intent.ActivityInfo aInfo =resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);ActivityContainer container = (ActivityContainer)iContainer;synchronized (mService) {//省略多行代码int res = startActivityLocked(caller, intent, resolvedType, aInfo,voiceSession, voiceInteractor, resultTo, resultWho,requestCode, callingPid, callingUid, callingPackage,realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,componentSpecified, null, container, inTask);// 省略多行代码return res;}}

该方法看起来非常复杂,但是流程确实蛮清晰的,通过resolveActivity()方法来获取ActivityInfo,接下来是一些其他操作(在不影响流程的前提下,省略多行),然后继续调用startActivityLocked():

final int startActivityLocked(IApplicationThread caller,Intent intent, String resolvedType, ActivityInfo aInfo,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode,int callingPid, int callingUid, String callingPackage,int realCallingPid, int realCallingUid, int startFlags, Bundle options,boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,ActivityContainer container, TaskRecord inTask) {int err = ActivityManager.START_SUCCESS;//省略多行代码err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,startFlags, true, options, inTask);return err;}

在该方法中,又继续调用了startActivityUncheckedLocked()方法,抛开其中细节,我们发现该方法中又继续调用了ActivityStack的resumeTopActivityLocked()来继续启动流程:

 final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {if (mStackSupervisor.inResumeTopActivity) {// Don't even start recursing.return false;}boolean result = false;try {// Protect against recursion.mStackSupervisor.inResumeTopActivity = true;if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;mService.updateSleepIfNeededLocked();}//继续启动result = resumeTopActivityInnerLocked(prev, options);} finally {mStackSupervisor.inResumeTopActivity = false;}return result;}

从上面的代码看出,resumeTopActivitiesLocked()方法继续调用了resumeTopActivityInnerLocked()方法,该方法内部又反过来调用了ActivityStackSupervisor的resumeTopActivitiesLocked()方法

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {//省略多行代码mStackSupervisor.startSpecificActivityLocked(next, true, false);if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();return true;}

在上述代码中,由于应用是第一次启动,因此这里跳过了一些判断代码,最终又调用了ActivityStackSupervisor的startSpecificActivityLocked()来继续启动流程:

void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {// Is this activity's application already running?ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);r.task.stack.setLaunchTime(r);//该应用的进程已经存在if (app != null && app.thread != null) {try {if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0|| !"android".equals(r.info.packageName)) {app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,mService.mProcessStats);}realStartActivityLocked(r, app, andResume, checkConfig);return;} catch (RemoteException e) {Slog.w(TAG, "Exception when starting activity "+ r.intent.getComponent().flattenToShortString(), e);}}//该应用的进程尚未创建,调用AMS的startProcessLocked()mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);}

应用是第一次启动,此时系统尚未为其创建进程,因此调用AMS的startProcessLocked()方法,如果该应用已经存在,则调用realStartActivityLocked().由于这里我们的应用第一次启动,所以从startProcessLocked()往下看:

  final ProcessRecord startProcessLocked(String processName,ApplicationInfo info, boolean knownToBeDead, int intentFlags,String hostingType, ComponentName hostingName, boolean allowWhileBooting,boolean isolated, boolean keepIfLarge) {return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,hostingName, allowWhileBooting, isolated, 0 , keepIfLarge,null , null , null,null);}

该方法直接调用了其对应的重载方法,并在该其中继续调用了重载方法:

      private final void startProcessLocked(ProcessRecord app, String hostingType,String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {long startTime = SystemClock.elapsedRealtime();//省略多行代码boolean isActivityProcess = (entryPoint == null);//默认情况下,entryPoint为null,此时虚拟机启动后默认从ActivityThread的main()方法执行if (entryPoint == null) entryPoint = "android.app.ActivityThread";Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +app.processName);//要求Zygote进程为其创建进程checkTime(startTime, "startProcess: asking zygote to start proc");Process.ProcessStartResult startResult = Process.start(entryPoint,app.processName, uid, uid, gids, debugFlags, mountExternal,app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,app.info.dataDir, entryPointArgs);checkTime(startTime, "startProcess: returned from zygote!");Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);//省略多行代码} catch (RuntimeException e) {//省略}}

到现在我们同样用一张图来描述这过程:

走进Zygote

这里通过Process的start()方法来请求Zygote进程为其生成新进程,在start()方法中又直接调用了startViaZygote():

//processClass是调用者传的android.app.ActivityThread
private static ProcessStartResult startViaZygote(final String processClass,final String niceName,final int uid, final int gid,final int[] gids,int debugFlags, int mountExternal,int targetSdkVersion,String seInfo,String abi,String instructionSet,String appDataDir,String[] extraArgs)throws ZygoteStartFailedEx {synchronized(Process.class) {ArrayList<String> argsForZygote = new ArrayList<String>();// --runtime-args, --setuid=, --setgid=,// and --setgroups= must go first//--runtime-agrs决定了新建进程执行方式,argsForZygote.add("--runtime-args");argsForZygote.add("--setuid=" + uid);argsForZygote.add("--setgid=" + gid);if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {argsForZygote.add("--enable-jni-logging");}if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {argsForZygote.add("--enable-safemode");}if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {argsForZygote.add("--enable-debugger");}if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {argsForZygote.add("--enable-checkjni");}if ((debugFlags & Zygote.DEBUG_ENABLE_JIT) != 0) {argsForZygote.add("--enable-jit");}if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {argsForZygote.add("--generate-debug-info");}if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {argsForZygote.add("--enable-assert");}if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {argsForZygote.add("--mount-external-default");} else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {argsForZygote.add("--mount-external-read");} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {argsForZygote.add("--mount-external-write");}argsForZygote.add("--target-sdk-version=" + targetSdkVersion);//TODO optionally enable debuger//argsForZygote.add("--enable-debugger");// --setgroups is a comma-separated listif (gids != null && gids.length > 0) {StringBuilder sb = new StringBuilder();sb.append("--setgroups=");int sz = gids.length;for (int i = 0; i < sz; i++) {if (i != 0) {sb.append(',');}sb.append(gids[i]);}argsForZygote.add(sb.toString());}if (niceName != null) {argsForZygote.add("--nice-name=" + niceName);}if (seInfo != null) {argsForZygote.add("--seinfo=" + seInfo);}if (instructionSet != null) {argsForZygote.add("--instruction-set=" + instructionSet);}if (appDataDir != null) {argsForZygote.add("--app-data-dir=" + appDataDir);}argsForZygote.add(processClass);if (extraArgs != null) {for (String arg : extraArgs) {argsForZygote.add(arg);}}return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);}}

上面的方法非常简单,设置一堆参数后然后又调用了zygoteSendArgsAndGetResult()向Zygote发送创建进程请求,该方法内部就是和Zygote进行Socket通信.Zygote接受到该请求,并将该请求封装为ZygoteConnection对象,具体代码在ZygoteInit.java当中,来看runSelectLoop():

   private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();fds.add(sServerSocket.getFileDescriptor());peers.add(null);while (true) {StructPollfd[] pollFds = new StructPollfd[fds.size()];for (int i = 0; i < pollFds.length; ++i) {pollFds[i] = new StructPollfd();pollFds[i].fd = fds.get(i);pollFds[i].events = (short) POLLIN;}try {Os.poll(pollFds, -1);} catch (ErrnoException ex) {throw new RuntimeException("poll failed", ex);}for (int i = pollFds.length - 1; i >= 0; --i) {if ((pollFds[i].revents & POLLIN) == 0) {continue;}if (i == 0) {//接受来自AMS的请求ZygoteConnection newPeer = acceptCommandPeer(abiList);peers.add(newPeer);fds.add(newPeer.getFileDesciptor());} else {boolean done = peers.get(i).runOnce();if (done) {peers.remove(i);fds.remove(i);}}}}}

此时Zygote作为服务端不断监听来自AMS的请求,通过acceptCommandPeer()将请求封装为ZygoteConection对象,并将Socket文件标识存在fds中,请求放在peers中.而runOnce()则在下一次循环中处理请求,具体代码如下:

   boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {String args[];Arguments parsedArgs = null;FileDescriptor[] descriptors;try {//读取请求中的参数args = readArgumentList();descriptors = mSocket.getAncillaryFileDescriptors();} catch (IOException ex) {Log.w(TAG, "IOException on command socket " + ex.getMessage());closeSocket();return true;}//省略多行代码/** the stderr of the most recent request, if avail */PrintStream newStderr = null;if (descriptors != null && descriptors.length >= 3) {newStderr = new PrintStream(new FileOutputStream(descriptors[2]));}int pid = -1;FileDescriptor childPipeFd = null;FileDescriptor serverPipeFd = null;try {//将请求参数封装成Arguments对象parsedArgs = new Arguments(args);//省略多行代码//创建新进程或者说创建VM实例pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,parsedArgs.appDataDir);} catch (ErrnoException ex) {//省略多行代码}try {if (pid == 0) {//pid=0表示刚才fork出的子进程IoUtils.closeQuietly(serverPipeFd);serverPipeFd = null;handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);// should never get here, the child is expected to either// throw ZygoteInit.MethodAndArgsCaller or exec().return true;} else {// in parent...pid of < 0 means failureIoUtils.closeQuietly(childPipeFd);childPipeFd = null;return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);}} finally {IoUtils.closeQuietly(childPipeFd);IoUtils.closeQuietly(serverPipeFd);}}

上面的代码比较简单主要是读取请求参数并将其封装为Arguments对象,Arguments包含一下参数:

--setuid=--setgid=--target-sdk-version=--enable-debugger--enable-safemode--enable-checkjni--enable-jit--generate-debug-info--enable-jni-logging--enable-assert--runtime-args--seinfo=--capabilities=--rlimit=--setgroups=--invoke-with--nice-name=--mount-external-default--mount-external-read--mount-external-write--query-abi-list--instruction-set=--app-data-dir=

并通过Zygote的forkAndSpecialize()来生成新进程,成功后pid的值为0,这里我们只关心创建成功的情况,接下来,在新的进程中关闭从Zygote继承来的Socket,然后通过handleChildProc()继续后续操作.

  private void handleChildProc(Arguments parsedArgs,FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)throws ZygoteInit.MethodAndArgsCaller {//关闭AMS和Zygote之间的Socket连接closeSocket();ZygoteInit.closeServerSocket();if (descriptors != null) {try {Os.dup2(descriptors[0], STDIN_FILENO);Os.dup2(descriptors[1], STDOUT_FILENO);Os.dup2(descriptors[2], STDERR_FILENO);for (FileDescriptor fd: descriptors) {IoUtils.closeQuietly(fd);}newStderr = System.err;} catch (ErrnoException ex) {Log.e(TAG, "Error reopening stdio", ex);}}if (parsedArgs.niceName != null) {Process.setArgV0(parsedArgs.niceName);}// End of the postFork event.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);if (parsedArgs.invokeWith != null) {//通过系统调用执行进程WrapperInit.execApplication(parsedArgs.invokeWith,parsedArgs.niceName, parsedArgs.targetSdkVersion,VMRuntime.getCurrentInstructionSet(),pipeFd, parsedArgs.remainingArgs);} else {//寻找相应目标类的main()方法并执行RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs, null /* classLoader */);}}

这里根据invokeWith参数决定使用哪种执行方式,invokeWith不为空则通过WrapperInit执行,否则通过RuntimeInit方式执行.对于这两者不做过多的解释,参数—runtime-args决定了新进程都是以RuntimeInit方式启动,目前就记住SystemServer和apk都是通过RuntimeInit来的即可.

走进RuntimeInit

现在来看RuntimeInit的zygoteInit()方法:

    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");redirectLogStreams();commonInit();nativeZygoteInit();applicationInit(targetSdkVersion, argv, classLoader);}

commonInit()为VM设置默认了线程异常处理器,然后调用了本地方法nativeZygoteInit(),其具体实现在AndroidRuntime.cpp下,位于frameworks/base/core/jni/AndroidRuntime.cpp

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{gCurRuntime->onZygoteInit();
}

在该方法中又调用了其子类AppRutime的onZygoteInit()方法,AppRuntime位于frameworks/base/cmds/app_process/app_main.cpp

virtual void onZygoteInit(){sp<ProcessState> proc = ProcessState::self();ALOGV("App process: starting thread pool.\n");proc->startThreadPool();}

为了不影响后文,我们先回到RuntimeInit的applicationInit():

  private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {nativeSetExitWithoutCleanup(true);//VM设置VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);final Arguments args;try {args = new Arguments(argv);} catch (IllegalArgumentException ex) {Slog.e(TAG, ex.getMessage());// let the process exitreturn;}Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);//反射执行ActivityThread的main函数invokeStaticMain(args.startClass, args.startArgs, classLoader);}

其中最关键的就是invokeStaticMain()方法:

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {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);}//该异常会在ZygoteInit.main()中被捕获,然后在异常处理中调用MethodAndArgsCaller的run()//方法,这样就清除了进程中所有的栈帧throw new ZygoteInit.MethodAndArgsCaller(m, argv);}

在上面的代码中,最终的执行是通过抛出MethodAndArgsCaller的方式,来看一下MethodAndArgsCaller类的定义:

    public static class MethodAndArgsCaller extends Exceptionimplements 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 {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);}}}

MethodAndArgsCaller继承Exception类并实现Runnable接口.但不管如何,现在最终开始执行ActivityThread的入口函数main():

    public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");SamplingProfilerIntegration.start();CloseGuard.setEnabled(false);Environment.initForCurrentUser();EventLogger.setReporter(new EventLoggingReporter());AndroidKeyStoreProvider.install();final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);Process.setArgV0("<pre-initialized>");Looper.prepareMainLooper();ActivityThread thread = new ActivityThread();thread.attach(false);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}

当main()开始运行时,主线程正式开始运行,这也就是我们所说的UI线程.同样我们用一张简单的图来描述上述过程:

总结

到现在,我们已经完全走完应用冷启动的流程,上面的过程看起来繁琐,但是结合时序图来看应该是比较清晰的.抛开细节不看,那么上述的整个流程可以用下图概括:

最后为了方便系统理解整个流程,附上一张相对完整的时序图:

Android 7.0应用冷启动流程分析相关推荐

  1. Android 9.0 Vold 挂载流程分析

    在Android 系统中所有的热插拔设备都是通过Vold 进程挂载的.通过kernel–>vold–>StorageManagerService这样的架构去逐级上报热插拔事件. 一.Vol ...

  2. Android 7.0 WifiMonitor工作流程分析

    2019独角兽企业重金招聘Python工程师标准>>> 在wifi启动扫描的分析过程中,出现了多次WifiMonitor的操作,在此分析一下这个函数是如何工作的. 在Android的 ...

  3. Android 8.0 Activity启动流程分析

    Activity启动过程中需要注意的一些类: Instrumentation     完成对Application和Activity初始化和生命周期调用的工具类.用来监控系统与应用的交互. Activ ...

  4. Android 11.0 Settings源码分析 - 主界面加载

    Android 11.0 Settings源码分析 - 主界面加载 本篇主要记录AndroidR Settings源码主界面加载流程,方便后续工作调试其流程. Settings代码路径: packag ...

  5. Android 8.0系统源码分析--Camera processCaptureResult结果回传源码分析

    相机,从上到下概览一下,真是太大了,上面的APP->Framework->CameraServer->CameraHAL,HAL进程中Pipeline.接各种算法的Node.再往下的 ...

  6. Android 7.1 屏幕旋转流程分析

    Android 7.1   屏幕旋转流程分析 一.概述 Android屏幕的旋转在framework主要涉及到三个类,结构如图 PhoneWindowManager:为屏幕的横竖屏转换的管理类. Wi ...

  7. Android Audio音量设置原理流程分析

    Android Audio音量设置原理流程分析 简介 本篇文章主要介绍Android音量设置从App应用层到framework层执行流程,以及相关的细节和原理分析,建议在阅读此文章前去看博主的混音理论 ...

  8. Android OTA升级原理和流程分析(五)---update.zip包从上层进入Recovery服务

    转载自:http://blog.chinaunix.net/uid-22028566-id-3533854.html 文章开头我们就提到update.zip包来源有两种: 一个是OTA在线下载(一般下 ...

  9. Android 8.0 p2p搜索流程

    #Android 8.0 p2p搜索流程 8.0 wifi p2p整体流程跟其他Android版本相差不大,主要还是多了HIDL一层转换而已 以下是8.0 p2p的搜索流程

  10. AOSP Android 8.0 冷启动流程分析(二)

    前奏: Android系统虽然基于Linux系统的,但是由于Android属于嵌入式设备,并没有像PC那样的BISO程序,取而代之的是Bootloader----系统启动加载器. /boot : 存放 ...

最新文章

  1. 第十五届智能车竞赛不公平竞争情况反映以及审议结果
  2. 开发HTML5的强大9个开发工具
  3. NoSQL(二):创建、管理集群
  4. python使用post方式提交数据
  5. Eigen入门之密集矩阵 1 -- 类Matrix介绍
  6. 我与CSDN的2020年
  7. CocoStudio 创建简单UI资源并添加到工程
  8. PostgreSQL 删除重复数据
  9. AC/DC、DC/DC转换器基础指南(二)
  10. 接口测试流程及测试点
  11. 点云与图像融合的深度学习方法综述
  12. 连续函数零点定理 介值定理
  13. CF1389G Directing Edges
  14. EDG获得S11冠军
  15. np.pad()用于卷积网络中对图片进行填充
  16. C++高阶 常对象和常函数
  17. win10聚焦功能失效的解决方法
  18. 关于sudo:no tty present and no askpass program specified
  19. 【全局面包屑导航】依据路由动态生成面包屑导航
  20. 英语美文阅读:当爱向你们挥手

热门文章

  1. 什么是化工工程?重化工业包含哪些项目?
  2. 查找、下载芯片手册推荐网址
  3. [C#][原创]Magick.NET使用时一些弱点简介
  4. 测试计划工作的目的是什么?
  5. 苏宁11.11:苏宁双十一大促保障经验
  6. 台式计算机配置清单4500,4500组装电脑配置清单
  7. 从0开始学c语言-01-如何完整运行一个程序
  8. freemarker的recurse示例代码
  9. 最实用的Windows安全加固手册
  10. 学术论文的标准格式是什么?写论文有哪些小技巧?