网站建设 业务员提成,网站流量统计系统,电商代运营十大公司排名,开网络公司需要多少资金忽然有一天#xff0c;我想要做一件事#xff1a;去代码中去验证那些曾经被“灌输”的理论。 – 服装… 忽然有一天我想要做一件事去代码中去验证那些曾经被“灌输”的理论。 – 服装学院的IT男 本篇已收录于Activity短暂的一生系列 欢迎一起学习讨论Android应用开发或者WMS VWJB6995 Q707409815 正文
由于篇幅原因整个启动流程分为以下3篇进行分析
Activity启动流程-1
Activity启动流程-2
Activity启动流程-3
本篇介绍阶段三的逻辑这部分的分析上篇阶段二的触发点是同级的也就是在阶段一中 TaskFragment::resumeTopActivity 触发的。 进程是怎么创建的不是当前分析的重点所以快速过一遍流程。
1 阶段三–触发进程创建
执行pause后会执行 ActivityTaskManagerService::startProcessAsync,最后也是通过 ActivityManagerService来触发启动进程的。 看看AMS这块执行进程创建的调用流程
# ActivityTaskManagerServicevoid startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,String hostingType) {try {if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, dispatchingStartProcess: activity.processName);}// 发送消息启动进程调用 ActivityManagerInternal::startProcessfinal Message m PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,isTop, hostingType, activity.intent.getComponent());mH.sendMessage(m);} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}}这里通过 Handler 来完成ActivityManagerInternal::startProcess 的实现在 ActivityManagerService 的内部类 LocalService 中。
# ActivityManagerService$LocalServicepublic void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,boolean isTop, String hostingType, ComponentName hostingName) {try {if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, startProcess: processName);}synchronized (ActivityManagerService.this) {// 继续调用startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,new HostingRecord(hostingType, hostingName, isTop),ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,false /* isolated */);}} finally {Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}}GuardedBy(this)final ProcessRecord startProcessLocked(String processName,ApplicationInfo info, boolean knownToBeDead, int intentFlags,HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,boolean isolated) {return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,false /* isSdkSandbox */, 0 /* sdkSandboxClientAppUid */,null /* sdkSandboxClientAppPackage */,null /* ABI override */, null /* entryPoint */,null /* entryPointArgs */, null /* crashHandler */);}流程走到 ProcessList::startProcessLocked 。
# ProcessListboolean startProcessLocked(......) {......mService.mProcStartHandler.post(() - handleProcessStart(app, entryPoint, gids, runtimeFlags, zygotePolicyFlags, mountExternal,requiredAbi, instructionSet, invokeWith, startSeq)); ...... }private void handleProcessStart(......) {创建一个用于启动进程的 Runnable 对象final Runnable startRunnable () - {try { // 调用 startProcess 方法启动进程并获取启动结果 ProcessStartResultfinal Process.ProcessStartResult startResult startProcess(app.getHostingRecord(),entryPoint, app, app.getStartUid(), gids, runtimeFlags, zygotePolicyFlags,mountExternal, app.getSeInfo(), requiredAbi, instructionSet, invokeWith,app.getStartTime());// 在锁定 ActivityManagerService 后处理进程启动结果synchronized (mService) {// 更新应用的状态如设置PID更新生命周期状态等handleProcessStartedLocked(app, startResult, startSeq);}} catch (RuntimeException e) {......异常处理}};......} 通过 ProcessList::startProcess 来启动应用进程 启动玩之后 ProcessList::handleProcessStartedLocked 会更新应用的状态如设置PID更新生命周期状态等
ProcessList::handleProcessStartedLocked 经过几次重载会调用下面的方法
# ProcessListActivityManagerService mService null;boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,long expectedStartSeq, boolean procAttached) {......StringBuilder buf mStringBuilder;buf.append(Start proc );buf.append(pid);buf.append(:);buf.append(app.processName);buf.append(/);UserHandle.formatUid(buf, app.getStartUid());if (app.getIsolatedEntryPoint() ! null) {buf.append( [);buf.append(app.getIsolatedEntryPoint());buf.append(]);}buf.append( for );buf.append(app.getHostingRecord().getType());if (app.getHostingRecord().getName() ! null) {buf.append( );buf.append(app.getHostingRecord().getName());}// 输出日志mService.reportUidInfoMessageLocked(TAG, buf.toString(), app.getStartUid());......}1.1创建进程小结
创建进行逻辑我没深入了解过所以简单看了下调用逻辑以 AMS::reportUidInfoMessageLocked 结束的原因是因为其会打印下面的这个创建进程的关键日志
07-26 19:19:05.477 8737 8782 I ActivityManager: Start proc 19643:com.example.myapplication/u0a198 for next-top-activity {com.example.myapplication/com.example.myapplication.MainActivity}经常看日志看启动了哪个进程搜的日志就是在这里打印的。
这部分的调用链如下
ActivityTaskManagerService::startProcessAsyncActivityManagerService$LocalService::startProcessActivityManagerService::startProcessLockedProcessList::startProcessLockedProcessList::handleProcessStartProcessList::startProcess -- 启动进程ProcessList::handleProcessStartedLockedActivityManagerService::reportUidInfoMessageLocked -- 打印日志
2. 阶段三–应用进程创建
进程创建完成后会执行 ActivityThread::main 方法所以应用端进程创建结束的逻辑从这个方法开始分析。
2.1 应用端处理
# ActivityThread// ApplicationThread 是 AMS 作为 C 端时与应用进程通信的方式final ApplicationThread mAppThread new ApplicationThread();public static void main(String[] args) {......// 主线程LooperLooper.prepareMainLooper();......ActivityThread thread new ActivityThread();// 下一步thread.attach(false, startSeq);// 主线程LooperLooper.loop();}private void attach(boolean system, long startSeq) {......final IActivityManager mgr ActivityManager.getService();try {//重点 *2. 将mAppThread告知AMS用于AMS与应用进程通信mgr.attachApplication(mAppThread, startSeq);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}......}应用端的调用链比较简单:
ActivityThread::mainLooper::prepareMainLooperActivityThread::initActivityThread::attachActivityManagerService::attachApplication -- 跨进程Looper::loop应用进程电话创建完毕后在 main 方法里会执行 attach 就是要将自己的信息告知AMS毕竟 AMS 是管理模块。
2.2 system_service端处理
system_service 端 ActivityManagerService 知道有进程启动了这个行为也可能会触发系统组显示逻辑的改变所以比如也会做响应处理
2.1 调用链
ActivityManagerService::attachApplicationActivityManagerService::attachApplicationLockedActivityThread::bindApplicationActivityTaskManagerService.LocalService::attachApplication WindowContainer::forAllRootTasks --- 省略forAllRootTasks等固定堆栈Task::forAllRootTasksWindowContainer::forAllActivitiesActivityRecord::forAllActivitiesRootWindowContainer.AttachApplicationHelper::testRootWindowContainer.AttachApplicationHelper::testActivityTaskSupervisor::realStartActivityLocked -- 构建LaunchActivityItem接上一篇知道如果进程启动了 ActivityTaskSupervisor::startSpecificActivity 就会走进去ActivityTaskSupervisor::realStartActivityLocked 。 但是可能会好奇怎么就知道要执行应用 MainActivity 到 onCreate 就一定是在这个方法里呢 调试方法有很多比如加 log 打堆栈但是对应这个逻辑比较简单的是需要执行 Activity 启动到 onCreate 的控制在 LaunchActivityItem 中而 LaunchActivityItem在 framework 的引用除了本身就只有在 ActivityTaskSupervisor。 2.2 主流程
# ActivityManagerService// 当应用进程调用attachApplication 执行public final void attachApplication(IApplicationThread thread, long startSeq) {if (thread null) {throw new SecurityException(Invalid application interface);}synchronized (this) {// 获取 应用进程的信息后执行attachApplicationLockedint callingPid Binder.getCallingPid();final int callingUid Binder.getCallingUid();final long origId Binder.clearCallingIdentity();// 执行attachApplicationLocked(thread, callingPid, callingUid, startSeq);Binder.restoreCallingIdentity(origId);}}private boolean attachApplicationLocked(NonNull IApplicationThread thread,int pid, int callingUid, long startSeq) {// 需要启动应用的进程数据ProcessRecord app;......if (pid ! MY_PID pid 0) {synchronized (mPidsSelfLocked) {// 通过mPidsSelfLocked获取app mPidsSelfLocked.get(pid);}......} ...... // 触发ActivityThread::bindApplication 逻辑if (app.getIsolatedEntryPoint() ! null) {......} else if (instr2 ! null) {// bindApplication...... } else {// 重点* 1. bindApplicationthread.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());}......if (!mConstants.mEnableWaitForFinishAttachApplication) {// 重点* 2. finishAttachApplicationInner(startSeq, callingUid, pid);} else {app.setPendingFinishAttach(true);}......}ActivityManagerService::finishAttachApplicationInner 是 U 把原来的逻辑提取新增的方法。
# ActivityManagerServicepublic ActivityTaskManagerInternal mAtmInternal;private void finishAttachApplicationInner(long startSeq, int uid, int pid) {......if (normalMode) {try {// 重点 触发构建 LaunchActivityItem 流程didSomething mAtmInternal.attachApplication(app.getWindowProcessController());} catch (Exception e) {Slog.wtf(TAG, Exception thrown launching activities in app, e);badApp true;}}......}这里是触发 LaunchActivityItem 的流程主线, mAtmInternal是 ATMS 的内部类 LocalService 。
# ActivityTaskManagerService$LocalServiceOverridepublic boolean attachApplication(WindowProcessController wpc) throws RemoteException {......return mRootWindowContainer.attachApplication(wpc);......}流程来到 RootWindowContainer 预感要开始处理窗口显示逻辑。
# RootWindowContainerprivate final AttachApplicationHelper mAttachApplicationHelper new AttachApplicationHelper();boolean attachApplication(WindowProcessController app) throws RemoteException {try {return mAttachApplicationHelper.process(app);} finally {mAttachApplicationHelper.reset();}}# RootWindowContainer// 实现 Consumer 接口private class AttachApplicationHelper implements ConsumerTask, PredicateActivityRecord {......boolean process(WindowProcessController app) throws RemoteException {mApp app;for (int displayNdx getChildCount() - 1; displayNdx 0; --displayNdx) {// 重点* 调用每个容器的 forAllRootTasksgetChildAt(displayNdx).forAllRootTasks(this);......}......}......}这里看到传递了“this”所以 AttachApplicationHelper 必然实现了 Consumer 接口 直接看其 accept 实现即可。
# RootWindowContainer$AttachApplicationHelperprivate class AttachApplicationHelper implements ConsumerTask, PredicateActivityRecord {......boolean process(WindowProcessController app) throws RemoteException {mApp app;for (int displayNdx getChildCount() - 1; displayNdx 0; --displayNdx) {// 重点*1. 调用每个容器的 forAllRootTasksgetChildAt(displayNdx).forAllRootTasks(this);......}......}Overridepublic void accept(Task rootTask) {......if (rootTask.getVisibility(null /* starting */) TASK_FRAGMENT_VISIBILITY_INVISIBLE) {// 如果Task 不可见则不需要处理return;}// 执行 topRunningActivitymTop rootTask.topRunningActivity();// 重点*2. 执行accept 让容器下的每个 ActivityRecord 执行 testrootTask.forAllActivities(this);}Overridepublic boolean test(ActivityRecord r) {// 判断 ActivityRecord 是否满足需要启动条件if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard|| r.app ! null || mApp.mUid ! r.info.applicationInfo.uid|| !mApp.mName.equals(r.processName)) {return false;}try {// 重点*3. 执行 realStartActivityLocked 尝试实际启动 Activityif (mTaskSupervisor.realStartActivityLocked(r, mApp,mTop r r.getTask().canBeResumed(r) /* andResume */,true /* checkConfig */)) {mHasActivityStarted true;}} catch (RemoteException e) {......}return false;}}这部分的逻辑也就是一路执行比较疑惑的点也许是进入 AttachApplicationHelper::proces 方法后的几个 Lambda 表达式容易绕晕。 简单梳理一下首先是从 RootWindowContainer 开始执行的目的就是想要执行到所有 ActivityRecord 然后判断一下它的情况是不是需要启动对应的 Activity 。 AttachApplicationHelper::proces 里的 “getChildAt” 对应的是每个屏幕也就是 DisplayContent 然后再遍历其下的每个 RootTask 让其执行 accept 函数 AttachApplicationHelper::accept 目前是对象是 Task ,准确的说是 RootTask 。如果这个 Task 是可见的则又开始遍历其下的所有 ActivityRecord 让其执行 test 函数 AttachApplicationHelper::test 方法是真正干活的地方所有一堆条件判断这个 ActivityRecord 是否满足 r.finishing活动是否正在结束!r.showToCurrentUser() 活动是否对当前用户可见!r.visibleIgnoringKeyguard 活动是否可见即使有屏幕保护器r.app ! null 活动的应用程序是否已经存在mApp.mUid ! r.info.applicationInfo.uid 应用程序的UID是否与预期的不同!mApp.mName.equals(r.processName)应用程序的名称是否与活动的进程名称不同 感觉比较重要的就是前面3个条件这个 ActivityRecord 是不是需要显示给用户如果需要则执行 ActivityTaskSupervisor::realStartActivityLocked 试图启动 Activity 。
3. 阶段三总结
阶段三的流程相对来逻辑简单一些知道个调用链就好流程目的就是执行 ActivityTaskSupervisor::realStartActivityLocked 。
这部分的堆栈如下图 加上应用端的调用链完成调用链如下
ActivityThread::mainLooper::prepareMainLooperActivityThread::initActivityThread::attachActivityManagerService::attachApplication -- 跨进程ActivityManagerService::attachApplicationLockedActivityThread::bindApplicationActivityManagerService::finishAttachApplicationInnerActivityTaskManagerService$LocalService::attachApplicationRootWindowContainer::attachApplicationRootWindowContainer$AttachApplicationHelper::process -- 开始遍历WindowContainer::forAllRootTasks --- 省略forAllRootTasks等固定堆栈Task::forAllRootTasks -- 1. 遍历所有root TaskRootWindowContainer$AttachApplicationHelper::accept -- 1.1 root Task执行acceptWindowContainer::forAllActivities -- 2. 遍历下面的所有ActivityRecordActivityRecord::forAllActivities RootWindowContainer$AttachApplicationHelper::test -- 2.1 ActivityRecord执行testActivityTaskSupervisor::realStartActivityLocked -- 试图启动ActivityLooper::loop
对应时序图 大概流程图如下 这一阶段主要就是应用进程启动后试图拉起对应的 Activity 能不能启动的条件就是没有正在 pause 的 Activity 了。 主要逻辑就是触发 ActivityTaskSupervisor::realStartActivityLocked
4. 阶段四–真正启动Activity
阶段四其实就是触发应用端创建 Activity 。
4.1 realStartActivityLocked
这个方法是要真去触发 Activity 启动的根据前面的流程图阶段二三的最终就是想执行到这个方法里面来触发 Activity 启动。
这个方法的最终目的就是通过事务执行 LaunchActivityItem 和 PauseActivityItem 也就是会触发应用端 TargetActivity 启动并执行生命周期到 onCreate 和 onResume 。
# ActivityTaskSupervisor boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,boolean andResume, boolean checkConfig) throws RemoteException {// 重点* 1. 判断是否执行完了pause if (!mRootWindowContainer.allPausedActivitiesComplete()) {// While there are activities pausing we skipping starting any new activities until// pauses are complete. NOTE: that we also do this for activities that are starting in// the paused state because they will first be resumed then paused on the client side.// 如果还有Activity没完成pause则打印日志并returnProtoLog.v(WM_DEBUG_STATES,realStartActivityLocked: Skipping start of r%s some activities pausing...,r);return false;}// 重点* 2. 表示ActivityRecord已连接到相应的进程r.setProcess(proc);......// event日志 wm_restart_activity EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),task.mTaskId, r.shortComponentName);......// 重点* 3.1 创建事务用于Activity启动// Create activity launch transaction.final ClientTransaction clientTransaction ClientTransaction.obtain(proc.getThread(), r.token);final boolean isTransitionForward r.isTransitionForward();// 获取Activity所在 TaskFragment Tokenfinal IBinder fragmentToken r.getTaskFragment().getFragmentToken();// 重点* 3.2 将构建的 LaunchActivityItem 添加到 clientTransaction 中clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(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(), r.compat,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));// 重点* 3.3 设置预期的最终状态为 ResumeActivityItemfinal ActivityLifecycleItem lifecycleItem;if (andResume) {// Resume逻辑,启动走的这。 表示需要执行到onCreatelifecycleItem ResumeActivityItem.obtain(isTransitionForward);} else {// Pause 逻辑lifecycleItem PauseActivityItem.obtain();}clientTransaction.setLifecycleStateRequest(lifecycleItem);// 重点* 3.4 执行事务mService.getLifecycleManager().scheduleTransaction(clientTransaction);......}根据代码的标注解释 根据注释如果有 Activity 正在 pause 则不允许任何 Activity 启动。换句话说就是想要启动一个 Activity 必须其他的 Activity 需要 pause 的都完成了 pause 流程 对应上一篇提到的 ActivityRecord::attachedToProcess 方法如果需要返回 true 则必须在这里执行 setProcess 方法否则 ActivityRecord 下的 app 变量就是 null 这里就是开始真正执行启动 Activity 的地方了是通过事务执行的分为以下几步 3.1 构建一个事务3.2 设置 LaunchActivityItem 这一步会将 Activity 的生命周期执行到 onCreate3.3 设置 ResumeActivityItem 这一步会将 Activity 的生命周期执行到 onResume3.4 执行事务 后续逻辑就是在应用端执行 Activity 的创建以及生命周期处理了这部分本篇大概看一遍流程以分析到 Activity 的创建为止。 4.2 创建Activity
这部分的调用链如下
LaunchActivityItem::executeActivityThread::handleLaunchActivityActivityThread::performLaunchActivityInstrumentation::newActivity -- 创建ActivityActivity::attach -- 处理Window相关Window::initWindow::setWindowManagerInstrumentation::callActivityOnCreate -- onCreate流程Activity::performCreateActivity::onCreate --over时序图图下 接下来看 LaunchActivityItem::execute
# LaunchActivityItem public void execute(ClientTransactionHandler client, IBinder token,PendingTransactionActions pendingActions) {Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, activityStart);ActivityClientRecord r new ActivityClientRecord(token, mIntent, mIdent, mInfo,mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,mTaskFragmentToken);client.handleLaunchActivity(r, pendingActions, null /* customIntent */);Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);}这里的 client 是 ClientTransactionHandler 类型 而 ActivityThread 是 ClientTransactionHandler 子类。
重点是这边创建了 ActivityClientRecord 第一个参数就是我们要找的token
逻辑来到应用进程 ActivityThread
# ActivityThreadpublic Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {......final Activity a performLaunchActivity(r, customIntent);......}private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {......Activity activity null;try {// 重点* 1. 通过Instrumentation 反射创建Activityjava.lang.ClassLoader cl appContext.getClassLoader();activity mInstrumentation.newActivity(cl, component.getClassName(), r.intent);......}try {......// 重点* 2. 执行 attach 流程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.activityConfigCallback,r.assistToken, r.shareableActivityToken);......if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {重点* 3. onCreate流程mInstrumentation.callActivityOnCreate(activity, r.state);}}......}这里有3个重点 Activity 是通过反射创建的。 到这里其实 Activity 启动流程基本分析完了 执行 Activity::attach 。这里会触发创建 Window 触发 Activity::onCreate
Activity 已经创建好了那就剩下 onCreate 了。
# Instrumentationpublic void callActivityOnCreate(Activity activity, Bundle icicle) {prePerformCreate(activity);// onCreate流程activity.performCreate(icicle);postPerformCreate(activity);}# Activityfinal void performCreate(Bundle icicle) {performCreate(icicle, null);}final void performCreate(Bundle icicle, PersistableBundle persistentState) {......if (persistentState ! null) {onCreate(icicle, persistentState);} else {// 执行onCreateonCreate(icicle);}......}写过应用的都知道默认都是一个参数的onCreate。
至此Activity 启动流程分析完毕。 在 ActivityTaskSupervisor::realStartActivityLocked 方法看到给事务加了个 ResumeActivityItem 因为 LaunchActivityItem 只是创建但是创建完成后需要执行到对应的生命周期。 正常情况都是希望执行到onResume所以会设置 ResumeActivityItem 。 4.3 阶段四小结 无论是阶段二还是阶段三触发了 ActivityTaskSupervisor::realStartActivityLocked 方法并且还满足启动 Activity 条件则会触发应用端进程 Activity 的创建和生命周期的执行。