Android8 从系统启动到用户见到第一个Activity的流程源码分析(二)

前文回顾:

Android8 从系统启动到用户见到第一个Activity的流程源码分析(一)-CSDN博客文章浏览阅读250次,点赞2次,收藏3次。本文分析了Android系统启动过程中AMS(ActivityManagerService)的systemReady方法及其关键流程。当SystemService调用AMS的systemReady方法后,AMS会初始化各类服务,清理不允许运行的进程,最终通过startHomeActivityLocked启动主屏幕Activity。该流程涉及多个关键步骤: 创建Home Intent并解析对应Activity信息 通过ActivityStarter启动主屏幕Activity 在startActivityLoc https://blog.csdn.net/g_i_a_o_giao/article/details/150958400?spm=1001.2014.3001.5502在上篇文章中,我们依次分析了从systemReady方法到startHomeActivityLocked方法,再到startHomeActivity方法,接着深入探讨了startActivityLocked方法和startActivity方法,最终对startActivityUnchecked方法进行了详细解析。

那么就来看看ActivityStarter.java中的startActivityUnchecked方法。首先就是初始化内部状态,然后就是获取可重用的Activity,但是在这里获取到的应该为null,然后就是判断包名是否存在,当然这里是存在的。然后就是一堆变量的设置,并且判断是不是新的任务。接下来就是调用方法ActivityStack.java的方法startActivityLocked,在目标任务栈中启动Activity。接下来由于之前调用startActivity方法传递的doResume为true,因此会进入ture分支判断可见性。又因为这是启动第一个Activity,那么这个Activity肯定是不可见的并且不在前台,就会调用ActivityStackSupervisor.java的resumeFocusedStackTopActivityLocked方法来resume一个Activity。

private ActivityStack mTargetStack;
rivate final ActivityStackSupervisor mSupervisor;
/*
  之前传递的doResumed为true
  return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,options, inTask, outActivity);
*/


// 注意:此方法只能从 {@link startActivity} 调用
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity) {

    // 1. 初始化内部状态
    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor);

    // 2. 计算启动任务标志
    computeLaunchingTaskFlags();

    // 3. 计算源堆栈
    computeSourceStack();

    // 4. 设置Intent的标志
    mIntent.setFlags(mLaunchFlags);

    // 5. 查找可重用的Activity
    ActivityRecord reusedActivity = getReusableIntentActivity();

    // 6. 获取优先启动的堆栈和显示ID
    final int preferredLaunchStackId =
            (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
    final int preferredLaunchDisplayId =
            (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;

    // 7. 处理可重用Activity的情况
    if (reusedActivity != null) {
        // 检查是否违反锁定任务模式
        if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
                (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
            mSupervisor.showLockTaskToast();
            Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }

        // 设置启动Activity的任务
        if (mStartActivity.getTask() == null) {
            mStartActivity.setTask(reusedActivity.getTask());
        }
        // 设置任务的基础Intent
        if (reusedActivity.getTask().intent == null) {
            reusedActivity.getTask().setIntent(mStartActivity);
        }

        // 处理CLEAR_TOP、单实例、单任务等标志
        if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                || isDocumentLaunchesIntoExisting(mLaunchFlags)
                || mLaunchSingleInstance || mLaunchSingleTask) {
            final TaskRecord task = reusedActivity.getTask();

            // 清除任务中到要启动的Activity之上的所有Activity
            final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
                    mLaunchFlags);

            // 确保reusedActivity仍然有任务引用
            if (reusedActivity.getTask() == null) {
                reusedActivity.setTask(task);
            }

            if (top != null) {
                if (top.frontOfTask) {
                    // 更新任务的Intent
                    top.getTask().setIntent(mStartActivity);
                }
                // 传递新的Intent
                deliverNewIntent(top);
            }
        }

        // 发送启动功率提示
        sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);

        // 设置目标堆栈并移动到前台
        reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);

        // 处理输出Activity
        final ActivityRecord outResult =
                outActivity != null && outActivity.length > 0 ? outActivity[0] : null;

        // 当有可重用Activity且当前结果是蹦床Activity时,设置可重用Activity为结果
        if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
            outActivity[0] = reusedActivity;
        }

        // 处理ONLY_IF_NEEDED标志
        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            // 不需要启动新Activity,只需恢复顶部Activity
            resumeTargetStackIfNeeded();
            return START_RETURN_INTENT_TO_CALLER;
        }
        
        setTaskFromIntentActivity(reusedActivity);

        // 如果没有添加到任务且没有重用任务,只需将任务带到前台
        if (!mAddingToTask && mReuseTask == null) {
            resumeTargetStackIfNeeded();
            if (outActivity != null && outActivity.length > 0) {
                outActivity[0] = reusedActivity;
            }
            return START_TASK_TO_FRONT;
        }
    }

    // 8. 检查包名是否存在
    if (mStartActivity.packageName == null) {
        final ActivityStack sourceStack = mStartActivity.resultTo != null
                ? mStartActivity.resultTo.getStack() : null;
        if (sourceStack != null) {
            sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
                    null /* data */);
        }
        ActivityOptions.abort(mOptions);
        return START_CLASS_NOT_FOUND;
    }

    // 9. 检查是否应该启动(单顶模式等)
    final ActivityStack topStack = mSupervisor.mFocusedStack;
    final ActivityRecord topFocused = topStack.topActivity();
    final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
    final boolean dontStart = top != null && mStartActivity.resultTo == null
            && top.realActivity.equals(mStartActivity.realActivity)
            && top.userId == mStartActivity.userId
            && top.app != null && top.app.thread != null
            && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
            || mLaunchSingleTop || mLaunchSingleTask);
    if (dontStart) {
        // 确保正确恢复顶部Activity
        topStack.mLastPausedActivity = null;
        if (mDoResume) {
            mSupervisor.resumeFocusedStackTopActivityLocked();
        }
        ActivityOptions.abort(mOptions);
        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            return START_RETURN_INTENT_TO_CALLER;
        }

        // 传递新的Intent
        deliverNewIntent(top);

        // 处理不可调整大小的任务
        mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
                preferredLaunchDisplayId, topStack.mStackId);

        return START_DELIVERED_TO_TOP;
    }

    // 10. 确定是否为新任务
    boolean newTask = false;
    final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
            ? mSourceRecord.getTask() : null;

    // 判断是否为新任务
    int result = START_SUCCESS;
    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;
        result = setTaskFromReuseOrCreateNewTask(
                taskToAffiliate, preferredLaunchStackId, topStack);
    } else if (mSourceRecord != null) {
        result = setTaskFromSourceRecord();
    } else if (mInTask != null) {
        result = setTaskFromInTask();
    } else {
        // 这种情况很少见,将其放在顶部任务中或创建新任务
        setTaskToCurrentTopOrCreateNewTask();
    }
    if (result != START_SUCCESS) {
        return result;
    }

    // 11. 授权URI权限和临时访问
    mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
            mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
    mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
            mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
    
    // 12. 设置返回任务
    if (mSourceRecord != null) {
        mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
    }
    
    // 13. 记录任务和Activity创建事件
    if (newTask) {
        EventLog.writeEvent(
                EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
                mStartActivity.getTask().taskId);
    }
    ActivityStack.logStartActivity(
            EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
    mTargetStack.mLastPausedActivity = null;

    // 14. 发送启动功率提示
    sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);

    // 15. 在目标堆栈中启动Activity
    mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
            mOptions);
    
    // 16. 处理resume或可见性
    if (mDoResume) {
        final ActivityRecord topTaskActivity =
                mStartActivity.getTask().topRunningActivityLocked();
        if (!mTargetStack.isFocusable()
                || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                && mStartActivity != topTaskActivity)) {
            // 如果Activity不可聚焦(如画中画)或当前有覆盖层,则确保可见但不resume
            mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
            mWindowManager.executeAppTransition();
        } else {
            // 如果目标堆栈可聚焦但不在前台,则移动到前台
            if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                mTargetStack.moveToFront("startActivityUnchecked");
            }
            // resume顶部Activity
            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                    mOptions);
        }
    } else {
        // 添加到最近活动列表
        mTargetStack.addRecentActivityLocked(mStartActivity);
    }
    
    // 17. 更新用户堆栈
    mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

    // 18. 处理不可调整大小的任务
    mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
            preferredLaunchDisplayId, mTargetStack.mStackId);

    return START_SUCCESS;
}

接下来分析frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java中的resumeFocusedStackTopActivityLocked方法。该方法主要是resume焦点栈顶部的Activity。因为这里传递的targetStack不为空,那么就会调用ActvityStack.java中的resumeTopActivityUnchecked

Locked方法

/**
 * 尝试恢复焦点栈顶部的Activity。
 * 这是一个同步方法,调用者需要持有AMS(ActivityManagerService)的相关锁。
 *
 * @param targetStack 目标Activity栈,如果非空且是当前焦点栈,则尝试恢复其顶部Activity
 * @param target 目标Activity记录,用于指定要恢复的具体Activity
 * @param targetOptions 启动选项,包含动画等参数
 * @return boolean 表示是否成功执行了恢复操作
 */
boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

    // 检查系统是否准备就绪可以执行Activity恢复操作
    if (!readyToResume()) {
        return false; // 系统未就绪,直接返回false
    }

    // 如果指定了目标栈且该栈正是当前焦点栈,则尝试恢复该栈顶部的Activity(执行这里的代码)
    if (targetStack != null && isFocusedStack(targetStack)) {
        // 调用目标栈的恢复方法,并返回其结果
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }

    // 获取当前焦点栈顶部正在运行的Activity记录
    final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    
    if (r == null || r.state != RESUMED) {
        // 情况1: 没有正在运行的Activity,或者顶部Activity不在RESUMED状态
        // 需要恢复焦点栈的顶部Activity
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    } else if (r.state == RESUMED) {
        // 情况2: 顶部Activity已处于RESUMED状态
        // 执行可能存在的挂起任务到前台的过渡动画
        mFocusedStack.executeAppTransition(targetOptions);
    }

    // 对于非焦点栈或不需要立即恢复的情况,返回false
    return false;
}

那么我们继续看一下ActivityStack.java中的resumeTopActivityUncheckedLocked方法。在这个方法中,主要是调用了resumeTopActivityInnerLocked方法来实现具体的逻辑。

/**
 * 确保栈顶的Activity被恢复到RESUMED状态。
 * 这是恢复Activity的核心入口方法,但通常不应直接调用。
 *
 * @param prev 先前处于RESUMED状态的Activity(通常正在执行PAUSE过程),可能为null。
 * @param options 启动选项,包含动画等参数。
 * @return 如果成功开始了某个Activity的恢复流程则返回true,否则返回false。
 *
 * 注意:直接调用此方法是不安全的,因为它可能导致非焦点栈中的Activity被恢复。
 *       正确的做法是使用 {@link ActivityStackSupervisor#resumeFocusedStackTopActivityLocked}
 *       来根据当前系统状态恢复正确的Activity。
 */
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    // 递归调用保护:检查全局标志,防止重入(例如在resume一个Activity时,它又触发了另一个resume)
    if (mStackSupervisor.inResumeTopActivity) {
        // 如果已经在执行resume操作,则直接返回,避免递归调用。
        return false;
    }

    boolean result = false;
    try {
        // 设置全局标志,表示开始执行resume操作,防止递归调用。
        mStackSupervisor.inResumeTopActivity = true;
        // 调用内部方法执行实际的恢复逻辑
        result = resumeTopActivityInnerLocked(prev, options);
    } finally {
        // 无论内部方法执行成功与否,最终都要清除全局标志,确保后续调用能正常进行。
        mStackSupervisor.inResumeTopActivity = false;
    }

    // 在恢复栈顶Activity的过程中,可能需要暂停当前的顶层Activity(例如,用户返回了锁屏界面)。
    // 上面的resumeTopActivityInnerLocked方法内部会处理正常的暂停逻辑。但有一种特殊情况:
    // 当最终要恢复的Activity就是当前已经Resumed的Activity时,正常的暂停逻辑会被抑制。
    // 因此,这里需要再次检查系统是否应该进入睡眠(准备暂停)状态。

    // 获取当前栈中真正可获取焦点的顶层Activity
    final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
    // 检查条件:如果下一个Activity为空,或者下一个Activity没有能力(或权限)点亮屏幕
    if (next == null || !next.canTurnScreenOn()) {
        // 调用检查准备进入睡眠的方法。这个方法会判断是否需要暂停当前Activity(比如设备即将休眠、锁屏等)。
        checkReadyForSleep();
    }

    // 返回内部方法执行的结果
    return result;
}

紧接着我们去分析resumeTopActivityInnerLocked方法。这个方法太长了足有500多行,本篇文章只截取其中一个比较关键的代码进行分析。进行一系列判断以后,最终调用到了ActivityStackSupervisor.java中的startSpecificActivityLocked方法。

 // Whoops, need to restart this 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.startSpecificActivityLocked(next, true, true);

那么再来看看这个startSpecificActivityLocked方法。在这个方法中首先判断目标Activity所存在的进程是否存在。如果存在的话直接在该进程中启动Activity,不存在则调用AMS中的startProcessLocked来启动一个新的应用进程。从这里可以看出Android在启动Activity中“进程先于Activity”的核心原则。

final ActivityManagerService mService;

/**
 * 启动一个特定的Activity。此方法负责判断是该Activity所属的应用进程是否已经运行,
 * 并根据判断结果决定是直接启动Activity还是先启动应用进程。
 * 这是一个同步方法,调用者需要持有AMS(ActivityManagerService)的相关锁。
 *
 * @param r 要启动的Activity的记录(ActivityRecord)
 * @param andResume 是否在启动后立即将其置为RESUMED状态(true),还是只走到STARTED状态(false)
 * @param checkConfig 是否检查配置变更(例如屏幕旋转)并等待Activity处理
 */
void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {

    // 1. 检查目标Activity所需的应用程序进程是否已经存在并运行。
    // 通过进程名和UID来查询进程记录(ProcessRecord)
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);

    // 为此Activity设置启动时间戳,用于后续性能分析和ANR判断
    r.getStack().setLaunchTime(r);

    // 2. 如果找到了对应的进程记录,并且该进程的ApplicationThread(与应用进程通信的Binder代理)不为空
    if (app != null && app.thread != null) {
        try {
            // 检查Activity的配置标志:FLAG_MULTIPROCESS
            // 通常,一个应用的组件默认运行在同一个进程中。此标志允许Activity运行在一个新的专属进程中。
            // 但同时需要排除Android系统核心组件("android"包),因为它们是框架的一部分,
            // 即使标记为多进程,也不应作为独立的APK在进程统计信息中进行跟踪。
            if ((r.info.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                // 将此Activity所在的包名和版本码添加到进程的包列表中。
                // 这用于进程管理(例如:当该包被更新时,需要重启进程)和统计信息收集。
                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                        mService.mProcessStats);
            }
            // 3. 核心方法:进程已存在,直接在该进程中启动目标Activity
            realStartActivityLocked(r, app, andResume, checkConfig);
            // 启动成功,直接返回
            return;

        } catch (RemoteException e) {
            // 捕获远程异常。如果与应用进程的通信失败(例如进程刚刚意外死亡),
            // 记录日志并继续执行下面的代码,走启动新进程的流程。
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }

        // 如果上面的try块中抛出了DeadObjectException(是RemoteException的一种),
        // 代码会执行到这里。此时app.thread可能已经无效,需要 fall through 到下面的逻辑去重启应用进程。
    }

    // 4. 如果进程不存在,或者进程存在但通信失败(app == null || app.thread == null || 发生异常)
    // 则调用AMS的方法来启动一个新的应用进程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", // 启动原因,表示为启动一个Activity而创建进程
            r.intent.getComponent(), // 目标组件,用于调试信息
            false, // 已知该进程当前不运行
            false, // 不设置为持久进程
            true); // 允许在启动时使用isolated(隔离)进程(如果该Activity配置了isolatedProcess属性)
}

那我们继续分析startProcessLocked方法。它内部又调用了重载的startProcessLocked方法,继续分析这个重载方法。由于传递的isolated标志位为false,因此app这个变量会置为null。那么接下来就会调用newProcessRecordLocked方法来创建一个新的ProcessRecord。最后会调用另一个重载方法startProcessLocked。

// 这里的isolated为false
final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        // 调用自身的重载方法startProcessLocked
        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }



/**
 * 启动或准备一个应用进程。这是一个核心方法,处理进程的创建、复用和清理。
 * 这是一个同步方法,调用者需要持有AMS(ActivityManagerService)的相关锁。
 *
 * @param processName 要启动的进程名
 * @param info 要启动的ApplicationInfo
 * @param knownToBeDead 调用者是否已知该进程已经死亡。如果为true,即使找到现有进程记录也会认为其无效。
 * @param intentFlags 启动这个进程的Intent的Flags,用于判断是否来自后台
 * @param hostingType 宿主类型(例如"activity", "service", "receiver"等),描述为何启动此进程
 * @param hostingName 宿主组件的ComponentName,用于调试和错误报告
 * @param allowWhileBooting 是否允许在系统还未完全启动完成(booting)时启动此进程
 * @param isolated 是否启动一个隔离进程(isolated process)
 * @param isolatedUid 如果是隔离进程,指定的UID
 * @param keepIfLarge 如果进程因为占用内存过大而被杀后,是否保留其进程记录
 * @param abiOverride 要覆盖的ABI(应用程序二进制接口),例如强制使用32位模式
 * @param entryPoint 入口点,通常为null(使用默认的"android.app.ActivityThread")
 * @param entryPointArgs 传递给入口点的参数
 * @param crashHandler 进程崩溃时的处理Runnable
 * @return ProcessRecord 返回进程记录。如果进程启动失败或因为某些原因被阻止,则返回null。
 */
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
        boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
        boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
        String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {

    long startTime = SystemClock.elapsedRealtime(); // 记录开始时间,用于性能分析
    ProcessRecord app;

    // 1. 处理非隔离进程:尝试获取已存在的进程记录并检查"坏进程"状态
    if (!isolated) {
        // 查询是否已有该进程名的记录
        app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
        checkTime(startTime, "startProcess: after getProcessRecord"); // 记录耗时点

        // 根据启动来源(前台/后台)处理“坏进程”逻辑
        if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
            // 后台启动:如果该进程已被标记为“坏进程”(例如连续崩溃),则静默失败,不启动。
            if (mAppErrors.isBadProcessLocked(info)) {
                if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
                        + "/" + info.processName);
                return null; // 静默返回null
            }
        } else {
            // 前台启动(例如用户点击图标):清除此进程的崩溃计数,给它一个新的机会。
            // 如果它之前被标记为“坏进程”,现在将其重置为“好进程”。
            if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
                    + "/" + info.processName);
            mAppErrors.resetProcessCrashTimeLocked(info); // 重置最近崩溃时间
            if (mAppErrors.isBadProcessLocked(info)) {
                // 记录事件日志,标记进程变好
                EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                        UserHandle.getUserId(info.uid), info.uid,
                        info.processName);
                mAppErrors.clearBadProcessLocked(info); // 从坏进程列表中清除
                if (app != null) {
                    app.bad = false; // 清除进程记录本身的坏标记
                }
            }
        }
    } else {
        // 2. 对于隔离进程,它不能复用任何现有进程,所以将app设为null,强制走创建新流程。
        app = null;
    }

    // 3. 决策点:检查是否可以直接复用现有的进程记录
    // 满足以下所有条件则可以复用:
    //   a) 找到了现有的进程记录 (app != null)
    //   b) 该进程有PID(pid > 0),意味着它正在运行或正在启动
    //   c) 并且满足以下条件之一:
    //        i)  调用者不认为它已死 (!knownToBeDead) 且它未被杀死 (!app.killed)
    //        ii) 进程记录还没有绑定ApplicationThread对象 (app.thread == null),
    //            这意味着进程正在启动中,我们只需等待它准备好。
    if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName
            + " app=" + app + " knownToBeDead=" + knownToBeDead
            + " thread=" + (app != null ? app.thread : null)
            + " pid=" + (app != null ? app.pid : -1));

    if (app != null && app.pid > 0) {
        if ((!knownToBeDead && !app.killed) || app.thread == null) {
            // 可以复用现有进程!
            if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
            // 将新包添加到进程的包列表中(如果尚未添加),用于后续管理
            app.addPackage(info.packageName, info.versionCode, mProcessStats);
            checkTime(startTime, "startProcess: done, added package to proc");
            return app; // 直接返回现有的进程记录
        }

        // 4. 如果找到进程记录,但它已经死亡(knownToBeDead为true 或 app.killed为true),
        //    并且已经有thread对象(说明之前完全启动过),那么需要先清理这个死亡的进程。
        if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app);
        checkTime(startTime, "startProcess: bad proc running, killing");
        // 杀死进程组(确保所有子进程都被清理)
        killProcessGroup(app.uid, app.pid);
        // 处理进程死亡的回调,清理内部状态
        handleAppDiedLocked(app, true, true);
        checkTime(startTime, "startProcess: done killing old proc");
    }

    String hostingNameStr = hostingName != null
            ? hostingName.flattenToShortString() : null;

    // 5. 此时,如果没有可用的进程记录,则需要创建一个新的。
    if (app == null) {
        checkTime(startTime, "startProcess: creating new process record");
        app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
        if (app == null) {
            // 创建失败记录日志并返回
            Slog.w(TAG, "Failed making new process record for "
                    + processName + "/" + info.uid + " isolated=" + isolated);
            return null;
        }
        // 设置崩溃处理器
        app.crashHandler = crashHandler;
        checkTime(startTime, "startProcess: done creating new process record");
    } else {
        // 6. 如果app不为null(走到这里说明是上面第4步清理了旧进程后,app记录被保留了下来),
        //    则将新包信息添加到这个将要被复用的ProcessRecord中。
        app.addPackage(info.packageName, info.versionCode, mProcessStats);
        checkTime(startTime, "startProcess: added package to existing proc");
    }

    // 7. 检查系统状态:如果系统尚未准备就绪,并且此进程不允许在启动时运行,
    //    则将其加入等待队列(mProcessesOnHold),延迟启动。
    if (!mProcessesReady // 系统未就绪
            && !isAllowedWhileBooting(info) // 该应用本身不允许在启动时运行
            && !allowWhileBooting) { // 调用者没有特别允许此次启动在启动时运行
        if (!mProcessesOnHold.contains(app)) {
            mProcessesOnHold.add(app); // 加入等待队列
        }
        if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
                "System not ready, putting on hold: " + app);
        checkTime(startTime, "startProcess: returning with proc on hold");
        return app; // 返回进程记录,但此时进程尚未真正启动
    }

    // 8. 所有条件都已满足,真正开始启动进程!
    checkTime(startTime, "startProcess: stepping in to startProcess");
    // 调用另一个重载方法,执行fork进程等实际操作
    startProcessLocked(
            app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
    checkTime(startTime, "startProcess: done starting proc!");

    // 9. 返回进程记录。如果进程启动成功,app.pid会被设置为非0值。
    return (app.pid != 0) ? app : null;
}


那么再来看这个重载的startProcessLocked方法。在这个方法中进行一些列的权限检验,环境配置以及参数准备。然后就是调用最核心的代码Process.java的start方法。

/**
 * 真正启动应用进程的核心方法。该方法准备所有参数,并通过Zygote fork出新进程。
 * 这是一个同步方法,调用者需要持有AMS(ActivityManagerService)的相关锁。
 *
 * @param app 要启动的进程记录(ProcessRecord),其pid字段将被更新
 * @param hostingType 宿主类型(如"activity", "service"等),用于描述启动原因
 * @param hostingNameStr 宿主组件的字符串表示,用于调试和日志
 * @param abiOverride 要覆盖的ABI(应用程序二进制接口),例如强制使用32位模式
 * @param entryPoint 入口点类名,如果为null则默认为"android.app.ActivityThread"
 * @param entryPointArgs 传递给入口点的参数
 */
private final void startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {

    long startTime = SystemClock.elapsedRealtime(); // 记录开始时间,用于性能分析和超时判断

    // 1. 清理旧的PID映射(如果存在)
    // 这种情况发生在进程之前启动过但死亡了,现在重新启动它。需要清理旧的状态。
    if (app.pid > 0 && app.pid != MY_PID) { // MY_PID是system_server自己的PID,不能清理自己
        checkTime(startTime, "startProcess: removing from pids map");
        synchronized (mPidsSelfLocked) {
            // 从PID映射表中移除旧的PID项
            mPidsSelfLocked.remove(app.pid);
            // 移除可能存在的进程启动超时消息
            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
        }
        checkTime(startTime, "startProcess: done removing from pids map");
        app.setPid(0); // 将进程记录的PID重置为0,表示尚未分配有效PID
    }

    // 2. 如果此进程之前被放在保持队列中(因为系统未就绪),现在启动它,所以从队列中移除
    if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) {
        Slog.v(TAG_PROCESSES, "startProcessLocked removing on hold: " + app);
    }
    mProcessesOnHold.remove(app);

    // 3. 更新CPU统计信息,为即将到来的新进程负载做准备
    checkTime(startTime, "startProcess: starting to update cpu stats");
    updateCpuStats();
    checkTime(startTime, "startProcess: done updating cpu stats");

    try {
        // 4. 安全检查:在启动前,通过PackageManager服务检查该包是否允许被启动
        //    例如,如果应用被管理员禁用或用户停用,这里会抛出异常。
        try {
            final int userId = UserHandle.getUserId(app.uid);
            AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }

        int uid = app.uid;
        int[] gids = null;
        int mountExternal = Zygote.MOUNT_EXTERNAL_NONE; // 外部存储挂载模式

        // 5. 为非隔离进程准备GID(组ID)和外部存储访问权限
        if (!app.isolated) {
            int[] permGids = null;
            try {
                checkTime(startTime, "startProcess: getting gids from package manager");
                final IPackageManager pm = AppGlobals.getPackageManager();
                // 从PackageManager获取此包声明所需的所有权限对应的GID
                permGids = pm.getPackageGids(app.info.packageName,
                        MATCH_DEBUG_TRIAGED_MISSING, app.userId);
                // 查询此外部存储的挂载模式(读、写、无访问权限)
                StorageManagerInternal storageManagerInternal = LocalServices.getService(
                        StorageManagerInternal.class);
                mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
                        app.info.packageName);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }

            // 构建完整的GID数组,包括:
            // - 权限GIDs (permGids)
            // - 共享应用GID (允许共享资源,如共享库)
            // - 缓存应用GID (访问缓存目录)
            // - 用户GID (访问用户范围的资源)
            if (ArrayUtils.isEmpty(permGids)) {
                gids = new int[3];
            } else {
                gids = new int[permGids.length + 3];
                System.arraycopy(permGids, 0, gids, 3, permGids.length);
            }
            gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
            gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
            gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
        }
        checkTime(startTime, "startProcess: building args");

        // 6. 工厂测试模式处理:在特定工厂测试模式下,允许某些进程以root权限运行
        if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {
            if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                    && mTopComponent != null
                    && app.processName.equals(mTopComponent.getPackageName())) {
                uid = 0; // root UID
            }
            if (mFactoryTest == FactoryTest.FACTORY_TEST_HIGH_LEVEL
                    && (app.info.flags & ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
                uid = 0; // root UID
            }
        }

        // 7. 设置调试标志(debugFlags),控制新进程的调试和行为选项
        int debugFlags = 0;
        if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
            // 可调试应用:启用JDWP、Java调试、CheckJNI
            debugFlags |= Zygote.DEBUG_ENABLE_JDWP;
            debugFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE;
            debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
        }
        // 安全模式:如果应用请求或系统处于安全模式,则在安全模式下运行
        if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
            mSafeMode == true) {
            debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
        }
        // 根据系统属性设置额外的调试选项
        if ("1".equals(SystemProperties.get("debug.checkjni"))) {
            debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
        }
        String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");
        if ("true".equals(genDebugInfoProperty)) {
            debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
        }
        if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
            debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
        }
        if ("1".equals(SystemProperties.get("debug.assert"))) {
            debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
        }
        // 本地调试:如果此进程是待调试的本地进程,则设置相关标志
        if (mNativeDebuggingApp != null && mNativeDebuggingApp.equals(app.processName)) {
            debugFlags |= Zygote.DEBUG_ALWAYS_JIT;          // 禁用解释模式,始终JIT
            debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; // 生成调试信息
            debugFlags |= Zygote.DEBUG_NATIVE_DEBUGGABLE;   // 禁用优化,便于本地调试
            mNativeDebuggingApp = null; // 重置,只调试一次
        }

        // 8. 包装脚本(invokeWith):对于可调试应用,检查是否存在wrap.sh脚本
        //    该脚本可用于在启动应用前设置环境变量等(如LD_PRELOAD)
        String invokeWith = null;
        if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
            String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh";
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
            try {
                if (new File(wrapperFileName).exists()) {
                    // 如果找到wrap.sh,则通过logwrapper执行它
                    invokeWith = "/system/bin/logwrapper " + wrapperFileName;
                }
            } finally {
                StrictMode.setThreadPolicy(oldPolicy);
            }
        }

        // 9. 确定目标ABI(应用程序二进制接口)和指令集
        String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
        if (requiredAbi == null) {
            requiredAbi = Build.SUPPORTED_ABIS[0]; // 默认使用主ABI
        }
        String instructionSet = null;
        if (app.info.primaryCpuAbi != null) {
            instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
        }

        // 10. 将计算出的值存回ProcessRecord,供后续使用
        app.gids = gids;
        app.requiredAbi = requiredAbi;
        app.instructionSet = instructionSet;

        // 11. 准备SELinux安全上下文(seInfo)
        //     SELinux是Android的重要安全机制,每个进程都必须有正确的上下文
        if (TextUtils.isEmpty(app.info.seInfoUser)) {
            Slog.wtf(TAG, "SELinux tag not defined",
                    new IllegalStateException("SELinux tag not defined for "
                    + app.info.packageName + " (uid " + app.uid + ")"));
        }
        // 拼接完整的seInfo字符串,包括用户部分
        final String seInfo = app.info.seInfo
                + (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);

        // 12. 核心调用:通过Zygote fork新进程
        boolean isActivityProcess = (entryPoint == null); // 判断是否是启动ActivityThread
        if (entryPoint == null) entryPoint = "android.app.ActivityThread"; // 默认入口点

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                app.processName); // 开始Trace,用于性能分析
        checkTime(startTime, "startProcess: asking zygote to start proc");
        ProcessStartResult startResult;
        if (hostingType.equals("webview_service")) {
            // WebView有特殊的启动路径
            startResult = startWebView(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, null, entryPointArgs);
        } else {
            // 正常应用启动:调用Process.start,最终通过socket与zygote通信,fork新进程
            startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, invokeWith, entryPointArgs);
        }
        checkTime(startTime, "startProcess: returned from zygote!");
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); // 结束Trace

        // 13. 进程启动成功后的后续处理
        mBatteryStatsService.noteProcessStart(app.processName, app.info.uid); // 更新电池统计
        checkTime(startTime, "startProcess: done updating battery stats");

        EventLog.writeEvent(EventLogTags.AM_PROC_START, // 写事件日志
                UserHandle.getUserId(uid), startResult.pid, uid,
                app.processName, hostingType,
                hostingNameStr != null ? hostingNameStr : "");

        try {
            // 通知PackageManager记录进程启动(用于应用待机分组等)
            AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.processName, app.uid,
                    seInfo, app.info.sourceDir, startResult.pid);
        } catch (RemoteException ex) {
            // 忽略RemoteException
        }

        // 14. 如果是持久化进程(persistent),通知Watchdog监控它
        if (app.persistent) {
            Watchdog.getInstance().processStarted(app.processName, startResult.pid);
        }

        // 15. 记录信息日志
        checkTime(startTime, "startProcess: building log message");
        StringBuilder buf = mStringBuilder;
        buf.setLength(0);
        buf.append("Start proc ");
        buf.append(startResult.pid);
        buf.append(':');
        buf.append(app.processName);
        buf.append('/');
        UserHandle.formatUid(buf, uid);
        if (!isActivityProcess) {
            buf.append(" [");
            buf.append(entryPoint);
            buf.append("]");
        }
        buf.append(" for ");
        buf.append(hostingType);
        if (hostingNameStr != null) {
            buf.append(" ");
            buf.append(hostingNameStr);
        }
        Slog.i(TAG, buf.toString());

        // 16. 更新ProcessRecord状态
        app.setPid(startResult.pid);          // 设置新分配的PID
        app.usingWrapper = startResult.usingWrapper; // 是否使用了包装脚本
        app.removed = false;                  // 重置移除标志
        app.killed = false;                   // 重置被杀标志
        app.killedByAm = false;               // 重置被AMS杀死标志

        // 17. 更新PID映射表并设置启动超时监控
        checkTime(startTime, "startProcess: starting to update pids map");
        ProcessRecord oldApp;
        synchronized (mPidsSelfLocked) {
            oldApp = mPidsSelfLocked.get(startResult.pid);
        }
        // 18. 处理PID冲突:如果新分配的PID已经被另一个进程记录占用(通常是因为进程死亡后Linux内核快速重用了PID),则需要清理旧的进程记录。
        if (oldApp != null && !app.isolated) {
            Slog.w(TAG, "Reusing pid " + startResult.pid
                    + " while app is still mapped to it");
            cleanUpApplicationRecordLocked(oldApp, false, false, -1,
                    true /*replacingPid*/);
        }
        synchronized (mPidsSelfLocked) {
            // 将新的<PID, ProcessRecord>映射添加到全局表中
            this.mPidsSelfLocked.put(startResult.pid, app);
            if (isActivityProcess) {
                // 设置进程启动超时监控:如果进程在指定时间内没有成功附加到AMS,则视为启动失败
                Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
                msg.obj = app;
                mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                        ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
            }
        }
        checkTime(startTime, "startProcess: done updating pids map");

    } catch (RuntimeException e) {
        // 19. 异常处理:如果进程启动过程中发生任何异常(如Zygote通信失败、包被冻结等)
        Slog.e(TAG, "Failure starting process " + app.processName, e);

        // 强制停止该包,清理任何相关的状态。这通常发生在包被冻结(例如正在升级)时。
        forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false,
                false, true, false, false, UserHandle.getUserId(app.userId), "start failure");
    }
}

关于Progress.java中的start方法,主要就是通过socket和Zygote通信来fork一个子进程,将会在下篇文章中进行详细讲解。
这里进行一个小的总结,可以看出要启动第一个Activity,调用流程还是比较复杂的。不过最核心的还是先fork一个进程供给Activity启动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值