文章目录
前言
在Activity启动过程中,ActivityManagerService会与APP进程进行交互,调度APP进程上的Activity的生成和初始化,以及生命周期的逐步切换和回调。
在这期间的调度交互中ActivityManagerService需要知道APP进程端的执行结果来进行下一步操作,因此ActivityManagerService需要一个超时判定机制,来应对APP进程端执行过久或无响应时的情况。
例如,当目标Activity所属进程未启动时,ActivityManagerService需要先请求Zygote创建进程,然后等待进程创建完毕后继续启动目标Activity,那么AMS如何监听进程启动是否太久呢?还有当启动目标Activity前,会先pause当前正显示的Activity,之后才显示目标Activity,那么AMS是否会无限期等待?
源码探究
文中源码基于Android 9.0
ActivityManagerService在调度Activity的各个阶段都需要超时处理,这里按照《Activity启动流程总结-生命周期》中的过程来分阶段看。
Activity pause阶段
Activity启动流程中,首先需要暂停当前正在显示的Activity。
超时的设置
[ActivityStack.java]
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean pauseImmediately) {
// ···
ActivityRecord prev = mResumedActivity;
// ···
mPausingActivity = prev;
// ···
if (prev.app != null && prev.app.thread != null) {
try {
// 调度APP进程执行对应Activity的pause行为
mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
PauseActivityItem.obtain(prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately));
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
} else {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
// ···
// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
// 获取Wakelock并设置超时监听
mStackSupervisor.acquireLaunchWakelock();
}
if (mPausingActivity != null) {
// ···
// pauseImmediately默认为false
if (pauseImmediately) {
// If the caller said they don't want to wait for the pause, then complete
// the pause now.
completePauseLocked(false, resuming);
return false;
} else {
// 设置超时监听
schedulePauseTimeout(prev);
return true;
}
} else {
// This activity failed to schedule the
// pause, so just treat it as being paused now.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
if (resuming == null) {
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
return false;
}
}
该方法中会设置两个超时,在通过scheduleTransaction方法调度Activity进行pause后,就调用acquireLaunchWakelock和schedulePauseTimeout方法进行超时设置。
LAUNCH_TIMEOUT_MSG
[ActivityStackSupervisor.java]
void acquireLaunchWakelock() {
if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
mLaunchingActivity.acquire();
if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
// To be safe, don't allow the wake lock to be held for too long.
mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
}
}
可以看出这里是通过mHandler发送延迟消息的方式来进行超时设置,what为LAUNCH_TIMEOUT_MSG,LAUNCH_TIMEOUT为10s。
PAUSE_TIMEOUT_MSG
[ActivityStack.java]
private void schedulePauseTimeout(ActivityRecord r) {
final Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
msg.obj = r;
r.pauseTime = SystemClock.uptimeMillis();
mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
}
通过mHandler发送延迟消息的方式来进行超时设置,Message的what赋值为PAUSE_TIMEOUT_MSG,obj为需要pause的ActivityRecord,pauseTime为系统启动以来时间。
[ActivityStack.java]
private static final int PAUSE_TIMEOUT = 500;
PAUSE_TIMEOUT表示500ms,留给Activity pause的时间很短,在500ms后就会触发超时。
mHandler的由来
- ActivityStack的mHandler成员在ActivityStack的构造函数中实例化:
[ActivityStack.java]
ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
int windowingMode, int activityType, boolean onTop) {
mHandler = new ActivityStackHandler(mService.mHandler.getLooper());
}
mHandler实例的类型为ActivityStackHandler(继承自Handler),通过ActivityManagerService的mHandler的成员的Looper创建。
- ActivityStackSupervisor的mHandler成员在构造函数中创建,其实例为ActivityStackSuper