Activity启动流程总结-超时判定机制

本文详细探讨了Android系统中ActivityManagerService在Activity启动、应用启动、暂停、停止和销毁等阶段的超时判定机制。从源码层面解析了每个阶段的超时设置、触发和取消过程,揭示了在APP进程执行过久或无响应时,AMS如何确保系统稳定运行的机制。
摘要由CSDN通过智能技术生成

前言

在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后,就调用acquireLaunchWakelockschedulePauseTimeout方法进行超时设置。

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值