Android Activity 的详细启动过程分析

版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com

在正式内容开始之前,我建议读者朋友下载platform/framework/base源代码备用,我们可以到 Android 源码托管站下载:https://android.googlesource.com/,可以下载具体某个模块源代码,可以指定分支或者 tag,需要翻阅 GFW。

另外如果你没有翻阅 GFW 的条件的话,可以使用清华大学镜像源:
https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

例如,现在我们从 Terminal 进入~/Workspance/Android目录下,然后下载framework/base模块的oreo-release分支源代码:

$ git clone -b oreo-release https://aosp.tuna.tsinghua.edu.cn/platform/frameworks/base framework_base

特别声明:本文出现的源代码,为了更加简洁清晰,部分代码经过大量的精简,读者阅读本文时,如果有条件,最好配合源代码,以免产生误解。


本应该从 Launcher 如何启动一个 App 开始讲起,但是 Launcher 启动一个 App 时也是启动这个 App 的 Luancher Activity,例如:

 <activityandroid:name=".WelcomeActivity"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity>

本文包含 App 的启动流程、新进程的启动流程。其实启动一个 App 和启动普通 Activity 一样,如果发现这个 Activity 的进程未启动的话,会启动对应的进程,然后由新的进程来启动这个 Activity,当然这可以单独写一篇文章来分析。但是本文为了降低耦合性让读者更加容易理解 Activity 的启动过程,直接从如何启动一个 Activity 开始讲起。

阅读并理解本文需要读者了解以下知识:

  1. Android 中的消息机制
  2. Binder 的原理和用法
  3. zygote 进程 和 system_server 进程的启动过程
  4. Android 消息机制之同步屏障

Android 消息机制请参考:https://yanzhenjie.blog.csdn.net/article/details/89218745
zygote 进程的启动请参考:https://yanzhenjie.blog.csdn.net/article/details/95539904
Android 消息机制之同步屏障请参考:https://yanzhenjie.blog.csdn.net/article/details/96497153


本文内容

  • AMS 的启动过程
  • startActivity 的执行过程
  • AMS 中 startActivity 的执行过程
  • 启动新进程并运行 ActivityThread
  • AMS 和 ApplicationThread 的通信
  • Application 的初始化
  • 启动 Activity 的流程
  • 执行 Activity 的生命周期
  • Activity 的绘制三连

读完本文后可以了解到的主要内容:

  1. AMS 是什么时候启动的?做了些什么事情?
  2. 普通 App 的进程如何启动的?
  3. ActivityThread 是在那里被执行的?
  4. Application 是什么时候执行的?
  5. Activity 的生命周期是如何在Looper#loop()死循环之外执行的?
  6. Activity 的onCreate()onResume()中为什么不能获取到 View 的宽高?

本文所有章节都配给了相应的流程图辅助理解,极大的提高了读者的理解效率。

来研究本文内容的同学,我相信基础都不会差,至少应该听说过 AMS 吧,AMS 意如其名,是管理 Activity 的系统服务,既然是系统服务,那么应该是在系统启动的时候启动的吧,我们下面来具体看看。

因为 Activity 的启动需要依赖 AMS,所以我们得先了解 AMS 是什么时候启动的,这样才能更加清晰理解 Activity 的启动。

AMS 的启动过程

Linux 系统的所有进程都是init进程的子进程,在 Android 中也不例外,包括zygote也是从init进程 fork 来的,我在Android zygote 进程的启动过程分析一文中详细分析了zygote进程的启动流程,如果不清楚zygote进程启动过流程的同学建议先看看这篇文章,虽然如此,接下来我还是会进行一个简述,方便一些读者会回忆这个过程。

init进程启动后执行位于platform/system/core/init.cpp代码对应的程序,该程序会解析位于platform/system/core/rootdir/init.rc处的配置文件,该配置文件会做一些初始化工作,同时会告诉init进程接着解析init.zygote32.rc或者init.zygote64.rc(具体和设备 CPU 有关),而init.zygote*.rc文件会告诉init进程 fork 一个名为zygote的进程,并指定了其要执行的程序是platform/frameworks/base/cmds/app_process/app_main.cpp代码对应的程序,该程序中最终反射调用了位于 Java 层的com.android.internal.os.ZygoteInit#main()方法,该方法用来初始化zygote进程,在ZygoteInit#main()方法中调用了Zygote#forkSystemServer()创建了system_server进程,并指定system_server进程要执行com.android.sever.SystemServer#main()方法,该方法做的主要的事情如下:

  1. 创建system_server进程的Context(System Context)
  2. 启动 AMS 和 WMS 等系统核心服务
  3. 调用Looper#prepareMainLooper()准备MainLooper
  4. 调用Looper#loop()MainLooper无限循环运行,使system_server进程持续运行

如果读者朋友不清楚zygote进程的启动流程的话,上面的这一段话看起来也许会特别难以理解,因此我还是建议读者先去阅读Android zygote 进程的启动过程分析。

在上述总结处第二步的时候就启动了 AMS,如果读者实在不想看 zogyte 进程启动分析,那么我为这些读者朋友准备了一张 AMS 启动时机的流程图:

接下来我们看看 AMS 启动后做了一些什么事情,这样我们才能更加清楚 AMS 角色在系统中的任务。

首先我们看看 AMS 在system_server进程中是如何启动的,代码位于com.android.server.SystemServer#main()

private SystemServiceManager mServiceManager;
private ActivityManagerService mActivityManagerService;...private void startBootstrapServices() {...// 启动AMSSystemService service =mServiceManager.startService(ActivityManagerService.Lifecycle.class);// 启动AMS后,获取AMS实例mActivityManagerService = service.getService();...// 注册为系统服务mActivityManagerService.setSystemProcess();...
}

可以看到先调用了SystemServiceManager#startService(Class)方法去启动了 AMS,然后把 AMS 注册为系统服务了,下面我们具体看看SystemServiceManager是如何启动 AMS 的。

/*** 根据传入的类名启动对应的服务。*/
public <T extends SystemService> T startService(Class<T> serviceClass) {Constructor<T> constructor = serviceClass.getConstructor(Context.class);final T service = constructor.newInstance(mContext);startService(service);return service;
}/*** 根据传入的服务实例,启动服务。*/
public void startService(@NonNull final SystemService service) {mServices.add(service);service.onStart();
}

在上述代码中,使用反射获取了ActivityManagerServer中的Lifrcycle类的实例,然后调用了Lifycycle#onStart()方法启动了服务,其实这里是使用了适配器模式,因为系统要管理的服务太多了,每一个服务的启动方法不一定相同,因此系统中其他的服务也是使用适配器模式来管理:

public static final class Lifecycle extends SystemService {private final ActivityManagerService mService;public Lifecycle(Context context) {super(context);mService = new ActivityManagerService(context);}@Overridepublic void onStart() {mService.start();}public ActivityManagerService getService() {return mService;}
}

接下来我们把目光的焦点回到SystemServer#main()

// 注册为系统服务
mActivityManagerService.setSystemProcess();

注册到系统服务的时候做了些什么事情呢?

public void setSystemProcess() {// 把AMS添加到ServiceManager中ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);ServiceManager.addService("meminfo", new MemBinder(this));ServiceManager.addService("gfxinfo", new GraphicsBinder(this));ServiceManager.addService("dbinfo", new DbBinder(this));if (MONITOR_CPU_USAGE) {ServiceManager.addService("cpuinfo", new CpuBinder(this));}ServiceManager.addService("permission", new PermissionController(this));ServiceManager.addService("processinfo", new ProcessInfoService(this));ApplicationInfo info = mContext.getPackageManager().getApplicationInfo("android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());synchronized (this) {ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);app.persistent = true;app.pid = MY_PID;app.maxAdj = ProcessList.SYSTEM_ADJ;app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);synchronized (mPidsSelfLocked) {mPidsSelfLocked.put(app.pid, app);}updateLruProcessLocked(app, false, null);updateOomAdjLocked();}
}

这里除了把 AMS 添加到ServiceManager中,也添加了一些必要的或者依赖的服务到ServiceManager中,这样系统和开发者就可以很方便的在任何地方获取到 AMS 服务了。

其实 AMS 的启动流程到这里就差不多了,但是为了辅助我们理解的更加深刻,我们还是来看看ServiceManager是如何注册和获取服务的:

/*** 获取服务*/
public static IBinder getService(String name) {try {IBinder service = sCache.get(name);if (service != null) {return service;} else {IBinder iBinder = getIServiceManager().getService(name)return Binder.allowBlocking(iBinder);}} catch (RemoteException e) {Log.e(TAG, "error in getService", e);}return null;
}/*** 注册服务*/
public static void addService(String name, IBinder service) {try {getIServiceManager().addService(name, service, false);} catch (RemoteException e) {Log.e(TAG, "error in addService", e);}
}

到这里还可以继续深入,但是会脱离本文的中心内容,因此到这里就不再深入。此时,就可以获取 AMS 服务了:

IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
IActivityManager am = IActivityManager.Stub.asInterface(b);

其实在ActivityManager中就是这样做的:

/*** 获取AMS服务。*/
public static IActivityManager getService() {return IActivityManagerSingleton.get();
}private static final Singleton<IActivityManager> IActivityManagerSingleton =new Singleton<IActivityManager>() {@Overrideprotected IActivityManager create() {final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);final IActivityManager am = IActivityManager.Stub.asInterface(b);return am;}
};

这里使用了单利模式来获取 AMS 服务,AMS 的启动过程到这里就结束了,下面就正式开始分析Activity的启动过程了。

startActivity 的执行过程

我们启动一个Activity时一般都是使用Context这样调用:

Intent intent = new Intent(context, XActivity.class);
context.startActivity(intent);

我们常用的ContextApplicationActivityService,其中ApplicationService直接继承ContextWrapper,而Activity涉及到View所以通过继承ContextThemeWrapper间接的继承了ContextWrapperContextWrapper包装的Context的实现类是ContextImpl。因此我们基本都是调用ContextImple的实现方法去执行startActivity的。

这里面的Activity比较特殊,我们知道Activity中有个startActivityResult()方法,为了扩展这些用法,Activity中重写了startActivity()的几个相关方法:

Instrumentation mInstrumentation;...@Override
public void startActivity(Intent intent) {startActivityForResult(intent, -1);
}@Override
public void startActivity(Intent intent, @Nullable Bundle options) {if (options != null) {startActivityForResult(intent, -1, options);} else {startActivityForResult(intent, -1);}
}public void startActivityForResult(Intent intent, int requestCode, Bundle options) {if (mParent == null) {options = transferSpringboardActivityOptions(options);ApplicationThread at = mMainThread.getApplicationThread();Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, at, mToken, this, intent, requestCode, options);if (ar != null) {mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode,ar.getResultCode(), ar.getResultData());}if (requestCode >= 0) {mStartedActivity = true;}cancelInputsAndStartExitTransition(options);} else {if (options != null) {mParent.startActivityFromChild(this, intent, requestCode, options);} else {mParent.startActivityFromChild(this, intent, requestCode);}}
}

可以看到Activity中调用了Instrumentation#execStartActivity(),不过到这里就会发现我们在startActivityForResult()requestCode的值不能使用-1哦,如果使用-1就接受不到回调啦,这也是很多同学都遇到过的问题。

接下来再看看Context的默认实现是怎么样的,首先要知道的是Context的实现类文件是ContextImpl。还记得文章开头我建议读者朋友下载platform/framework/base代码吧,现在我们打开这个项目,再打开ContextImpl.java文件,可以看到Context#startActivity()的代码:

ActivityThread mMainThread;
Instrumentation mInstrumentation;...@Override
public void startActivity(Intent intent) {warnIfCallingFromSystemProcess();startActivity(intent, null);
}@Override
public void startActivity(Intent intent, Bundle options) {warnIfCallingFromSystemProcess();if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0&& options != null&& ActivityOptions.fromBundle(options).getLaunchTaskId() == -1) {throw new AndroidRuntimeException("Calling startActivity() from outside of an Activity "+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."+ " Is this really what you want?");}Instrumentation instrumentation = mMainThread.getInstrumentation();ApplicationThread at = mMainThread.getApplicationThread();instrumentation.execStartActivity(getOuterContext(), at, null,(Activity) null, intent, -1, options);
}

同样可以看到Context中调用了Instrumentation#execStartActivity(),不过这里要注意的一点是,当我们使用非ActivityContext(例如 Application、Service 等)启动一个Activity时,如果没有添加Intent.FLAG_ACTIVITY_NEW_TASK标志的话,会抛出一个异常,具体原因后面分析到相应源码时会详细分析。

这里要注意到一点:

ActivityThread mMainThread;...
ApplicationThread at = mMainThread.getApplicationThread();

ActivityThread是 App 进程对应的程序,它所在就是 App 的默认线程也就主线程,通过getApplicationThread()获取到的对象是主线程在实例化的时候被实例化的ApplicationThread对象,ApplicationThread是每一个 App 进程的 AIDL 服务端,用来管理四大组件的生命周期,具体后面分析到ActivityThread的启动过程时再说。

上述的调用逻辑都比较简单,我们跟踪到Instrumentation里面一步步看最终调用到了哪里:

public ActivityResult execStartActivity( Context who, IBinder contextThread,IBinder token, Activity target, Intent intent,int requestCode, Bundle options) {IApplicationThread whoThread = (IApplicationThread) contextThread;...try {intent.migrateExtraStreamToClipData();intent.prepareToLeaveProcess(who);int result = ActivityManager.getService().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;
}

可以看到这里最终调用了ActivityManager.getService().startActivity(),如果读者看了上文中AMS 的启动过程就知道,这里是获取了IActivityManager实例,IActivityManager基于 AIDL 实现 Binder,如果读者朋友了解 Binder 的话就会知道,因为 App 进程和 AMS 的进程system_server不是同一个进程,所以这里获取到的是 AMS 的IActivityManger在服务端代理,不过这里还会远程调用到 AMS 中去。

AMS 中 startActivity 的执行过程

AMS 作为系统服务,管理的不仅仅是某一个 App 的组件,因此它里面的逻辑是相当复杂的,在这里我们还是根据上文中的调用顺序继续查看源代码。

在看代码之前,我们要明白一点,此时调用已经是 App 进程在进行远程调用了,也就是 App 进程调用了是system_server进程里面的 AMS 服务的方法:

ActivityStarter mActivityStarter;@Override
public final int startActivity(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo,String resultWho, int requestCode, int startFlags,ProfilerInfo profilerInfo, Bundle bOptions) {return startActivityAsUser(caller, callingPackage, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profilerInfo,bOptions, UserHandle.getCallingUserId());
}@Override
public final int startActivityAsUser(IApplicationThread caller,String callingPackage, Intent intent, String resolvedType,IBinder resultTo, String resultWho, int requestCode, int startFlags,ProfilerInfo profilerInfo, Bundle bOptions, int userId) {enforceNotIsolatedCaller("startActivity");userId = mUserController.handleIncomingUser(Binder.getCallingPid(),Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY,"startActivity", null);// 调用了这里return mActivityStarter.startActivityMayWait(caller, -1,callingPackage, intent, resolvedType, null, null, resultTo,resultWho, requestCode, startFlags, profilerInfo, null, null,bOptions, false, userId, null, null, "startActivityAsUser");
}

我们知道 Linux 中 pid 表示进程 id,uid 用来表示用户 id,而 Android 是单用户系统,所以 uid 基本被用来标记应用,而一个应用中可能有多个进程,所以一个应用有一个 uid,但是可能有多个 pid。

在这里处理了 uid 之后从AMS中出来,走入了ActivityStarter,这列调用了ActivityStarter#startActivityMayWait()方法:

private final ActivityManagerService mService;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 globalConfig, Bundle bOptions,boolean ignoreTargetSecurity, int userId,IActivityContainer iContainer, TaskRecord inTask, String reason) {ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);...// Collect information about the target of the Intent.ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo,startFlags, profilerInfo);...synchronized (mService) {...// 调用了这里int res = startActivityLocked(caller, intent, ephemeralIntent,resolvedType, aInfo, rInfo, voiceSession, voiceInteractor,resultTo, resultWho, requestCode, callingPid, callingUid,callingPackage, realCallingPid, realCallingUid,startFlags, options, ignoreTargetSecurity, componentSpecified,outRecord, container, inTask, reason);...try {mService.wait();catch (InterruptedException e) {}mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);return res;}
}

看方法是比较明显的,启动 Activity 可能要等待,为什么呢?因为这里使用了synchronizedwait(),为什么要使用synchronizedwait()呢?我们知道这一套组合一般用于线程间的通信,具体的其他作用后面再看,现在接着调用到:

/*** 先调用这里。*/
int startActivityLocked(IApplicationThread caller, Intent intent,Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo,ResolveInfo rInfo, IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho,int requestCode, int callingPid, int callingUid, String callingPackage,int realCallingPid, int realCallingUid, int startFlags,ActivityOptions options, boolean ignoreTargetSecurity,boolean componentSpecified, ActivityRecord[] outActivity,ActivityStackSupervisor.ActivityContainer container,TaskRecord inTask, String reason) {...// 调用了这里mLastStartActivityResult = startActivity(caller, intent,ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession,voiceInteractor, resultTo, resultWho, requestCode, callingPid,callingUid, callingPackage, realCallingPid, realCallingUid,startFlags, options, ignoreTargetSecurity, componentSpecified,mLastStartActivityRecord, container, inTask);if (outActivity != null) {outActivity[0] = mLastStartActivityRecord[0];}return mLastStartActivityResult;
}/*** 再调用这里。*/
private int startActivity(IApplicationThread caller, Intent intent,Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo,ResolveInfo rInfo, IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho,int requestCode, int callingPid, int callingUid, String callingPackage,int realCallingPid, int realCallingUid, int startFlags,ActivityOptions options, boolean ignoreTargetSecurity,boolean componentSpecified, ActivityRecord[] outActivity,ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask) {...return startActivity(r, sourceRecord, voiceSession, voiceInteractor,startFlags,true, // 注意这里,doResume的值直接是trueoptions, inTask, outActivity);}/*** 再调用这里。*/
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options,TaskRecord inTask, ActivityRecord[] outActivity) {int result = START_CANCELED;try {mService.mWindowManager.deferSurfaceLayout();// 调用了这里result = startActivityUnchecked(r, sourceRecord,voiceSession, voiceInteractor, startFlags, doResume,options, inTask, outActivity);} finally {...}postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId,mSourceRecord, mTargetStack);return result;
}/*** 然后调用这里。*/
private int startActivityUnchecked(final ActivityRecord r,ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor, int startFlags, boolean doResume,ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) {// 注意这里调用了初始状态值的相关参数setInitialState(r, options, inTask, doResume, startFlags,sourceRecord, voiceSession, voiceInteractor);...if (mDoResume) {...// 调用这里mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack,mStartActivity, mOptions);} else {mTargetStack.addRecentActivityLocked(mStartActivity);}mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),preferredLaunchStackId, preferredLaunchDisplayId, mTargetStack.mStackId);return START_SUCCESS;
}/*** 初始化一些记录状态值的参数。*/
private void setInitialState(ActivityRecord r, ActivityOptions options,TaskRecord inTask, boolean doResume, int startFlags,ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor) {...mDoResume = doResume;...
}

这里的情况其实比较复杂的,比如Activity已经是启动的情况,就只调用onNewIntent(),但是我们为了让情况尽量的简单,这里只分析完全重新启动一个Activity的情况。

可以注意到,ActivityStarter的成员变量mDoResume的值这里被初始化为true,这里还有很多其他记录状态的成员变量,因此这里也是上方ActivityStarter#startActivityMayWait()方法中使用了synchronizedwait()的其中一个原因,当然另一个原因就是线程间的通信了。

因此在上方最后一个startActivityUnchecked()方法中会进入if(mDoResume)代码块内,然后执行了ActivityStackSupervisor#resumeFocusedStackTopActivityLocked()方法:

boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack,ActivityRecord target, ActivityOptions targetOptions) {if (targetStack != null && isFocusedStack(targetStack)) {// 调用这里return targetStack.resumeTopActivityUncheckedLocked(target,targetOptions);}final ActivityRecord r = mFocusedStack.topRunningActivityLocked();if (r == null || r.state != RESUMED) {mFocusedStack.resumeTopActivityUncheckedLocked(null, null);} else if (r.state == RESUMED) {mFocusedStack.executeAppTransition(targetOptions);}return false;
}

现在调用到了ActivityStack

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev,ActivityOptions options) {if (mStackSupervisor.inResumeTopActivity) {return false;}boolean result = false;try {mStackSupervisor.inResumeTopActivity = true;// 调用了这里result = resumeTopActivityInnerLocked(prev, options);} finally {mStackSupervisor.inResumeTopActivity = false;}mStackSupervisor.checkReadyForSleepLocked();return result;
}private boolean resumeTopActivityInnerLocked(ActivityRecord prev,ActivityOptions options) {...final ActivityRecord next = topRunningActivityLocked(true);ActivityStack lastStack = mStackSupervisor.getLastStack();if (next.app != null && next.app.thread != null) {...} else {...// 调用了这里mStackSupervisor.startSpecificActivityLocked(next, true, true);}if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();return true;
}

这里主要处理了一些Activity栈相关的东西,然后又回到了ActivityStackSupervisor,接着调用了ActivityStackSupervisor#startSpecificActivityLocked()

ActivityManagerService mService;void startSpecificActivityLocked(ActivityRecord r, boolean andResume,boolean checkConfig) {// 获取当前要启动的Activity所在进程ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);r.getStack().setLaunchTime(r);// 1. 如果进程已经启动了if (app != null && app.thread != null) {try {...// 1. 那么在当前进程启动对应的ActviityrealStartActivityLocked(r, app, andResume, checkConfig);return;} catch (RemoteException e) {...}}// 2. 进程没启动,启动进程后启动ActviitymService.startProcessLocked(r.processName, r.info.applicationInfo,true, 0, "activity", r.intent.getComponent(),false, false, true);
}

在这里主要判断了当前要启动的Activity的进程是否存在,如果存在就在该进程中启动对应的Activity,如果不存在就先启动对应的进程,当然非常有可能是新的 App,然后在新的进程中启动Activity

到这里出现了两种情况,我们分别分析,我们先来分析启动新 App 或者启动新进程。

在上图中,到 11 步的时候,有一个分道扬镳,我们选择了分析 12 步:启动新进程后再启动对应的 Actviity。最终还是会回到 13 步,请继续向下看。

启动新进程并运行 ActivityThread

在上述代码中继续跟踪第二种情况,调用回到了ActivityManagerService,这里主要是使用Socketzygote进程通信,让zygote进程 fork 新的进程出来,并指定了新进程要执行的程序是ActivityThread,要理解下面的分析,必须先熟悉zygote 进程的启动过程,不熟悉该过程的同学建议先熟悉一下。

/*** 先调用这里*/
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 /* isolatedUid */,keepIfLarge,null /* ABI override */,null /* entryPoint */,null /* entryPointArgs */,null /* crashHandler */);
}/*** 再调用这里*/
final ProcessRecord startProcessLocked(String processName,ApplicationInfo info, boolean knownToBeDead, int intentFlags,String hostingType, ComponentName hostingName, boolean allowWhileBooting,boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride,String entryPoint, String[] entryPointArgs, Runnable crashHandler) {// 由于是全新进程,这里的内容我们先不关注...// 调用了这里startProcessLocked(app, hostingType, hostingNameStr,abiOverride, entryPoint, entryPointArgs);// 可以看到`ActivityStackSupervisor#startSpecificActivityLocked()`// 中并没有使用该返回值,该返回值和上方省略逻辑相关,不关注...
}/*** 再调用这里*/
private final void startProcessLocked(ProcessRecord app, String hostingType,String hostingNameStr, String abiOverride, String entryPoint,String[] entryPointArgs) {...try {...// 上面调用时,该值为null// 因此这里指定了新进程要执行的程序是ActvityThreadboolean isActivityProcess = (entryPoint == null);if (entryPoint == null) entryPoint = "android.app.ActivityThread";ProcessStartResult startResult;if (hostingType.equals("webview_service")) {// 启动webview_zygote进程,这里不关注startResult = startWebView(entryPoint, app.processName, uid,uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion,seInfo, requiredAbi, instructionSet, app.info.dataDir,null, entryPointArgs);} else {// 启动新进程startResult = Process.start(entryPoint, app.processName, uid,uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion,seInfo, requiredAbi, instructionSet, app.info.dataDir,invokeWith, entryPointArgs);}...} catch (RuntimeException e) {...}
}

这里使用了Process.start()去启动新的进程,并且指定了新进程要执行的程序是ActivityThread

我们知道 Android App 应用程序的入口是ActivityThread#main(),在这里我们发现了关于它的蛛丝马迹,其实我们在Launcher中启动一个应用时就是走这条逻辑,Launcher中点击某个应用图标时会获取该应用的Launcher对应的Activity,也就是配置了这个intent-filterActivity,也就是默认Activity

<intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>

这也就是为什么我没有从Launcher开始讲 App 的启动过程的原因,因为Activity的启动过程就包含了 App 的启动过程。

接下来我们还是继续看Process.start()

public static final ZygoteProcess zygoteProcess =new ZygoteProcess(ZYGOTE_SOCKET, SECONDARY_ZYGOTE_SOCKET);public static final ProcessStartResult start(final String processClass,final String niceName, int uid, int gid, int[] gids,int debugFlags, int mountExternal, int targetSdkVersion,String seInfo, String abi, String instructionSet,String appDataDir, String invokeWith, String[] zygoteArgs) {return zygoteProcess.start(processClass, niceName, uid, gid, gids,debugFlags, mountExternal, targetSdkVersion, seInfo, abi,instructionSet, appDataDir, invokeWith, zygoteArgs);
}

这里要注意的是,上方方法中传入的entryPoint的值是android.app.ActivityThread,这里对应的参数名称是processClass,然后现在进入ZygoteProcess#start()方法:

public final Process.ProcessStartResult start(final String processClass,final String niceName, int uid, int gid, int[] gids, int debugFlags,int mountExternal, int targetSdkVersion, String seInfo, String abi,String instructionSet, String appDataDir, String invokeWith,String[] zygoteArgs) {try {return startViaZygote(processClass, niceName, uid, gid, gids,debugFlags, mountExternal, targetSdkVersion, seInfo,abi, instructionSet, appDataDir, invokeWith, zygoteArgs);} catch (ZygoteStartFailedEx ex) {...}
}private Process.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 invokeWith,String[] extraArgs) throws ZygoteStartFailedEx {ArrayList<String> argsForZygote = new ArrayList<String>();// 把各种参数存入argsForZygote列表中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_JDWP) != 0) {argsForZygote.add("--enable-jdwp");}if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {argsForZygote.add("--enable-checkjni");}if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {argsForZygote.add("--generate-debug-info");}if ((debugFlags & Zygote.DEBUG_ALWAYS_JIT) != 0) {argsForZygote.add("--always-jit");}if ((debugFlags & Zygote.DEBUG_NATIVE_DEBUGGABLE) != 0) {argsForZygote.add("--native-debuggable");}if ((debugFlags & Zygote.DEBUG_JAVA_DEBUGGABLE) != 0) {argsForZygote.add("--java-debuggable");}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);...//synchronized(mLock) {return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), // 和zygote进程建立Socket连接argsForZygote);}
}

这里要稍微注意一下,argsForZygote是一个ArrayList对象,该List保存了进程的uidgidgroupstarget-sdknice-name等一系列的参数。

然后看看怎么和zygote进程建立连接的:

private final String mSocket;
private final String mSecondarySocket;private ZygoteState openZygoteSocketIfNeeded(String abi)throws ZygoteStartFailedEx {Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");if (primaryZygoteState == null || primaryZygoteState.isClosed()) {try {// 使用主要的Socket发起连接primaryZygoteState = ZygoteState.connect(mSocket);} catch (IOException ioe) {...}}// 主要的Socket连接成功,返回if (primaryZygoteState.matches(abi)) {return primaryZygoteState;}if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {try {// 主要的Socket没匹配成功,则使用次要的Socket发起连接secondaryZygoteState = ZygoteState.connect(mSecondarySocket);} catch (IOException ioe) {throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);}}// 次要的Socket连接成功,返回if (secondaryZygoteState.matches(abi)) {return secondaryZygoteState;}throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}

建立连接到使用连接返回的ZygoteState发送参数列表,zygoteSendArgsAndGetResult()中是如何发送参数列表的:

private static Process.ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, ArrayList<String> args)throws ZygoteStartFailedEx {try {final BufferedWriter writer = zygoteState.writer;final DataInputStream inputStream = zygoteState.inputStream;// 先把指令和参数行数发送过去writer.write(Integer.toString(args.size()));writer.newLine();// 然后把指令和参数一行行发送过去int sz = args.size();for (int i = 0; i < sz; i++) {String arg = args.get(i);writer.write(arg);writer.newLine();}writer.flush();Process.ProcessStartResult result = new Process.ProcessStartResult();// 接受新进程的idresult.pid = inputStream.readInt();result.usingWrapper = inputStream.readBoolean();if (result.pid < 0) {throw new ZygoteStartFailedEx("fork() failed");}// 返回新进程启动结果return result;} catch (IOException ex) {zygoteState.close();throw new ZygoteStartFailedEx(ex);}
}

这里使用一个很常规的数据格式,就是以行的形式发送数据,首先在第一行发送了本次发送的数据有多少行,然后一行行的把所有数据发送过去,可以猜到的是zygote进程中是先读取了第一行,然后按照第一行指定的行数读取了剩余的行数,接下来我们到zygote进程中去看一下,是如何 fork 新进程的。

那么到哪里去看呢,想知道这一点,必须了解zygote 进程的启动过程,zygote进程是从init进程被 fork 出来的,它要执行的程序是om.android.internal.os.ZygoteInit,要进入的方法就是 Java 的main()方法,这方法里面是这样的:

public static void main(String argv[]) {ZygoteServer zygoteServer = new ZygoteServer();try {...// 注册一个名为zygote的ServerSocket,zygoteServer.registerServerSocket(socketName);...// 这里一定是true,启动SystemServerif (startSystemServer) {startSystemServer(abiList, socketName, zygoteServer);}// 运行zygote进程的select循环zygoteServer.runSelectLoop(abiList);zygoteServer.closeServerSocket();} catch (Zygote.MethodAndArgsCaller caller) {// 读者要特别注意这里哦,这里对ZygoteServer#runSelectLoop()包裹了caller.run();}
}

熟悉了zygote进程的启动过程后,我们知道zygote进程使用Socket和其他进程通信。在这里实例化了ZygoteServerZygoteServerzygote进程的服务端,它启动ServerSocket后进入ZygoteServer.runSelectLoop()方法,zygote进程也就是在这里接受 AMS 的连接,并接受指令和参数来 fork 新进程的:

void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {// 可以看到上面的MethodAndArgsCaller异常,值得注意ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();fds.add(mServerSocket.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 {// 轮训连接,-1表示永不超时,一直阻塞,直到有连接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) {// 接受客户端的连接,并添加到fdsZygoteConnection newPeer = acceptCommandPeer(abiList);peers.add(newPeer);fds.add(newPeer.getFileDesciptor());} else {// 拿到一个新连接后,运行一次boolean done = peers.get(i).runOnce(this);if (done) {// 执行结束后从fds移除该描述符peers.remove(i);fds.remove(i);}}}}
}

这里就是不停的从LocalServerSocket接受新连接,并且从一个spawn-request的连接中一次性读取读取命令行调用ZygoteConnection#runOne(Ser)。其实就是等待 AMS 来连接这个Socket,以便启动新的进程来处理后续的事情。

接着看ZygoteConnection#runOnce():

boolean runOnce(ZygoteServer zygoteServer)throws Zygote.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;}...int pid = -1;FileDescriptor childPipeFd = null;FileDescriptor serverPipeFd = null;try {// 把参数接受到的参数数组,解析称Arguments对象parsedArgs = new Arguments(args);...// Fork新进程pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,parsedArgs.gids, parsedArgs.debugFlags, rlimits,parsedArgs.mountExternal, parsedArgs.seInfo,parsedArgs.niceName, fdsToClose, fdsToIgnore,parsedArgs.instructionSet, parsedArgs.appDataDir);} catch (Exception ex) {...}try {if (pid == 0) {zygoteServer.closeServerSocket();IoUtils.closeQuietly(serverPipeFd);serverPipeFd = null;// 处理子进程handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);// 不应到达此处,子进程预期的是抛出// ZygoteInit.MethodAndArgsCaller异常或者执行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);}
}

这里通过readArgumentList()方法从Socket中读取了参数列表成一个数组,该数组里面的参数列表都是有一定格式的,然后根据预定格式把该数据转换为Arguments对象,使用该对象去 fork 一个新的进程。

接下来调用了Zygote#forkAndSpecialize()方法去 fork 新进程:

ZygoteHooks VM_HOOKS = new ZygoteHooks();public static int forkAndSpecialize(int uid, int gid, int[] gids,int debugFlags, int[][] rlimits, int mountExternal, String seInfo,String niceName, int[] fdsToClose, nt[] fdsToIgnore,String instructionSet, String appDataDir) {// 通知要开始fork新进程了VM_HOOKS.preFork();resetNicePriority();// 调用Native方法fork新进程int pid = nativeForkAndSpecialize( uid, gid, gids, debugFlags,rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore,instructionSet, appDataDir);// 通知进程fork结束VM_HOOKS.postForkCommon();return pid;
}

其实VM_HOOKS中的很多代码非常值得深入,但是这里就会脱离我们分析Activity启动的核心内容,因此这里不去深入。

现在新进程已经 fork 完成,接下来还是回到ZygoteConnection,继续查看runOnce()方法中的handleChildProc()方法的处理过程:

private void handleChildProc(Arguments parsedArgs,FileDescriptor[] descriptors, FileDescriptor pipeFd,PrintStream newStderr) throws Zygote.MethodAndArgsCaller {// 关闭Socket连接closeSocket();...// 设置进程名if (parsedArgs.niceName != null) {Process.setArgV0(parsedArgs.niceName);}if (parsedArgs.invokeWith != null) {// 这里暂时不做分析WrapperInit.execApplication(parsedArgs.invokeWith,parsedArgs.niceName, parsedArgs.targetSdkVersion,VMRuntime.getCurrentInstructionSet(),pipeFd, parsedArgs.remainingArgs);} else {// 源码中invokeWith实际上是null,所以走到这里ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs, null /* classLoader */);}
}

现在进入ZygoteInit#zygoteInit()方法:

public static final void zygoteInit(int targetSdkVersion, String[] argv,ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {// 重定向Log的输出RuntimeInit.redirectLogStreams();// 初始化通用的运行时环境RuntimeInit.commonInit();// 让native层初始化zygoteZygoteInit.nativeZygoteInit();// 初始化ApplicationRuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

这里主要是一些初始化工作,具体测进程初始化这里不去深究,我们直接看RuntimeInit.applicationInit()在初始化应用的时候做了些什么工作:

protected static void applicationInit(int targetSdkVersion,String[] argv, ClassLoader classLoader)throws Zygote.MethodAndArgsCaller {// System#exit()时不释放任何hooksnativeSetExitWithoutCleanup(true);// 设置JVM的内存利用率为0.75,提高利用避免不必要的内存VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);// 设置tagetSdkVersionVMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);final Arguments args;try {args = new Arguments(argv);} catch (IllegalArgumentException ex) {Slog.e(TAG, ex.getMessage());return;}// 调用应用层ActivityThread的main方法invokeStaticMain(args.startClass, args.startArgs, classLoader);
}private static void invokeStaticMain(String className, String[] argv,ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {// 反射获取到ActivityThread类,和ActviityThread#main()方法Class<?> cl = Class.forName(className, true, classLoader);Method m = cl.getMethod("main", new Class[] { String[].class });/** 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.*/throw new Zygote.MethodAndArgsCaller(m, argv);// 上述代码最终抛出异常,回到ZygoteInit.main()
}

到这里抛出了一个Zygote.MethodAndArgsCaller异常,在上文中提到过,zygote进程是从init进程被 fork 出来的,它要执行的程序是om.android.internal.os.ZygoteInit,上文中也提到过这段代码:

public static void main(String argv[]) {ZygoteServer zygoteServer = new ZygoteServer();try {...// 注册一个名为zygote的ServerSocket,zygoteServer.registerServerSocket(socketName);...// 这里一定是true,启动SystemServerif (startSystemServer) {startSystemServer(abiList, socketName, zygoteServer);}// 运行zygote进程的select循环zygoteServer.runSelectLoop(abiList);zygoteServer.closeServerSocket();} catch (Zygote.MethodAndArgsCaller caller) {// 读者要特别注意这里哦,这里对ZygoteServer#runSelectLoop()包裹了caller.run();}
}

现在我们关注这个异常处理,在上文中invokeStaticMain()方法被调用后最终抛出了Zygote.MethodAndArgsCaller异常,这个异常最终会层层传递到这里。

这样做的好处是清空堆栈帧,提高栈帧利用率,在源码的注释有有解释。我们知道在抛出这个异常之前有很多初始化工作,在这里清除堆栈帧之后我们看到的栈应该是这样的:

...
android.os.Handler.dispatchMessage(Handler.java:102)
android.os.Looper.loop(Looper.java:157)
android.app.ActivityThread.main(ActivityThread.java:5684)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:746)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)

这一段栈信息大家应该经常看到吧,除非你没有出现过 crash,口亨,我不信!

下面就到了我们都很熟悉的ActivityThread了,想必读者朋友们都应该猜到了,我们来看看Zygote.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);}}
}

这里就是反射调用了刚才传进来的ActivityThread#main()方法,并把相应的参数也传进去了,绕来绕去终于来到了ActivityThread

其实ActivityThread#main()我们应该已经很熟悉了,但是这里还涉及到一些细节,我们还是来看一下:

public static void main(String[] args) {...Environment.initForCurrentUser();// Set the reporter for event logging in libcoreEventLogger.setReporter(new EventLoggingReporter());...// 创建主线程LooperLooper.prepareMainLooper();// attach系统进程ActivityThread thread = new ActivityThread();thread.attach(false);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}// 让主线程进入循环状态Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");
}

终于到了ActivityThread了,胖胖哒!看注释吧,不用多解释了。

看了前面的分析,我们知道 App 启动一个Activity时,是远程调用 AMS 的方法的,那么 AMS 启动了一个Activity后,还要让Activity的生命周期在 App 所在的进程主线程执行,这是怎么做的呢?

新进程启动后,按照本文的节奏应该接着分析 Activity 是如何启动的。其实不然,ActivityThread 程序运行后,App 确实开始初始化了,但是 ActivityThread 启动的过程是怎样的呢?它做了什么样的工作,能让 AMS 通知它调用 Actvity 的生命周期呢?

接下来我们就看看初始化的时候有没有做和 AMS 有相关的任何事情。

AMS 和 ApplicationThread 的通信

在上文中,我们看到AcitivytThread中和系统进程进行了通信绑定,也正是因为这个绑定,ApplicationThread和 AMS 是怎么通信的,AMS 才得以调用对应 App 的远程方法。

private void attach(boolean system) {sCurrentActivityThread = this;mSystemThread = system;if (!system) {...// 保存ApplicationThread到运行时环境来处理后期的异常RuntimeInit.setApplicationObject(mAppThread.asBinder());// 获取到AMS服务final IActivityManager mgr = ActivityManager.getService();try {// 和AMS服务绑定mgr.attachApplication(mAppThread);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}...} else {...}...
}

上述代码中IActivityManager.attachApplication()即是把 App 的ApplicationThread的服务端Binder的实例绑定到 AMS 中去。

可以看到这里只是传入了Binder实例,并没有标记是哪个 App 的Binder,我们知道代码执行到这里时,已经脱离最初调用startActvitiy的进程了,也就是说现在已经在被启动Activity所在进程中了,现在再来看看IActivityManager.attachApplication()方法就一目了然了,打开ActivityManagerService

@Override
public final void attachApplication(IApplicationThread thread) {synchronized (this) {// 获取调用者的进程IDint callingPid = Binder.getCallingPid();final long origId = Binder.clearCallingIdentity();// 使用调用者的进程ID和ApplicationThread绑定attachApplicationLocked(thread, callingPid);Binder.restoreCallingIdentity(origId);}
}

到这里后面的代码就不用贴了,可想而知的是 AMS 中使用了进程 ID 绑定了对应进程的ApplicationThread

在学习Android 的消息机制和应用时我们知道,ApplicationThreadBinder的服务端,其也提供了一些远程方法供客户端调用,这些远程方法就包括四大组件的生命周期方法。

到这里,App 进程就可以调用 AMS 的远程方法了,AMS 也可以调用 App 进程的远程方法了,这就是 AMS 和 APP 互相通信的主要原理。

Application 的初始化

我们知道每一个 Android 进程都有一个贯穿全局的Context,在ActivityManagerService#attachApplication()方法中会初始化 App 的ContextApplication,在上文中调用了ActivityManagerService#attachApplication()方法把ApplicationThead绑定到system_server进程的 AMS 中,在 AMS 接着调用了attachApplicationLocked()方法:

private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {// 找到对应的进程记录ProcessRecord app = mPidsSelfLocked.get(pid);...ApplicationInfo appInfo =app.instr != null ? app.instr.mTargetInfo : app.info;...boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);...// 1. 调用ApplicationThread#bindApplication方法thread.bindApplication(processName, appInfo, providers,app.instr.mClass, profilerInfo, app.instr.mArguments,app.instr.mWatcher, app.instr.mUiAutomationConnection,testMode, mBinderTransactionTrackingEnabled,enableTrackAllocation, isRestrictedBackupMode || !normalMode,app.persistent, new Configuration(getGlobalConfiguration()),app.compat, getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial);...// 顶部是否有Activity在等着进程启动后执行if (normalMode) {try {// 2. 绑定到栈监听,if (mStackSupervisor.attachApplicationLocked(app)) {didSomething = true;}} catch (Exception e) {...}}...return true;
}

这里主要的工作有两个,第一步是调用了 App 进程的ApplicationThread#bindApplication()远程方法,让 App 进程初始化绑定 Application 对象。

我们先来看第一步,ApplicationThread#bindApplication()ApplicationThread的代码位于ActivityThread中:

public final class ActivityThread {
...private class ApplicationThread extends IApplicationThread.Stub {public final void bindApplication(String processName,ApplicationInfo appInfo, List<ProviderInfo> providers, ...) {if (services != null) {// 把服务注册到ServiceManager中,主要是为了BinderServiceManager.initServiceCache(services);}setCoreSettings(coreSettings);AppBindData data = new AppBindData();data.processName = processName;data.appInfo = appInfo;data.providers = providers;...// 把操作发送到主线程去sendMessage(H.BIND_APPLICATION, data);}
}...

因为ApplicationThread是 Binder 的服务端,而 Binder 的远程方法都运行在 Binder 的线程池中,Application的生命周期方法都是运行在主线程中的,因此这里把操作发送到主线程中去了,在ActivityThreadMessage都是发送到 H 中,在 H 中是这样处理H.BIND_APPLICATION消息的:

...
public void handleMessage(Message msg) {...switch (msg.what) {...case BIND_APPLICATION: {AppBindData data = (AppBindData)msg.obj;// 处理绑定Application操作handleBindApplication(data);break;}...}
}...private void handleBindApplication(AppBindData data) {...// info的类型是LoadedApk,给它赋值data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);// Instrumentation信息会影响类加载器,在设置Context之前就加载它final InstrumentationInfo ii;if (data.instrumentationName != null) {try {ii = new ApplicationPackageManager(null, getPackageManager()).getInstrumentationInfo(data.instrumentationName, 0);} catch (PackageManager.NameNotFoundException e) {...}mInstrumentationPackageName = ii.packageName;mInstrumentationAppDir = ii.sourceDir;...} else {ii = null;}// 创建AppContextContextImpl appContext = ContextImpl.createAppContext(this, data.info);updateLocaleListFromAppContext(appContext,mResourcesManager.getConfiguration().getLocales());// 如果不是系统应用if (!Process.isIsolated() && !"android".equals(appContext.getPackageName())) {final File cacheDir = appContext.getCacheDir();if (cacheDir != null) {// 设置每个App使用File.createTempFile()创建的临时目录System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());} else {...}...}...// 加载Instrumentationif (ii != null) {final ApplicationInfo instrApp = new ApplicationInfo();ii.copyTo(instrApp);instrApp.initForUser(UserHandle.myUserId());final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,appContext.getClassLoader(), false, true, false);// 创建Instrumentation的Contextfinal ContextImpl instrContext = ContextImpl.createAppContext(this, pi);try {final ClassLoader cl = instrContext.getClassLoader();// 加载InstrumentationmInstrumentation = (Instrumentation)cl.loadClass(data.instrumentationName.getClassName()).newInstance();} catch (Exception e) {...}...} else {mInstrumentation = new Instrumentation();}...try {// 创建Application,这里第二个参数Instrumentation是nullApplication app = data.info.makeApplication(data.restrictedBackupMode, null);mInitialApplication = app;...// 调用Application#onCreate()方法mInstrumentation.callApplicationOnCreate(app);} finally {StrictMode.setThreadPolicy(savedPolicy);}...
}

这里的一些细节读者朋友可以结合源码看注释,这里我们需要关注的事就是创建Application的过程,在Application成功创建后,调用了Application#onCreate()方法。

接着我们看,是如何创建Application实例的,上文中data参数的类型是AppBindData

static final class AppBindData {LoadedApk info;...
}

它使用LoadedApk去创建Application,但是这里要注意的是LoadedApk#makeApplication()方法的第二个参数传入的null,我们来看看这个LoadedApk#makeApplication()方法:

public Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) {// 已经加载过了,直接返回if (mApplication != null) {return mApplication;}Application app = null;// 获取应用的Application类,如果没有则使用原生Application类String appClass = mApplicationInfo.className;if (forceDefaultAppClass || (appClass == null)) {appClass = "android.app.Application";}try {java.lang.ClassLoader cl = getClassLoader();if (!mPackageName.equals("android")) {initializeJavaContextClassLoader();}// 创建应用的ContextContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);// 调用Instrumentation#newApplication()方法创建Applicationapp = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);appContext.setOuterContext(app);} catch (Exception e) {...}mActivityThread.mAllApplications.add(app);mApplication = app;// 刚刚这里传入的是null,所以这里调用Application#onCreate()方法是不会走的if (instrumentation != null) {try {instrumentation.callApplicationOnCreate(app);} catch (Exception e) {...}}...return app;
}

这里有一些细节,第一个是先获取应用的manifest.xml中配置的Application类名,如果没有获取到,则使用系统默认的android.app.Application作为Application

最终的Application的反射实例化是在Instrumentation中完成的:

public Application newApplication(ClassLoader cl, String className, Context context)throws InstantiationException, IllegalAccessException, ClassNotFoundException {return newApplication(cl.loadClass(className), context);
}static public Application newApplication(Class<?> clazz, Context context)throws InstantiationException, IllegalAccessException, ClassNotFoundException {// 创建Application对象,并绑定应用的ContextApplication app = (Application)clazz.newInstance();app.attach(context);return app;
}

在这里也是通过 App 各自对应的ClassLoader去加载对应 Apk 的class,通过反射实例化Application

再看如何调用Application#onCreate()进行初始化 App 的:

// 调用Application#onCreate()方法
mInstrumentation.callApplicationOnCreate(app);

Instrumentation#callApplicationOnCreate()中没有什么骚操作了:

public void callApplicationOnCreate(Application app) {app.onCreate();
}

至此,Application的初始化就结束了,还记得我们刚开始分析Application的初始化的时候,我们选择分析了ApplicationThread#bindApplication()方法,等第一步执行完成之后,AMS 还会执行第二步:

// 找到对应的进程记录
ProcessRecord app = mPidsSelfLocked.get(pid);// 顶部是否有Activity在等着进程启动后执行
if (normalMode) {try {// 2. 绑定到栈监听if (mStackSupervisor.attachApplicationLocked(app)) {didSomething = true;}} catch (Exception e) {...}
}

那我们接着看第二个调用,代码位于ActivityStackSupervisor#attachApplicationLocked()

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {...// 获取顶部等待启动的Activity信息ActivityRecord hr = stack.topRunningActivityLocked();if (hr != null) {if (hr.app == null && app.uid == hr.info.applicationInfo.uid&& processName.equals(hr.processName)) {try {// 启动刚才获取到的Activityif (realStartActivityLocked(hr, app, true, true)) {didSomething = true;}} catch (RemoteException e) {...}}}
}

ActivityStackSupervisorActivity堆栈监听器或者管理者,它负责管理StackTaskRecord,在这里表示进程启动完毕,要做剩下的事了,首先获取了顶部在等待运行的Activity,下面我们来分析,ActivityStackSupervisor中是如何启动Activity的。

启动 Activity 的流程

不知道读者朋友是否还记得,我们在启动Activity的时候有过分道扬镳,就是在ActivityStackSupervisor#startSpecificActivityLocked()

ActivityManagerService mService;void startSpecificActivityLocked(ActivityRecord r, boolean andResume,boolean checkConfig) {// 获取当前要启动的Activity所在进程ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);r.getStack().setLaunchTime(r);// 1. 如果进程已经启动了if (app != null && app.thread != null) {try {...// 1. 那么在当前进程启动对应的ActviityrealStartActivityLocked(r, app, andResume, checkConfig);return;} catch (RemoteException e) {...}}// 2. 进程没启动,启动进程后启动ActviitymService.startProcessLocked(r.processName, r.info.applicationInfo,true, 0, "activity", r.intent.getComponent(),false, false, true);
}

当时我们选择了分析新的进程,现在可以看到,都回到了同一个方法,在获取到要启动的目标Activity后都调用了ActivityStackSupervisor#realStartActivityLocked(),这个叫殊途同归。

下面进入realStartActivityLocked()方法:

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,boolean andResume, boolean checkConfig) throws RemoteException {...r.app = app;// 处理Activity任务栈相关工作final TaskRecord task = r.getTask();...final ActivityStack stack = task.getStack();try {...// 调用ApplicationThread远程方法运行Activityapp.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,System.identityHashCode(r), r.info,mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.launchedFromPackage, task.voiceInteractor, app.repProcState,r.icicle, r.persistentState, results, newIntents, !andResume,mService.isNextTransitionForward(), profilerInfo);...} catch (RemoteException e) {...}...return true;
}

这里处理了ActivityStack相关的工作,然后调用了 App 进程的远程方法在 App 进程启动ActivityApplicationThread#scheduleLaunchActivity()的代码还是位于ActivityThread中,该方法是这样实现的:

@Override
public final 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) {updateProcessState(procState, false);ActivityClientRecord r = new ActivityClientRecord();r.token = token;r.ident = ident;r.intent = intent;r.referrer = referrer;r.voiceInteractor = voiceInteractor;r.activityInfo = info;...sendMessage(H.LAUNCH_ACTIVITY, r);
}

和初始化Application一样,发送Message H 中,在 H 中就是主线程啦,是这样处理H.LAUNCH_ACTIVITY消息的:

case LAUNCH_ACTIVITY: {final ActivityClientRecord r = (ActivityClientRecord) msg.obj;r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");break;
}

现在把启动Activity的消息发送到主线程了,主线程封装了统一的方法来处理,我们来看ActviityThread#handleLaunchActivity()

private void handleLaunchActivity(ActivityClientRecord r,Intent customIntent, String reason) {...// 运行Ativity,并且执行Activity#onCreate方法Activity a = performLaunchActivity(r, customIntent);r.createdConfig = new Configuration(mConfiguration);reportSizeConfigurations(r);Bundle oldState = r.state;// 执行Activity#onResume()方法handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed,r.lastProcessedSeq, reason);if (!r.activity.mFinished && r.startsNotResumed) {performPauseActivityIfNeeded(r, reason);if (r.isPreHoneycomb()) {r.state = oldState;}}
}

在上述方法中,基本原理和启动Application一致。首先使用反射获取了Activity实例,然后调用了生命周期方法,期间还使用了 WMS 让 Activity 显示在屏幕上。

首先来看一下ActviityThread#performLaunchActivity()中是如何运行Activity的:

private Activity performLaunchActivity(ActivityClientRecord r,Intent customIntent) {ActivityInfo aInfo = r.activityInfo;...// 为Activity生成ContextContextImpl appContext = createBaseContextForActivity(r);Activity activity = null;try {// 需要关注的1:通过反射获取Activity实例java.lang.ClassLoader cl = appContext.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);...} catch (Exception e) {...}// 获取在实例化Application时已经保存的ApplicationApplication app = r.packageInfo.makeApplication(false, mInstrumentation);if (activity != null) {// 获取manifest中为Activity配置的lableCharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());Configuration config = new Configuration(mCompatConfiguration);...// 为Activity生成WindowWindow window = null;if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {window = r.mPendingRemoveWindow;r.mPendingRemoveWindow = null;r.mPendingRemoveWindowManager = null;}// Activity和Context绑定appContext.setOuterContext(activity);// 绑定Activity的一些配置信息activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback);// 绑定启动Activity时的Intentif (customIntent != null) {activity.mIntent = customIntent;}...// 需要关注的2:调用Activity#onCreate()方法if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state,r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}// 调用Activity#onStart()if (!r.activity.mFinished) {activity.performStart();r.stopped = false;}// 如果需要,调用Activity#onRestoreInstanceState()if (!r.activity.mFinished) {if (r.isPersistable()) {if (r.state != null || r.persistentState != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, r.persistentState);}} else if (r.state != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity,r.state);}}// 调用Activity#onPostCreate()if (!r.activity.mFinished) {activity.mCalled = false;if (r.isPersistable()) {mInstrumentation.callActivityOnPostCreate(activity, r.state,r.persistentState);} else {mInstrumentation.callActivityOnPostCreate(activity, r.state);}}...}r.paused = true;mActivities.put(r.token, r);return activity;
}

在上述代码中,主要是在执行 Activity 的生命周期,更多的细节读者可以看注释。我在注释中写了我们需要关注的 2 点,先来看Instrumentation#newActivity()中获取Activity的代码:

public Activity newActivity(ClassLoader cl, String className,Intent intent) throws InstantiationException, IllegalAccessException,ClassNotFoundException {return (Activity)cl.loadClass(className).newInstance();
}

这里的代码比较简单,使用Context的类加载器加载对应的类,并且newInstance()生成对应的实例。接下来就是执行Activity的生命周期方法啦。

执行 Activity 的生命周期

这里我们分析执行Activity#onCreate()Activity#onResume()方法的代码,先来看是如何执行onCreate()方法的。

接上文Instrumentation#callActivityOnCreate()

public void callActivityOnCreate(Activity activity, Bundle icicle) {prePerformCreate(activity);// 执行Activity#onCrate()activity.performCreate(icicle);postPerformCreate(activity);
}

下面来看Activity#performCreate()方法:

final void performCreate(Bundle icicle) {// 上次回收Activity时是否有保存一些数据restoreHasCurrentPermissionRequest(icicle);// 做完准备工作后调用onCreate()方法onCreate(icicle);mActivityTransitionState.readState(icicle);performCreateCommon();
}

嗯,终于执行了Activity#onCreate()方法,接着就看看Activity#onResume()怎么被执行的吧。

现在我们需要回到ActviityThread#handleLaunchActivity()回忆一下:

private void handleLaunchActivity(ActivityClientRecord r,Intent customIntent, String reason) {...// 运行Ativity,并且执行Activity#onCreate方法Activity a = performLaunchActivity(r, customIntent);r.createdConfig = new Configuration(mConfiguration);reportSizeConfigurations(r);Bundle oldState = r.state;// 执行Activity#onResume()方法handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed,r.lastProcessedSeq, reason);if (!r.activity.mFinished && r.startsNotResumed) {performPauseActivityIfNeeded(r, reason);if (r.isPreHoneycomb()) {r.state = oldState;}}
}

我们已经分析了运行 Activity 并执行 ActivityonCreate()方法这种情况,在运行 Activity 时就顺便执行了Activity#onCreate()方法,执行完毕进行了一系列配置,然后就执行Activity#onResume()方法了,下面来看看ActivityThread#handleResumeActivity()

final void handleResumeActivity(IBinder token, boolean clearHide,boolean isForward, boolean reallyResume, int seq, String reason) {ActivityClientRecord r = mActivities.get(token);...// 第一步,先执行 Activity#onResume()r = performResumeActivity(token, clearHide, reason);if (r != null) {final Activity a = r.activity;boolean willBeVisible = !a.mStartedActivity;// 第二步,执行绘制三连if (r.window == null && !a.mFinished && willBeVisible) {// 获取要启动的Activity的Window对象,是刚才绑定的r.window = r.activity.getWindow();// 获取Window的DocoreViewView decor = r.window.getDecorView();decor.setVisibility(View.INVISIBLE);// 获取要启动的Activity的WindowsManagerViewManager wm = a.getWindowManager();WindowManager.LayoutParams l = r.window.getAttributes();...if (a.mVisibleFromClient) {if (!a.mWindowAdded) {// 标记Window已经被添加了a.mWindowAdded = true;// 将ViewRoot添加到Window上wm.addView(decor, l);} else {a.onWindowAttributesChanged(l);}}} else if (!willBeVisible) {...}...} else {...}
}

可以看到在执行Activity#onResume()完成后才把DororeView添加到Activity对应的Window上,所以我们一般在Activity#onCreate()Activity#onResume()中获取不到View的宽高。

接着我们看第一步,是怎么执行Activity#onResume()的,从上述代码可知,第一步的代码还是在ActivityThread中:

public final ActivityClientRecord performResumeActivity(IBinder token,boolean clearHide, String reason) {ActivityClientRecord r = mActivities.get(token);if (r != null && !r.activity.mFinished) {if (clearHide) {r.hideForNow = false;r.activity.mStartedActivity = false;}try {...// 调用Activity#Onresume()r.activity.performResume();...} catch (Exception e) {...}return r;}
}

再看Activity#performResume()

final void performResume() {// 如果是stop状态的化调用onRestart()方法performRestart();...// 调用Activity#onResume()方法mInstrumentation.callActivityOnResume(this);...
}

最后到Instrumentation#,在Instrumentation中调用了Activity#onResume方法:

public void callActivityOnResume(Activity activity) {activity.mResumed = true;activity.onResume();...
}

到这里在全新启动一个Activity时的生命周期就执行结束了,一个Activity也就启动好了。

Activity 的绘制三连

Activity启动后,当它的onResume()方法执行完后,立即开始着手绘制页面,因此当onResume()方法执行完后我们还是看不到Activity的哦,在ActivityThread#handleResumeActivity()方法中调用完Activity#onResume()后开始着手绘制相关的所有工作,我们回忆一下:

final void handleResumeActivity(IBinder token, boolean clearHide,boolean isForward, boolean reallyResume, int seq, String reason) {ActivityClientRecord r = mActivities.get(token);...// 第一步,先执行 Activity#onResume()r = performResumeActivity(token, clearHide, reason);if (r != null) {final Activity a = r.activity;boolean willBeVisible = !a.mStartedActivity;// 第二步,执行绘制三连if (r.window == null && !a.mFinished && willBeVisible) {// 获取要启动的Activity的Window对象,是刚才绑定的r.window = r.activity.getWindow();// 获取Window的DocoreViewView decor = r.window.getDecorView();decor.setVisibility(View.INVISIBLE);// 获取要启动的Activity的WindowsManagerViewManager wm = a.getWindowManager();WindowManager.LayoutParams l = r.window.getAttributes();...if (a.mVisibleFromClient) {if (!a.mWindowAdded) {// 标记Window已经被添加了a.mWindowAdded = true;// 将ViewRoot添加到Window上wm.addView(decor, l);} else {a.onWindowAttributesChanged(l);}}} else if (!willBeVisible) {...}...} else {...}
}

在上述代码中,与绘制三连相关联的代码是:

// 获取要启动的Activity的WindowsManager
ViewManager wm = a.getWindowManager();
...// 将ViewRoot添加到Window上
wm.addView(decor, l);

在这里获取到的ViewManager的实现类的实例是WindowManagerImpl,我们定位到WindowManagerImpl#addView()方法:

WindowManagerGlobal mGlobal;...@Override
public void addView(View view, ViewGroup.LayoutParams params{applyDefaultToken(params);mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}

在这里做了一些默认配置后,调用到WindowManagerGlobal#addView()

public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {...ViewRootImpl root;View panelParentView = null;synchronized (mLock) {...// 实例化ViewRootImplroot = new ViewRootImpl(view.getContext(), display);view.setLayoutParams(wparams);mViews.add(view);mRoots.add(root);mParams.add(wparams);try {// 把上方传进来的DecoreView添加到ViewRoot中root.setView(view, wparams, panelParentView);} catch (RuntimeException e) {...}}
}

为了让逻辑更加清晰,这里省去了一些初始化参数的代码,最终这里把ActivityThread中传入的DecoreView绑定到为这个Activity对应的WindowManager中。

从上述代码可以看出来,绑定的代码是在ViewRootImpl#setView()中:

public void setView(View view, WindowManager.LayoutParams attrs,View panelParentView) {synchronized (this) {if (mView == null) {// DecoreView就是顶层视图啦mView = view;// 标记View已经绑定过啦mAdded = true;// 开始测量、布局、绘制requestLayout();// 下面的太长了,改天专门开一篇文章分析...}}
}

从这里也能看出来,我们为什么说DecoreViewActivity的顶级视图。

requestLayout()的作用我们应该再清楚不过了:

@Override
public void requestLayout() {if (!mHandlingLayoutInLayoutRequest) {// 检查是否在主线程中checkThread();mLayoutRequested = true;// 把测试、布局、绘制工作安排上scheduleTraversals();}
}void scheduleTraversals() {if (!mTraversalScheduled) {// 标记绘制三连工作开始安排啦,那么如果有人再让我安排,我不干的喔mTraversalScheduled = true;// 开启同步屏障mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();// 发送消息,让同步消息停止执行,先做绘制三连mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL,mTraversalRunnable, // 异步消息发送后立刻执行这个回调null);if (!mUnbufferedInputDispatch) {scheduleConsumeBatchedInput();}notifyRendererOfFramePending();pokeDrawLockIfNeeded();}
}

安排测量、布局、绘制时使用了同步屏障机制,如果读者不了解同步屏障机制的话,请看着这篇文章:
Android 消息机制之同步障碍机制和应用

同步屏障会阻碍同步消息的执行,优先执行异步消息。这里的的异步消息在Choreographer#postCallback()方法被发出:

// 第一步
public void postCallback(int callbackType, Runnable action, Object token) {postCallbackDelayed(callbackType, action, token, 0);
}// 第二步
public void postCallbackDelayed(int callbackType, Runnable action,Object token, long delayMillis) {...postCallbackDelayedInternal(callbackType, action, token, delayMillis);
}// 第三步
private void postCallbackDelayedInternal(int callbackType, Object action,Object token, long delayMillis) {...final long now = SystemClock.uptimeMillis();final long dueTime = now + delayMillis;mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);if (dueTime <= now) {// 如果走到这里,发送逻辑和else中一直,所以不再列出代码scheduleFrameLocked(now);} else {// 发送异步消息,执行测量工作Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);msg.arg1 = callbackType;msg.setAsynchronous(true);mHandler.sendMessageAtTime(msg, dueTime);}
}

可以看到最终在Choreographer#postCallback()方法中发送出了异步消息,这个异步消息的回调在上述代码中也有提到,我们回顾一下:

// 发送消息,让同步消息停止执行,先做绘制三连
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL,mTraversalRunnable, // 异步消息发送后立刻执行这个回调null);

再来看看mTraversalRunnable是什么,代码位于ViewRootImple中:

final TraversalRunnable mTraversalRunnable = new TraversalRunnable();class TraversalRunnable implements Runnable {@Overridepublic void run() {doTraversal();}
}void doTraversal() {if (mTraversalScheduled) {// 标记绘制三连工作安排结束了,如果再让我安排,我也乐意的mTraversalScheduled = false;// 移除同步屏障,可以执行同步消息啦mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);// 接着立刻执行绘制三连performTraversals();}
}

一看到 perform 这个单词就知道,开始做实际的工作啦,我们看一下performTraversals()方法:

private void performTraversals() {...performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);...if (measureAgain) {performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);}...performLayout(lp, mWidth, mHeight);...performDraw();
}

这个方法代码太长了,似乎有近千行,适合专门开一篇文章来分析。

这里主要就是分发绘制三连的工作:测量、布局和绘制。具体细节这里不细究,到此,Activity 的全部启动流程分析完毕,鼓掌、撒花

到这里本文就全部结束啦,下次再分析一些其他的系统源码,告辞!


版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com

Android Activity 的详细启动过程分析相关推荐

  1. Android Activity Launch Mode 启动模式详解

    简介 android:launchMode 属性能设置 Activity 对象启动时是否使用已有的实例还是多次创建,会使得交互设计更加良好,也能避免很多问题. 它是 Androidmanifest.x ...

  2. android activity 被notification启动,Android通知Notification全面剖析

    原标题:Android通知Notification全面剖析 通知 通知是您可以在应用的常规 UI 外部向用户显示的消息.当您告知系统发出通知时,它将先以图标的形式显示在通知区域中.用户可以打开抽屉式通 ...

  3. Android Activity的launchMode四种启动模式备忘

    Android Activity的launchMode四种启动模式备忘 Android的Activity的启动模式有四种,在AndroidManifest.xml通过配置Activity的androi ...

  4. android基础 [超级详细android Activity组件解析(Activity综述,Activity生命周期,Activity启动--携带参数启动)]

    1 章节目录 2 Android Activity综述 2.1 Activity怎么用 2.2 layout - 界面布局 2.3 Java - 控制界面 2.4 AndroidManifest.xm ...

  5. Android开发入门教程2-Android init 启动过程分析

    Android init 启动过程分析   分析android的启动过程,从内核之上,我们首先应该从文件系统的init开始,因为 init 是内核进入文件系统后第一个运行的程序,通常我们可以在linu ...

  6. Android系统Surface机制的SurfaceFlinger服务的启动过程分析

    在前面一篇文章中,我们简要介绍了Android系统Surface机制中的SurfaceFlinger服务.SurfaceFlinger服务是在System进程中启动的,并且负责统一管理设备的帧缓冲区. ...

  7. android activity启动流程_Activity 启动流程(二)

    标签: Activity启动流程 Activity启动时间优化 前一篇文章有介绍Launcher请求AMS过程,参考文章- <Activity 启动流程(一)> 本文将介绍AMS到Appl ...

  8. Android应用程序内部启动Activity过程(startActivity)的源代码分析

    上文介绍了Android应用程序的启动过程,即应用程序默认Activity的启动过程,一般来说,这种默认Activity是在新的进程和任务中启动的:本文将继续分析在应用程序内部启动非默认Activit ...

  9. Android Activity启动模式总结

    简介 Activity 作为 Android 四大组件之一,几乎是被接触得最多的.Activity 中有个启动模式的概念,分别是 standard.singleTop.singleTask 以及 si ...

  10. Android中Service的启动方式及Activity与Service的通信方式

    Service启动的两种方式 1.通过startService启动 使用Service的步骤: 定义一个类继承Service 在Manifest.xml文件中配置该Service 使用Context的 ...

最新文章

  1. 【Ubuntu】ping: unknown host www.baidu.com
  2. python的第三方库-Python 的第三方库到底行不行啊?
  3. Windows MySQL8.0安装出错解决方案(Start Server 失败)
  4. python3写一个计算器_Python3 写了一个简单的模拟计算器 总是报错 有知道的大神 帮忙解答下 非常感谢...
  5. Linux中默认的JDK版本设置
  6. pandas之shift()函数
  7. 在印度8年的华为工程师,有很多话想说。
  8. 男人该知道的人生感悟(图)
  9. StarlingMVC:为Starling量身打造的MVC框架
  10. VS远程Linux项目附加pthread
  11. [大牛翻译系列]Hadoop(7)MapReduce:抽样(Sampling)
  12. 【C语言】c语言练习题【4】(适合初学者)
  13. 台式机显示屏作为笔记本显示屏的设置
  14. WinMerge文字重叠问题
  15. 派克宇航获得AVIC涡轮螺旋桨支线飞机MA700的飞控作动系统合同
  16. AI大神Hinton再次“逃离”美国,成就了虎视眈眈的加拿大
  17. excel调整所有行高列宽
  18. 我愿称之为最强归纳—浮点数的规格化与进制数之间的转换
  19. 东北人都难懂的东北话
  20. 《微机原理与接口技术》期末考试题型总结 + 试卷超详解

热门文章

  1. 【深度学习+组合优化】深度学习和强化学习在组合优化方面有哪些应用?
  2. maya藤蔓插件_Maya特效制作之植物生长动画制作教程(二)之多条藤蔓动画制作...
  3. 1、Python3.9版本官网下载安装教程
  4. idea清除本地注册信息
  5. mybatis + spring + PostgreSQL使用中的问题一例
  6. 二维数组定义及初始化
  7. pyqt5 python qlineedit信号_PyQt5实现QLineEdit添加clicked信号的方法
  8. 2019UI设计趋势,抢先了解一下
  9. hdu 2122 最小生成树
  10. win7系统关闭蓝牙服务器,win7系统怎么打开蓝牙的两种方法