Android 启动过程Activity 启动源码分析 ( AMS -> ActivityThreadAMS 线程阶段 )

Posted 韩曙亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 启动过程Activity 启动源码分析 ( AMS -> ActivityThreadAMS 线程阶段 )相关的知识,希望对你有一定的参考价值。





一、Activity 启动源码分析 ( AMS | ActivityManagerService )




1、Instrumentation 调用 AMS 方法


在 Instrumentation 中 , 通过调用 ActivityManagerService ( AMS ) 的 startActivity 方法 ,

			// 在此处调用 AMS , Binder 机制获取 AMS
            int result = ActivityManager.getService()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);

调用的是 AMS 的 startActivity 10 10 10 个参数的方法 , 在该方法中又掉了 11 11 11 个参数的 startActivityAsUser 方法 ; 在 startActivityAsUser 方法中 , 主要是确保要打开的 Activity 在 androidManifest.xml 清单文件中注册过 ;

在插件化中 , 要在执行该 AMS 方法之前 , 使用在清单文件中注册过的占坑 Activity 替换插件 Activity , 借此骗过 AMS ;

AMS 相关源码如下 :

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
    }
}

ActivityManagerService 完整源码参考 : frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java


2、ActivityStarter 调用 AMS 方法


ActivityStarter.startActivityUnchecked 中调用了 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); 方法 , 显示栈顶元素 ,

mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); 中, 调用了 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); 方法启动新进程 ;

最终在 private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) 方法中 , 调用了Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, entryPointArgs) 方法 , 开启新的进程 ;

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
        
    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
            if (hostingType.equals("webview_service")) {
                startResult = startWebView(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, entryPointArgs);
            } else {
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, entryPointArgs);
            }
	}
}

ActivityManagerService 完整源码参考 : frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java


3、Process 启动新进程


AMS 的 void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) 方法中 , 调用了 startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, entryPointArgs); 启动新进程 , 该方法原型如下 :

    /**
     * 开始一个新的过程。
     *
     * <p>如果启用了流程,则会创建一个新流程,并且
     * 在那里执行<var>processClass</var>的静态main()函数。
     * 此函数返回后,进程将继续运行。
     *
     * <p>如果未启用进程,则在调用方的
     * 进程被创建,并在那里调用<var>processClass</var>的main()。
     *
     * <p>niceName参数(如果不是空字符串)是要使用的自定义名称
     * 指定给进程,而不是使用processClass。这允许您
     * 即使使用相同的基础,也要创建易于识别的流程
     * <var>processClass</var>启动它们。
     *
     * 当invokeWith不为null时,该进程将作为新应用程序启动
     * 而不是合子叉。请注意,这仅适用于uid 0或以下情况
     * runtimeFlags包含调试\\启用\\调试器。
     *
     * @param processClass 要用作进程主项的类
     * 指向
     * @param niceName 用于进程的可读性更强的名称。
     * @param uid 进程将在其下运行的用户id。
     * @param gid 进程将在其下运行的组id。
     * @param gids 与进程关联的其他组ID。
     * @param runtimeFlags 为运行时添加附加标志。
     * @param targetSdkVersion 应用程序的目标SDK版本。
     * @param seInfo null确定新进程的SELinux信息。
     * @param abi non null此应用程序启动时应使用的abi。
     * @param instructionSet null确定要使用的指令集。
     * @param appDataDir null ok应用程序的数据目录。
     * @param invokeWith null ok用于调用的命令。
     * @param zygoteArgs 为合子进程提供附加参数。
     *
     * @返回一个对象,该对象描述尝试启动进程的结果。
     * @在致命启动失败时引发RuntimeException
     *
     * {@hide}
     */
    public static final ProcessStartResult start(final String processClass,
                                                 final String niceName,
                                                 int uid, int gid, int[] gids,
                                                 int runtimeFlags, int mountExternal,
                                                 int targetSdkVersion,
                                                 String seInfo,
                                                 String abi,
                                                 String instructionSet,
                                                 String appDataDir,
                                                 String invokeWith,
                                                 String[] zygoteArgs) {
        return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
    }

完整源码参考 /frameworks/base/core/java/android/os/Process.java ;





二、Activity 启动源码分析 ( ActivityStarter )



1、ActivityStarter.startActivityMayWait() 方法


在 AMS 中调用了 mActivityStarter.startActivityMayWait 方法 , 在 ActivityStarter 中的 startActivityMayWait 中 , 调用了 24 24 24 个参数的 startActivity 方法 ,

class ActivityStarter {
   private int startActivityMayWait(IApplicationThread caller, int callingUid,
           String callingPackage, Intent intent, String resolvedType,
           IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
           IBinder resultTo, String resultWho, int requestCode, int startFlags,
           ProfilerInfo profilerInfo, WaitResult outResult,
           Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
           int userId, TaskRecord inTask, String reason,
           boolean allowPendingRemoteAnimationRegistryLookup) {

	   // 获取对应 Activity 信息 , 并处理该信息
	   // 	从多个 Activity 中选择最合适的 Activity 
	   // 	类似于打开一个文本文件 , 弹出窗口 , 选择什么应用打开 
       ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
               0 /* matchFlags */,
                       computeResolveFilterUid(
                               callingUid, realCallingUid, mRequest.filterCallingUid));

			// 在 ActivityRecord 对象中 , 记录了 Activity 的相关活动
            final ActivityRecord[] outRecord = new ActivityRecord[1];
			// 启动 Activity 
			// 调用的是 24 个参数的 startActivity 方法
            int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup);
	}
}

完整代码参考 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java ;


2、ActivityStarter.startActivity ( 24 参数 ) 方法


24 24 24 个参数的 startActivity 的重载方法中 , 又调用了 23 23 23 个参数的 startActivity 重载方法 ;

class ActivityStarter {
	// 24 个参数的 startActivity 的重载方法
    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, TaskRecord inTask, String reason,
            boolean allowPendingRemoteAnimationRegistryLookup) {
        // 调用了 23 个参数的 startActivity 的重载方法
        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                inTask, allowPendingRemoteAnimationRegistryLookup);
	}
}

完整代码参考 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java ;


3、ActivityStarter.startActivity ( 23 参数 ) 方法


23 23 23 个参数的 startActivity 的重载方法中 , 又调用了 9 9 9 个参数的 startActivity 重载方法 ,

class ActivityStarter {
	// 23 个参数的 startActivity 重载方法 
    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            SafeActivityOptions options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
		// 调用 9 个参数的 startActivity 的重载方法
        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity);
	}
}

完整代码参考 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java ;


4、ActivityStarter.startActivity ( 9 参数 ) 方法


9 9 9 个参数的 startActivity 的重载方法中 , 调用了 startActivityUnchecked 方法 ;

class ActivityStarter {
	// 9 个参数的 startActivity 的重载方法
    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity) {
        try {
            mService.mWindowManager.deferSurfaceLayout();
			// 此处是主要的逻辑 
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        }
	}
}

完整代码参考 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java ;


5、ActivityStarter.startActivityUnchecked 方法


startActivityUnchecked 方法中 , 调用了 computeLaunchingTaskFlags 方法 ,

mTargetStack.startActivityLocked 是将启动的 Activity 插入到栈顶部 , 调用 ActivityStack 的 startActivityLocked 方法 ;

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

		// 启动 Activity 的 Launcher Mode 4 种启动模式 , 就是在该方法中处理
        computeLaunchingTaskFlags();

        computeSourceStack();

		// 此处将启动的 Activity 插入到栈顶部
		// 	调用 ActivityStack 的 startActivityLocked 方法 
        mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
                mOptions);

		// 显示栈顶元素
		mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
		
}

完整代码查看 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java ;


6、ActivityStarter.computeLaunchingTaskFlags() 方法


该方法处理 Activity 启动模式 , 假如启动 Activity 场景是 Activity A 启动 Activity B , mSourceRecord 是 Activity A 相关资料 , 是 ActivityRecord 类型对象 , 该对象中保存了 Activity 的所有信息 ;

mSourceRecord == null , 判断启动 Activity 的源是否是 Activity , 如果通过 Context 或 Application 启动 Activity , 则 mSourceRecord 就是空的 ;

mInTask != null 判断要加入的 TaskRecord 是否为空 ;

调用 isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK) 方法用于判定该 Activity 的启动模式是否是 LAUNCH_SINGLE_INSTANCE 或 LAUNCH_SINGLE_TASK 中二者之一 ;

class ActivityStarter {
	// 处理 Activity 启动模式
    private void computeLaunchingTaskFlags() {
        // 如果调用方不是来自另一个 Activity,而是给了我们一个明确的任务,
		// 	他们希望我们在其中启动新Activity,那么让我们看看如何执行该任务。
		// 假如启动 Activity 场景是 Activity A 启动 Activity B 
		// 	mSourceRecord 是 Activity A 相关资料 , 是 ActivityRecord 类型对象
		// 	该对象中保存了 Activity 的所有信息 
        if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
            final Intent baseIntent = mInTask.getBaseIntent();
            final ActivityRecord root = mInTask.getRootActivity();
            if (baseIntent == null) {
                ActivityOptions.abort(mOptions);
                throw new IllegalArgumentException("Launching into task without base intent: "
                        + mInTask);
            }

            // 如果此任务为空,那么我们将添加第一个活动——它确定根,并且必须作为新的_任务启动。
            if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
                if (root != null) {
                    ActivityOptions.abort(mOptions);
                    throw new IllegalArgumentException("Caller with mInTask " + mInTask
                            + " has root " + root + " but target is singleInstance/Task");
                }
            }
    }
}

完整代码参考 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java ;





三、Activity 启动源码分析 ( ActivityRecord )



ActivityRecord 中记录了所有的 Activity 信息 , 其中的 private TaskRecord task; // the task this is in. 成员 , 记录该 ActivityRecord 是存储在哪个 TaskRecord 中 ;

由于 Activity 可以启动多次 , 1 1 1 个 Activity 可能有多个 ActivityRecord 与之对应 , 每个 ActivityRecord 都与当前某个存在的 Activity 对应 ; 如果启动模式是 Standard , 那么每次启动该 Activity 都会创建一个新的 Activity , 放在任务栈栈顶 ;

final class ActivityRecord extends ConfigurationContainer implements AppWindowContainerListener {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_AM;
    private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
    private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
    private static final String TAG_STATES = TAG + POSTFIX_STATES;
    private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
    private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
    // TODO(b/67864419): Remove once recents component is overridden
    private static final String LEGACY_RECENTS_PACKAGE_NAME = "com.android.systemui.recents";

    private static final boolean SHOW_ACTIVITY_START_TIME = true;

    private static final String ATTR_ID = "id";
    private static final String TAG_INTENT = "intent";
    private static final String ATTR_USERID = "user_id";
    private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
    private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
    private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
    private static final String ATTR_RESOLVEDTYPE = "resolved_type";
    private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
    static 以上是关于Android 启动过程Activity 启动源码分析 ( AMS -> ActivityThreadAMS 线程阶段 )的主要内容,如果未能解决你的问题,请参考以下文章

Android 启动过程Activity 启动源码分析 ( ActivityThread -> Activity主线程阶段 一 )

Android 启动过程Activity 启动源码分析 ( AMS -> ActivityThreadAMS 线程阶段 二 )

Android 启动过程Activity 启动源码分析 ( AMS -> ActivityThreadAMS 线程阶段 )

Android 启动过程Activity 启动源码分析 ( ActivityThread -> Activity主线程阶段 二 )

android6.0源码分析之Activity启动过程

android6.0源码分析之Activity启动过程