ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Android14应用冷启动源码2,从 Zygote fork 到 onCreate:Activity 启动流程六阶段拆解

Android14应用冷启动源码2,从 Zygote fork 到 onCreate:Activity 启动流程六阶段拆解

继续上一篇 Android14 应用冷启动源码:从 ActivityThread.attach 到 AttachApplicationHelper-CSDN博客 , 这一篇继续追踪剩余的应用启动流程。

现在已经看到ActivityStackSupervisor的realStartActivityLocked方法了。看下:

代码太庞大,重点是这一段:

final LaunchActivityItem launchActivityItem = LaunchActivityItem.obtain(r.token, r.intent, System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), deviceId, r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor, proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(), results, newIntents, r.takeOptions(), isTransitionForward, proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController, r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken); // Set desired final state. final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(r.token, isTransitionForward, r.shouldSendCompatFakeFocus()); } else { lifecycleItem = PauseActivityItem.obtain(r.token); } // Schedule transaction. mService.getLifecycleManager().scheduleTransactionAndLifecycleItems( proc.getThread(), launchActivityItem, lifecycleItem);

LaunchActivityItem.obtain(...) 这里把启动 Activity 所需的数据——r.token(目标标识)、r.intent、r.info(ActivityInfo)、配置、保存的状态、结果、新 Intent、profiler 信息等——打包成一个命令对象。

andResume = true:启动完这个 Activity 之后,紧接着要走 Resume(让它可见、获得焦点),所以搭配 ResumeActivityItem。 栈顶activity启动走这个分支。 而andResume为false时只创建,不需要立刻 onResume。

最后一段代码,scheduleTransactionAndLifecycleItems,第一个参数是ApplicationThread 代理。

继续追踪下,这里mService就是ActivityTaskManagerService对象,getLifecycleManager代码在这里:

看下ClientLifecycleManager的scheduleTransactionAndLifecycleItems方法代码:

/** * Schedules a single transaction item with a lifecycle request, delivery to client application. * @throws RemoteException * @see ClientTransactionItem */ void scheduleTransactionAndLifecycleItems(@NonNull IApplicationThread client, @NonNull ClientTransactionItem transactionItem, @NonNull ActivityLifecycleItem lifecycleItem) throws RemoteException { // The behavior is different depending on the flag. // When flag is on, we wait until RootWindowContainer#performSurfacePlacementNoTrace to // dispatch all pending transactions at once. if (Flags.bundleClientTransactionFlag()) { final ClientTransaction clientTransaction = getOrCreatePendingTransaction(client); clientTransaction.addTransactionItem(transactionItem); clientTransaction.addTransactionItem(lifecycleItem); onClientTransactionItemScheduledLocked(clientTransaction); } else { // TODO(b/260873529): cleanup after launch. final ClientTransaction clientTransaction = ClientTransaction.obtain(client); clientTransaction.addCallback(transactionItem); clientTransaction.setLifecycleStateRequest(lifecycleItem); scheduleTransaction(clientTransaction); } }

它有两个分支,由 Flags.bundleClientTransactionFlag() 控制:

flag 关闭(旧路径):立即组装 ClientTransaction 并发出。

flag 开启(新路径):先不发出,把事务项攒进一个 pending 事务里,等 RootWindowContainer#performSurfacePlacementNoTrace 时统一 dispatch。注释写得很直白:we wait until ... to dispatch all pending transactions at once。

这是新版的性能优化:把多次 Binder 调用合并成一次,减少 IPC 次数。

ClientTransaction.obtain(client):创建事务,client 就是 proc.getThread(),即 ApplicationThread 代理。事务知道“发给谁”。

addCallback(transactionItem):挂上 LaunchActivityItem,即“启动指令”。

setLifecycleStateRequest(lifecycleItem):挂上 ResumeActivityItem 或 PauseActivityItem,即“目标生命周期”。

scheduleTransaction(clientTransaction):这里才是真正发出。代码如下:

继续追踪,调用了ClientTransaction的schedule方法:

mClient.scheduleTransaction(this); 这一行就是 SystemServer 侧发出 Binder 调用的最后一环。mClient 是 IApplicationThread 代理,scheduleTransaction(this) 就是把整个 ClientTransaction 打包,通过 Binder 发到 App 进程。到这里,SystemServer 侧的“组装 → 发出”就闭环了。

调用到ApplicationThread的scheduleTransaction方法,这里:

ActivityThread里面没定义scheduleTransaction方法,在它的父类ClientTransactionHandler里:

sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); 切换到主线程,看下这个执行事务的消息:

重点看mTransactionExecutor.execute(transaction); 执行事务。看TransactionExecutor的execute方法如下:

重点看executeTransactionItems(transaction); 方法如下:

记得第一个事务是LaunchActivityItem,应该是走else分支,执行executeNonLifecycleItem。另一个事务是生命周期的,后面再来看。先看executeNonLifecycleItem。executeNonLifecycleItem方法如下:

private void executeNonLifecycleItem(@NonNull ClientTransaction transaction, @NonNull ClientTransactionItem item, boolean shouldExcludeLastLifecycleState) { final IBinder token = item.getActivityToken(); ActivityClientRecord r = mTransactionHandler.getActivityClient(token); if (token != null && r == null && mTransactionHandler.getActivitiesToBeDestroyed().containsKey(token)) { // The activity has not been created but has been requested to destroy, so all // transactions for the token are just like being cancelled. Slog.w(TAG, "Skip pre-destroyed transaction item:\n" + item); return; } if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item); final int postExecutionState = item.getPostExecutionState(); if (item.shouldHaveDefinedPreExecutionState()) { final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r, postExecutionState); if (closestPreExecutionState != UNDEFINED) { cycleToPath(r, closestPreExecutionState, transaction); } } item.execute(mTransactionHandler, mPendingActions); item.postExecute(mTransactionHandler, mPendingActions); if (r == null) { // Launch activity request will create an activity record. r = mTransactionHandler.getActivityClient(token); } if (postExecutionState != UNDEFINED && r != null) { cycleToPath(r, postExecutionState, shouldExcludeLastLifecycleState, transaction); } }

重点看item.execute(mTransactionHandler, mPendingActions); 这句代码。启动事务LaunchActivityItem的execute方法如下:

final ActivityClientRecord r = new ActivityClientRecord(mActivityToken, mIntent, mIdent,
mInfo, mOverrideConfig, ...);
---- LaunchActivityItem 是从 SystemServer 的 LaunchActivityItem.obtain(...) 打包过来的,经过 Binder 传输后,它的字段在 App 端被还原。这一行把这些字段组装成 App 端真正能用的 ActivityClientRecord。

ActivityClientRecord 是 App 端的“Activity 记录”,可以理解为 SystemServer 侧 ActivityRecord 的客户端镜像。关键字段:

mActivityToken:就是 SystemServer 侧的 r.token,两边靠它关联同一个 Activity;

mIntent、mInfo:启动的 Intent 和 ActivityInfo;

mState、mPersistentState:保存的状态,用于恢复;

mPendingResults、mPendingNewIntents:启动时要投递的结果和新 Intent。

然后,client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);
这里的 client 是 ClientTransactionHandler 类型,实际对象就是 ActivityThread(因为 ActivityThread extends ClientTransactionHandler)。所以这一行就是调用 ActivityThread.handleLaunchActivity(...)。ActivityThread的handleLaunchActivity方法如下:

@Override public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, int deviceId, Intent customIntent) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); mSomeActivitiesChanged = true; if (r.profilerInfo != null) { mProfiler.setProfiler(r.profilerInfo); mProfiler.startProfiling(); } // Make sure we are running with the most recent config and resource paths. applyPendingApplicationInfoChanges(r.activityInfo.packageName); mConfigurationController.handleConfigurationChanged(null, null); updateDeviceIdForNonUIContexts(deviceId); if (localLOGV) Slog.v( TAG, "Handling launch of " + r); // Initialize before creating the activity if (ThreadedRenderer.sRendererEnabled && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) { HardwareRenderer.preload(); } WindowManagerGlobal.initialize(); // Hint the GraphicsEnvironment that an activity is launching on the process. GraphicsEnvironment.hintActivityLaunch(); final Activity a = performLaunchActivity(r, customIntent); if (a != null) { r.createdConfig = new Configuration(mConfigurationController.getConfiguration()); reportSizeConfigurations(r); if (!r.activity.mFinished && pendingActions != null) { pendingActions.setOldState(r.state); pendingActions.setRestoreInstanceState(true); pendingActions.setCallOnPostCreate(true); } // Trigger ActivityWindowInfo callback if first launch or change from relaunch. handleActivityWindowInfoChanged(r); } else { // If there was an error, for any reason, tell the activity manager to stop us. ActivityClient.getInstance().finishActivity(r.token, Activity.RESULT_CANCELED, null /* resultData */, Activity.DONT_FINISH_TASK_WITH_ACTIVITY); } return a; }

final Activity a = performLaunchActivity(r, customIntent); 这句代码是重点。然后看performLaunchActivity,这个方法太庞大。

前面是准备 ActivityInfo 和 ClassLoader,然后创建activity对象:

里面最终是调用反射构造activity对象。

然后重点看activity.attach方法:

attach() 内部会做几件关键事:创建 PhoneWindow、设置 WindowManager、调用 attachBaseContext() 把 ContextImpl 注入进去。这是 Activity 从“裸对象”变成“有 Context 的 Activity”的分界点,也是 Application 和 Activity 共享同一套 Context 体系的连接处。

然后重点看这一句代码:
mInstrumentation.callActivityOnCreate(activity, r.state);

callActivityOnCreate里面最终会调用activity的onCrate方法。这一行最终回调到自己写的 Activity.onCreate()。到这里,跨进程启动指令的完整旅程就结束了——SystemServer 发出的 LaunchActivityItem,经过 Binder、H、TransactionExecutor,最终到onCreate。

ok. 回顾了下,从ActivityThread的main方法开发,main里面调用attach方法,中间经过很长的调用链,最终执行到了activity的onCreate。 调用链实在太长,细节很容易忘,总结下,如下:

┌─────────────────────────── Zygote fork ───────────────────────────┐
│ │
│ App 进程 (主线程) │
│ ActivityThread.main() │
│ └─ attach() │
│ └─ mgr.attachApplication(mAppThread, startSeq) ────────────┼── Binder ──┐
│ │ │
└────────────────────────────────────────────────────────────────────┘ │
│
┌─────────────────────────── system_server ────────────────────────────────────────┘
│
│ AMS.attachApplication()
│ └─ attachApplicationLocked(thread, pid, uid, startSeq)
│ ├─ thread.asBinder().linkToDeath(adr, 0) ← 监听 App 死亡
│ ├─ thread.bindApplication(...) ──────────────┼── Binder ──┐ (oneway)
│ └─ app.makeActive(thread, mProcessStats) ← 通道登记
│ │
└────────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────── App 进程 (Binder 线程) ──────────────────┘
│
│ ApplicationThread.bindApplication()
│ └─ queueOrSendMessage(H.BIND_APPLICATION, data)
│
├─────────────── 切主线程 ───────────────┐
│ │
│ App 进程 (主线程) ▼
│ H.handleMessage(BIND_APPLICATION)
│ └─ handleBindApplication(data)
│ ├─ app = data.info.makeApplicationInner(...) ← Application 实例
│ ├─ installContentProviders(app, ...) ← Provider 先于 onCreate
│ ├─ mInstrumentation.callApplicationOnCreate(app) ← Application.onCreate()
│ └─ mgr.finishAttachApplication(startSeq, ...) ── Binder ──┐
│ │
└────────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────── system_server ──────────────────────────┘
│
│ AMS.finishAttachApplicationInner()
│ └─ mAtmInternal.attachApplication(wpc) ← LocalServices,同进程
│ └─ ATMS.LocalService.attachApplication(wpc)
│ └─ RootWindowContainer.attachApplication(wpc)
│ └─ AttachApplicationHelper.process(app)
│ └─ accept() → forAllActivities(this) → test(r)
│ └─ realStartActivityLocked(r, app, andResume, ...)
│ ├─ LaunchActivityItem.obtain(...) ← 启动指令
│ ├─ ResumeActivityItem.obtain(...) ← 目标状态
│ └─ ClientTransaction.schedule()
│ └─ mClient.scheduleTransaction(t) ── Binder ──┐
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────── App 进程 (Binder 线程) ───────────────────────────────────┘
│
│ ApplicationThread.scheduleTransaction()
│ └─ ActivityThread.scheduleTransaction() ← 实际在父类 ClientTransactionHandler
│ └─ sendMessage(H.EXECUTE_TRANSACTION, transaction)
│
├─────────────── 切主线程 ───────────────┐
│ │
│ App 进程 (主线程) ▼
│ H.handleMessage(EXECUTE_TRANSACTION)
│ └─ TransactionExecutor.execute()
│ └─ executeTransactionItems()
│ └─ executeNonLifecycleItem()
│ └─ LaunchActivityItem.execute()
│ └─ ActivityThread.handleLaunchActivity()
│ └─ performLaunchActivity()
│ ├─ mInstrumentation.newActivity(...) ← 反射创建
│ ├─ activity.attach(...) ← 注入 Context
│ └─ mInstrumentation.callActivityOnCreate(...) ← Activity.onCreate()

压缩成六个阶段:

整条链路很长,但本质上只有三次关键切换:

整条链路再长,本质上只有三次关键切换:
1、App → 系统:attachApplication,App 把 ApplicationThread 这个 Binder 对象交给系统。

2、系统 → App:bindApplication 和 scheduleTransaction,系统通过 ApplicationThread 代理反向调用 App。

3、Binder 线程 → 主线程:两次 sendMessage(H.XXX),分别在 bindApplication 和 scheduleTransaction 之后,把工作从 Binder 线程池抛给主线程。

一句话记忆:

attach 交通道 → bindApplication 造 Application → finishAttachApplication 报完成 → realStartActivityLocked 发事务 → LaunchActivityItem 造 Activity。 两次 Binder 往返,两次 H 切主线程,起点是 ActivityThread.main(),终点是 Activity.onCreate()。

返回列表