对于安卓开发者来说,理清安卓应用的启动流程实在很有帮助,可以在这个流程中把一些重要的概念都串起来,包括AMS, WMS,IMS, SurfaceFlinger, AIDL通信机制,Lopper机制等,也可以帮助我们解决各种应用启动问题,还可以帮助我们更好地理解启各种动优化技术,知道哪种启动优化技术是作用于哪个阶段的。 这篇文章会结合安卓源码介绍用户在Launcher上点击启动图标到应用的第一帧被渲染出来的流程。
1 一图总览全流程
2 结合源码介绍具体流程
2.1 根据需要创建进程
在主页点击应用的图标之后,主页会调用startActivity函数,这个函数其实会最终调用到ATMS的启动activity方法
launcehr会调用这个方法启动应用, 这个方法经过层层调用最终会调用ATMS的方法startActivityAsUser
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
ATMS是服务中专门负责Activity启动和管理的服务,原理这块工作是交由AMS负责,现在专门独立出一个ATMS来负责这块,startActivityAsUser方法最终会调用到ActivityTaskSupervisor.startSpecificActivity方法,在这个方法中会判断目标引用进程是否存在,如果不存在就通过socket发送消息给zygote进程去创建一个新的引用进程。
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
// 应用进程存在,直接启动activity
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
}
}
// 应用进程不存在, 创建新的进程, 这里调用了ATMS的startProcessAsync方法,
// 但最终会发闪送消息给zygote进程,由zygote进程去创建进程
mService.startProcessAsync(r, knownToBeDead, isTop,
isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY
: HostingRecord.HOSTING_TYPE_ACTIVITY);
}
新的应用进程创建之后,会自动继承zygote进程的一些资源,包括ART虚拟机和一些公共的库。然后新进程会执行预定义的程序入口点即ActivityThread.main()方法
2.2 进程启动后,准备环境,启动application
应用进程创建之后,应用进程会告诉AMS新进程已经好了,AMS因为还负责进程管理的职责,所以需要更新一下新进程的信息,像优先级。然后应用进程启动Looper,开启消息循环处理机制,等待AMS下一步启动Applicaiton和Activity的消息并处理。 接下来结合源码看看这个流程 在ActivityThread.main中,一方面会准备looper机制,以便处理应用内主线程的消息。不熟悉looper机制的可以参考之前的文章。另一方里面调用MAS.attachApplication方法告诉AMS当前应用进程已经准备好了。
public static void main(String[] args) {
...
// 初始化looper机制, 先调用prepareMainLooper方法,再调用下面的loop方法
Looper.prepareMainLooper();
// 这里attach到AMS
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
Looper.loop();
}
private void attach(boolean system, long startSeq) {
...
final IActivityManager mgr = ActivityManager.getService();
try {
// 调用AMS.attachApplication方法
mgr.attachApplication(mAppThread, startSeq);
}
}
- attch到AMS,因为AMS负责管理应用进程,所以首先更新下这个进程的一些信息,像进程优先级。 然后通过binder调用ApplicationThread.bindApplication方法继续之后启动流程
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
}
}
private void attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// 更新进程的一些信息
...
// 调用ApplicationThread.bindApplication方法通知应用进程继续下一步的动作
thread.bindApplication(processName, appInfo,
app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
providerList, null, profilerInfo, null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.getCompat(), getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.getDisabledCompatChanges(), serializedSystemFontMap,
app.getStartElapsedTime(), app.getStartUptime());
// 这个方法里面会继续启动需要的activity, service和接受广播
finishAttachApplicationInner(startSeq, callingUid, pid);
}
private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
// 启动activity
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
// 启动service
didSomething |= mServices.attachApplicationLocked(app, processName);
// 接受一些广播并处理
for (BroadcastQueue queue : mBroadcastQueues) {
didSomething |= queue.onApplicationAttachedLocked(app);
}
}
- ApplicationThread.bindApplication方法中,应用进程会通过Looper机制发送一个BIND_APPLICATION消息,然后由Handler的继承类H来处理, H会加载应用包,然后执行Application.onCreate()
// ActivityThread.java
public final void bindApplication(...) {
AppBindData data = new AppBindData();
...
// 发送BIND_APPLICATION消息
sendMessage(H.BIND_APPLICATION, data);
public void handleMessage(Message msg) {
switch (msg.what) {
case BIND_APPLICATION:
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
break;
}
}
private void handleBindApplication(AppBindData data) {
// 构造LoadedApk对象,这里负责加载apk, 包括dex文件和资源文件
data.info = getPackageInfo(data.appInfo, mCompatibilityInfo, null /* baseLoader */,
false /* securityViolation */, true /* includeCode */,
false /* registerPackage */, isSdkSandbox);
try {
// 执行Application.onCreate函数
mInstrumentation.onCreate(data.instrumentationArgs);
}
2.2 启动Activity
上面讲过应用进程启动之后会通知AMS,然后AMS再通过binder让应用进程启动Application后会通过ATMS.attachApplication方法启动Activity。当然后面还会启动service和接受广播,这部分不展开介绍。
在启动Activity的过程中
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
// 这里最终会执行到ApplicationThread.handleLaunchActivity方法
clientTransaction.addCallback(LaunchActivityItem.obtain(...));
final ActivityLifecycleItem lifecycleItem = ResumeActivityItem.obtain(isTransitionForward, r.shouldSendCompatFakeFocus());
// 这里最终会执行到Application.handleResumeActivity方法
clientTransaction.setLifecycleStateRequest(lifecycleItem);
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
handleLaunchActivity方法中会创建Activity,然后执行onCreate生命周期方法,在onCreate中,开发者会调用setContentView方法,这个方法中会创建DecorView
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, int deviceId, Intent customIntent) {
final Activity a = performLaunchActivity(r, customIntent);
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 创建Activity
Activity activity = null;
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
//这里会创建PhoneWindow对象
activity.attach(...);
// 这里会调用Activity.onCreate函数
mInstrumentation.callActivityOnCreate(activity, r.state);
}
handleResumeActivity方法中会执行Activity.onResume方法,然后创建DecorView并通过调用addView方法通知surface创建surface用于后期的界面绘制和渲染。
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
boolean isForward, boolean shouldSendCompatFakeFocus, String reason) {
// 这里会执行Activity.onResume方法
if (!performResumeActivity(r, finalStateRequest, reason)) {
return;
}
// 这里创建DecorView并通过调用addView方法通知surface创建surface用于后期的界面绘制和渲染, addView中会
View decor = r.window.getDecorView();
// 这个方法中会创建ViewRootImpl对象, 并调用setview
wm.addView(decor, l);
setView方法中完成了这些工作之后会向SurfacceFlinger请求vsync信号,然后再vsync信号到来的时候进行第一帧的渲染。
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
if (windowlessSession == null) {
root = new ViewRootImpl(view.getContext(), display);
} else {
root = new ViewRootImpl(view.getContext(), display,
windowlessSession, new WindowlessWindowLayout());
}
// 这个方法最终会调用Choreographer.postCallback去请求vsync信号
root.setView(view, wparams, panelParentView, userId);
}
接受到vsync信号之后就会开始第一帧的渲染工作
2.3 第一帧的渲染
安卓应用通过Choreographer类去请求和接受Vsync信号,接受到vsync信号之后会完成第一帧的绘制。 Choreographer类在FrameDisplayEventReceiver.onVsync(...)方法中接受vsync信号,然后构造一个消息丢到主线程的消息队列中等待处理。
public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
VsyncEventData vsyncEventData) {
// 构造一个异步消息,这个消息的callback绑定的就是FrameDisplayEventReceiver对象,这个类继承自runable
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
// 放进消息队列,处理消息的之后时候会执行FrameDisplayEventReceiver.run方法
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
FrameDisplayEventReceiver.run方法里面最终会调用ViewRootImlp.doTraversal方法完成绘制
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame, mLastVsyncEventData);
}
ViewRootImlp.doTraversal方法里面会经过measure, layout,draw完成一帧的绘制
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
//
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
参考
安卓14源码