这里,我们可以看到,Instrumentation.execStartActivity()调用了ActivityTaskManager.getService().startActivity()将启动活动委托给了某个“服务”执行,我们来看看这个“服务”是什么。
ActivityTaskManager.getService()
{@link android.app.ActivityTaskManager}
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton IActivityTaskManagerSingleton =
new Singleton() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};
这里代码的作用其实是通过获取IBinder类型的服务生产一个启动活动的代理类,实现方式: 使用的是名为ACTIVITY_TASK_SERVICE的IBinder生产了一个IActivityTaskManager。
使用过AIDL的同学应该看出来了,这里类似的,也是通过跨进程通信的方式操作的。
IActivityTaskManager.startActivity()
由于我们没办法直接获取到IActivityTaskManager的实现类,我们通过搜索IActivityTaskManager.Stub的实现类来寻找前面提到的“服务”具体是什么。

由上图可知,这个“服务”应该就是com.android.server.wm.ActivityTaskManagerService,我们找到startActivity()方法,验证其入参是否一致:
{@link com.android.server.wm.ActivityTaskManagerService}
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
通过入参比对,基本确认此方法是Instrumentation.execStartActivity()中调用ActivityTaskManager.getService().startActivity()的后续流程了。
ActivityTaskManagerService.startActivityAsUser
startActivityAsUser包含一系列重载方法,最终都是执行以下代码:
{@link com.android.server.wm.ActivityTaskManagerService}
private int startActivityAsUser(IApplicationThread caller, String callingPackage,
@Nullable String callingFeatureId, Intent intent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
assertPackageMatchesCallingUid(callingPackage);
enforceNotIsolatedCaller(“startActivityAsUser”);
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), “startActivityAsUser”);
// TODO: Switch to user app stacks here.
// 注意这里的caller为 IApplicationThread
return getActivityStartController().obtainStarter(intent, “startActivityAsUser”)
.setCaller(caller)
.setCallingPackage(callingPackage)
.setCallingFeatureId(callingFeatureId)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setUserId(userId)
.execute();
}
这里主要通过工厂生产出ActivityStarter对象,并调用execute()执行。
ActivityStarter.execute()
由该方法注释我们可知其作用:
根据前面提供的请求参数解析必要的信息,并执行开始启动活动旅程的请求。
{@link com.android.server.wm.ActivityStarter}
{@link }
int execute() {
try {
// 此处省略代码
int res;
synchronized (mService.mGlobalLock) {
// 此处省略代码
res = executeRequest(mRequest);
Binder.restoreCallingIdentity(origId);
// 此处省略代码
return getExternalResult(mRequest.waitResult == null ? res
: waitForResult(res, mLastStartActivityRecord));
}
} finally {
onExecutionComplete();
}
}
而这个方法的核心是调用executeRequest(mRequest),由于代码较长,此处省略具体实现:
{@link com.android.server.wm.ActivityStarter}
private int executeRequest(Request request) {
// 省略其他定义
final IApplicationThread caller = request.caller;
final IBinder resultTo = request.resultTo;
// 省略其他检查代码
// 检查权限等
boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
requestCode, callingPid, callingUid, callingPackage, callingFeatureId,
request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord, resultStack);
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);
abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
callingPackage);
// 省略其他检查及设置状态代码
// 创建ActivityRecord,注意此处callerApp为 对 IApplicationThread的封装
final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, callingFeatureId, intent, resolvedType, aInfo,
mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode,
request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions,
sourceRecord);
mLastStartActivityRecord = r;
// 省略代码
mService.onStartActivitySetDidAppSwitch();
mController.doPendingActivityLaunches(false);
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
restrictedBgActivity, intentGrants);
if (request.outActivity != null) {
request.outActivity[0] = mLastStartActivityRecord;
}
return mLastStartActivityResult;
}
executeRequest 做了基本的启动检查,创建包含IApplicationThread对象的Activity的表示类ActivityRecord(历史堆栈中的一个条目,表示一个活动),并最终调用 startActivityUnchecked() 方法,startActivityUnchecked()中主要调用 startActivityInner() 方法:
{@link com.android.server.wm.ActivityStarter}
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
// 省略代码
// 计算是否有一个现有的任务可用于加载Activity。
final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
final boolean newTask = targetTask == null;
// 省略以下代码:
// 以下判断主要针对目标Activity
// 判断是否正在栈顶
// 判断并执行是否可以栈顶复用
// 判断并执行是否需要开启新栈
// 判断并执行是否移动到栈顶(singleTask弹栈)
// =====
// 操作目标Activity栈,启动模式、转场动画相关逻辑
mTargetStack.startActivityLocked(mStartActivity, topStack.getTopNonFinishingActivity(),
newTask, mKeepCurTransition, mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isTopActivityFocusable()
|| (topTaskActivity != null && topTaskActivity.isTaskOverlay()
&& mStartActivity != topTaskActivity)) {
// 如果该活动是不可调焦的,我们不能恢复它,但仍然希望确保它在开始时可见(这也将触发进入动画)。
// 这方面的一个例子是PIP活动。同样,我们不希望在一个任务中恢复当前有覆盖的活动,因为开始的活动只是需要在可见的暂停状态,直到覆盖被删除。
// 传递{@code null}作为start参数可以确保所有活动都是可见的。
mTargetStack.ensureActivitiesVisible(null /* starting /,
0 / configChanges */, !PRESERVE_WINDOWS);
// 继续并告诉窗口管理器为这个活动执行应用程序过渡,因为应用程序过渡不会通过resume通道触发。
mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
} else {
// 如果目标堆栈之前不是可调焦的(该堆栈上之前的top运行活动不可见),那么之前任何将该堆栈移动到该堆栈的调用都不会更新被调焦的堆栈。
// 如果现在启动新的活动允许任务堆栈可调焦,那么请确保我们现在相应地更新已调焦的堆栈。
if (mTargetStack.isTopActivityFocusable()
&& !mRootWindowContainer.isTopDisplayFocusedStack(mTargetStack)) {
mTargetStack.moveToFront(“startActivityInner”);
}
mRootWindowContainer.resumeFocusedStacksTopActivities(
mTargetStack, mStartActivity, mOptions);
}
}
mRootWindowContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
// 当活动启动时,立即更新最近任务列表
mSupervisor.mRecentTasks.add(mStartActivity.getTask());
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetStack);
return START_SUCCESS;
}
由于这里代码较长,故忽略了大量代码,我们对这个方法的功能做一个简单的总结:
- 根据当前栈的情况,判断目标Activity入栈操作:是否需要新栈,是否栈顶复用,是否弹栈等
- 转场动画相关操作
- 判断目标活动是否可获得焦点,执行对应操作
那么,在判断目标活动是否可获得焦点的分支里,我们启动的activity自然是需要焦点(可见可操作)的,所以我们主要关注mRootWindowContainer.resumeFocusedStacksTopActivities(mTargetStack, mStartActivity, mOptions);.
RootWindowContainer.resumeFocusedStacksTopActivities()
{@link com.android.server.wm.RootWindowContainer}
boolean resumeFocusedStacksTopActivities(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (!mStackSupervisor.readyToResume()) {
return false;
}
boolean result = false;
// 如果目标在栈顶展示区域,则调用(状态模式)ResumeActivityItem执行resume操作
if (targetStack != null && (targetStack.isTopStackInDisplayArea()
|| getTopDisplayFocusedStack() == targetStack)) {
result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
// 省略展示区域相关判断及计算
if (!resumedOnDisplay) {
// 在没有有效活动的情况下(例如,设备刚刚启动或启动程序崩溃),可能什么都没有恢复显示。
// 显式地请求集中堆栈中的top活动的resume将确保至少home活动被启动和恢复,并且不会发生递归。
final ActivityStack focusedStack = display.getFocusedStack();
if (focusedStack != null) {
result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
} else if (targetStack == null) {
result |= resumeHomeActivity(null /* prev */, “no-focusable-task”,
display.getDefaultTaskDisplayArea());
}
}
}
return result;
}
观察上述代码,主要做了以下事情:
- 如果目标已展示在栈顶可见区域,则执行resume
- 如果不存在有效的活动(崩溃或首次启动),则启动首页
- 如果存在有效活动(存在有焦点的栈),继续执行启动流程
此处,我们以存在有效活动为条件,继续关注启动流程,跟进resumeTopActivityUncheckedLocked();
ActivityStack.resumeTopActivityUncheckedLocked()
{@link com.android.server.wm.ActivityStack}
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mInResumeTopActivity) {
// (如果在栈顶可见),甚至不要开始递归.
return false;
}
boolean result = false;
try {
// 防止递归。
mInResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
// 当恢复top活动时,可能需要暂停top活动(例如,返回锁屏。
// 我们在{@link #resumeTopActivityUncheckedLocked}中取消了正常的暂停逻辑,因为顶部活动在结束时恢复。我们在这里再次调用{@link ActivityStackSupervisor# checkreadyforsleepplocked}来确保任何必要的暂停逻辑发生。
// 在不考虑锁屏的情况下,活动将被显示,对{@link ActivityStackSupervisor# checkreadyforsleepplocked}的调用被跳过。
final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
if (next == null || !next.canTurnScreenOn()) {
checkReadyForSleep();
}
} finally {
mInResumeTopActivity = false;
}
return result;
}
观察代码,这里主要做了防止递归调用的措施,以及调用了resumeTopActivityInnerLocked()方法,代码较长,此处将做忽略和拆解:
{@link com.android.server.wm.ActivityStack}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
// 忽略部分判断
if (!hasRunningActivity) {
// 栈里没有活动了,我们去别的地方看看。
// 备注:注意,此处可能会出现递归调用,即会调用前面的流程:RootWindowContainer.resumeFocusedStacksTopActivities()
// 这里也是前序流程中防范递归的原因
return resumeNextFocusableActivityWhenStackIsEmpty(prev, options);
}
// 省略大量代码
// 执行栈中其他activity的pause操作
// 我们正在启动下一个活动,因此告诉窗口管理器前一个活动将很快被隐藏。这样它就可以知道在计算所需的屏幕方向时忽略它。
if (next.attachedToProcess()) {
// 更新进程信息
// 检查特殊场景,例如半透明Activity等
}else {
// 哎呀,需要重新启动这个Activity!
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
next.showStartingWindow(null /* prev /, false / newTask /,
false / taskSwich */);
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
mStackSupervisor.startSpecificActivity(next, true, true);
}
return true;
}
代码比较长,其中大部分的操作在上述代码的注释中有说明,此处不做过多关注,我们看到与startActivity()有关的代码为mStackSupervisor.startSpecificActivity(next, true, true), 我们来看一下它的作用是什么。
ActivityStackSupervisor.startSpecificActivity()
Supervisor :主管。这个类字面意思是活动栈的主管,它的作用从注释中可以了解到:
- 将与层次结构相关的东西移动到RootWindowContainer
- 将与活动生命周期相关的东西移动到一个新的类ActivityLifeCycler中
- 移动接口事物到ActivityTaskManagerService。
- 所有其他的小事情到其他文件。
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity’s application already running?
// 真是个糟糕的注释,让我想起了偶尔会遇到的一个报错 ┗|`O′|┛
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
// 如果applicationThread存在,则执行真实的启动Activity
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
- r.intent.getComponent().flattenToShortString(), e);
}
// 如果抛出了死对象异常——重新启动应用程序。
knownToBeDead = true;
}
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
final boolean isTop = andResume && r.isTopRunningActivity();
// 若applicationThread不存在,将启动新的进程
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? “top-activity” : “activity”);
}
上述代码中,主要做了三次校验:
- 若目标ApplicationThread对象存在,则继续执行启动流程
- 若启动流程执行失败,则重启应用程序
- 若目标ApplicationThread对象不存在,则启动新的进程;此流程暂不做关注,可自行跟进,最终会调用ActivityManagerService.startProcessLocked()及后续ZygoteProcess相关方法。
ActivityStackSupervisor.realStartActivityLocked()
ActivityStackSupervisor.realStartActivityLocked()基本算得上启动流程中相当重要的一部分了,基本算得上是调用链的结束,后续将执行目标ActivityThread执行Launch操作,故单独做一小节讲述。
{@link com.android.server.wm.ActivityStackSupervisor}
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
if (!mRootWindowContainer.allPausedActivitiesComplete()) {
// 当有活动暂停时,我们跳过开始任何新的活动,直到暂停完成。
// 注意:对于在暂停状态下启动的活动,我们也会这样做,因为它们首先会被恢复,然后在客户端暂停。
// 思考:那么,你会担心当此启动未成功吗?可还记得。我们启动流程其实包含递归操作,如果此次中断,不代表后续就不再执行启动操作了。
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
“realStartActivityLocked: Skipping start of r=” + r
- " some activities pausing…");
return false;
}
// 省略大量代码
// 因为我们可能会在系统进程中启动一个活动,所以这可能不会跨越创建新配置的绑定器接口。因此,我们必须总是在这里创建一个新的配置。
final MergedConfiguration mergedConfiguration = new MergedConfiguration(
proc.getConfiguration(), r.getMergedOverrideConfiguration());
r.setLastReportedConfiguration(mergedConfiguration);
logIfTransactionTooLarge(r.intent, r.getSavedState());
// 创建活动启动事务。
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
final DisplayContent dc = r.getDisplay().mDisplayContent;
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode®, r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
r.assistToken, r.createFixedRotationAdjustmentsIfNeeded()));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
// 再次省略大量代码
// 设置活动状态后,执行OOM评分,使流程可以更新为最新状态。
proc.onStartActivity(mService.mTopProcessState, r.info);
//如果需要,启动新版本设置屏幕。我们在启动初始化的activity(即home)之后做这个操作,这样它就有机会在后台初始化自己,使切换回它更快,看起来更好。
if (mRootWindowContainer.isTopDisplayFocusedStack(stack)) {
mService.getActivityStartController().startSetupActivity();
}
// 更新我们绑定到的任何可能关心其客户端是否有活动的服务。
if (r.app != null) {
r.app.updateServiceConnectionActivities();
}
return true;
}
从上述代码及注释我们可知,realStartActivityLocked的主要功能是:
- 若有正在pause的活动,等待它操作完毕
- 创建 LaunchActivityItem (启动Activity的策略/状态)并封装成事务
- 执行启动Activity的事务
- 更新进程信息及其他相关服务
那么,我们知道activity启动流程的最后两步即是:创建 LaunchActivityItem 及执行 ClientTransaction,这里我们分两各部分介绍,先介绍 ClientTransaction 的调用流程,再介绍 LaunchActivityItem 是什么。
执行LaunchActivityItem事务
ActivityStackSupervisor.realStartActivityLocked()中调用的mService.getLifecycleManager().scheduleTransaction(clientTransaction);实际是ClientLifecycleManager.scheduleTransaction():
{@link com.android.server.wm.ClientLifecycleManager}
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
if (!(client instanceof Binder)) {
// 如果client不是Binder的实例——它是一个远程调用,此时可以安全地回收对象。
// 在ActivityThread的客户端上执行事务后,用于本地调用的所有对象都将被回收。
transaction.recycle();
}
}
这里主要调用了ClientTransaction.schedule():
{@link android.app.servertransaction.ClientTransaction}
/** Target client. */
private IApplicationThread mClient;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。





既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
总结:
各行各样都会淘汰一些能力差的,不仅仅是IT这个行业,所以,不要被程序猿是吃青春饭等等这类话题所吓倒,也不要觉得,找到一份工作,就享受安逸的生活,你在安逸的同时,别人正在奋力的向前跑,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。
-
BAT大厂面试题、独家面试工具包,
-
资料包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
且会持续更新!**
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
总结:
各行各样都会淘汰一些能力差的,不仅仅是IT这个行业,所以,不要被程序猿是吃青春饭等等这类话题所吓倒,也不要觉得,找到一份工作,就享受安逸的生活,你在安逸的同时,别人正在奋力的向前跑,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。
-
BAT大厂面试题、独家面试工具包,
-
资料包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter
[外链图片转存中…(img-u4RckFwm-1713690080899)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
本文详细解析了Android中Activity的启动流程,从Instrumentation.execStartActivity()开始,依次介绍了ActivityTaskManager.getService()、IActivityTaskManager.startActivity()等方法的调用过程,还阐述了ActivityStackSupervisor.realStartActivityLocked()的主要功能,包括创建LaunchActivityItem及执行事务等。
2782

被折叠的 条评论
为什么被折叠?



