Android14 AMS 剖析—— Activity 启动分析之 ActivityRecord 的构建

2/27/2024

上一节我们分析到客户端发起 Binder RPC 调用,接下来就会远程调用到 SystemServer 进程中。

SystemServer 端主要要完成以下一些工作:

  1. 解析与处理请求参数,要启动那个 Activity,怎么启动(flags 等参数),是谁启动等等一些信息
  2. 修改窗口容器树,创建新的 ActivityRecord 与 Task 并挂载到窗口容器树中
  3. pause 源 Activity
  4. 启动新进程,触发 Application Activity 的初始化和启动生命周期回调

本节主要分析第一点和第二点部分内容。

整体的调用链如下:

ActivityTaskManagerService::startActivity
    ActivityTaskManagerService::startActivityAsUser
        ActivityTaskManagerService::startActivityAsUser
            ActivityStartController::obtainStarter
                ActivityStarter::execute
                    ActivityStarter$Request::resolveActivity           
                    ActivityStarter::executeRequest                    
                        ActivityStarter::startActivityUnchecked
1
2
3
4
5
6
7
8

时序图如下:

20240902120553

# 1. 构建 ActivityStart

App 端会远程调用到 ATMS 中的 startActivity 方法,具体实现如下:

    // frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    @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());
    }
  
    @Override
    public int startActivityAsUser(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions, int userId) {
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

方法的参数有:

  • IApplicationThread caller:启动端 App 的 ActivityThread 对象中的 ApplicationThread 类型成员 mAppThread,在 App 端它是一个 Binder 服务端对象,到 SystemServer 端,经过 Binder 驱动和上层框架的处理,实际这个对象已经转换为 Binder 代理端对象了。SystemServer 端可以使用该对象向 App 端发起 RPC 调用,用于通知 Activity 的状态改变
  • String callingPackage:启动方 Activity 所在包名 "com.android.launcher3"
  • String callingFeatureId:null
  • Intent intent:启动目的 Activity 的 Intent,携带了目的端 Acitivity 隐式或者显示启动需要的参数
  • String resolvedType: null,the MIME data type of this intent
  • IBinder resultTo:IBinder 对象,在 App 端是一个 Binder 代理对象,到 SystemServer 端,经过 Binder 驱动和上层框架的处理,实际这个对象已经是一个 Binder 服务端对象了,其值和发起端 Activity 的 ActivityRecord 对象中的 Token 成员相同,这个参数相对复杂一点,目前只需要知道,它可以作为一个索引找到对应的 ActivityRecord 对象
  • String resultWho:null
  • int requestCode:-1,启动目的端 Activity 的请求码
  • int startFlags:Activity 的启动 flag,当前值为 0
  • ProfilerInfo profilerInfo:System private API for passing profiler settings,这里是 null
  • Bundle bOptions:启动 Activity 的额外参数
  • userId:0

接着调用到 startActivityAsUser 方法:

    // frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

    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) {

        // ......

        // TODO: Switch to user app stacks here.
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setCallingFeatureId(callingFeatureId)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(opts)
                .setUserId(userId)
                .execute();

    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

这里,我们主要关注最后的 return 部分,先调用 getActivityStartController 方法,方法中返回 ActivityTaskManagerService 类的成员变量 mActivityStartController。

    // base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    ActivityStartController getActivityStartController() {
        return mActivityStartController;
    }  
1
2
3
4

ATMS 中, Activity 启动相关的功能都放在 ActivityStartController 类中:

public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    // ......
    private ActivityStartController mActivityStartController;
    // ......
}
1
2
3
4
5

通过搜索可以发现,mActivityStartController 在 ActivityTaskManagerService 的 initialize 方法中初始化

    // base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

    public void initialize(IntentFirewall intentFirewall, PendingIntentController intentController,
            Looper looper) {
              // ......
              mActivityStartController = new ActivityStartController(this);
              // ......
    }
1
2
3
4
5
6
7
8

在 initialize 方法中,会去 new 一个 ActivityStartController 对象。

ActivityStartController 的造函数中主要是对内部的成员进行赋值:

    // frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java 
    // ActivityStartController 构造函数

    ActivityStartController(ActivityTaskManagerService service) {
        this(service, service.mStackSupervisor,
                new DefaultFactory(service, service.mStackSupervisor,
			        // 给 mInterceptor 拦截器赋值 
                    new ActivityStartInterceptor(service, service.mStackSupervisor)));
    }

    ActivityStartController(ActivityTaskManagerService service, ActivityStackSupervisor supervisor,
            Factory factory) {
        mService = service;
        mSupervisor = supervisor;
        mHandler = new StartHandler(mService.mH.getLooper());
        //重点关注
        mFactory = factory;
        mFactory.setController(this);
        mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service,
                service.mH);
    }   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

这里需要重点关注的是 ActivityStartController 的成员 mFactory, mFactory 会被初始化为 DefaultFactory 对象。后续会用到这个工厂类对象生成 ActivityStarter 对象。

回到 startActivityAsUser 方法中,接着会调用 mActivityStartController 的 obtainStarter 方法:


    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) {

        // ......

        // TODO: Switch to user app stacks here.
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser") // 接着调用 obtainStarter
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setCallingFeatureId(callingFeatureId)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(opts)
                .setUserId(userId)
                .execute();

    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

obtainStarter 方法的实现如下:

    // frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
    ActivityStarter obtainStarter(Intent intent, String reason) {
        return mFactory.obtain().setIntent(intent).setReason(reason);
    }
1
2
3
4

这里的 mFactory 就是 ActivityStartController 初始化过程中的 DefaultFactory,会调用其 obtaion 方法初始化一个 ActivityStarter 对象返回。

    // frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
        @Override
        public ActivityStarter obtain() {
            ActivityStarter starter = mStarterPool.acquire();

            if (starter == null) {
                if (mService.mRootWindowContainer == null) {
                    throw new IllegalStateException("Too early to start activity.");
                }
                starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
            }

            return starter;
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

这里先从缓存里面去获取 ActivityStarter 对象,如果没有获取到,就 new 一个。当前情景下,会 new 一个 ActivityStarter 对象。

接着给获取到的 ActivityStarter 对象设置一堆参数,这些参数都来自 startActivityAsUser 方法的参数:

        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();
1
2
3
4
5
6
7
8
9
10
11
12

ActivityStarter 中有很多的 set 方法,这些 set 方法实际是把传入的值保存在 Request 对象中。

Request 中保存了启动 Activity 需要的所有数据,这些数据主要来自 startActivity 的传入参数。

// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
class ActivityStarter {
    // ......
    Request mRequest = new Request();  

    ActivityStarter setCaller(IApplicationThread caller) {
        mRequest.caller = caller;
        return this;
    }

    // ......
}
1
2
3
4
5
6
7
8
9
10
11
12

Request 主要用于保存启动中的参数:

    static class Request {
        private static final int DEFAULT_CALLING_UID = -1;
        private static final int DEFAULT_CALLING_PID = 0;
        static final int DEFAULT_REAL_CALLING_UID = -1;
        static final int DEFAULT_REAL_CALLING_PID = 0;

        IApplicationThread caller;
        Intent intent;
        NeededUriGrants intentGrants;
        // A copy of the original requested intent, in case for ephemeral app launch.
        Intent ephemeralIntent;
        String resolvedType;
        ActivityInfo activityInfo;
        ResolveInfo resolveInfo;
        IVoiceInteractionSession voiceSession;
        IVoiceInteractor voiceInteractor;
        IBinder resultTo;
        String resultWho;
        int requestCode;
        int callingPid = DEFAULT_CALLING_PID;
        int callingUid = DEFAULT_CALLING_UID;
        String callingPackage;
        @Nullable String callingFeatureId;
        int realCallingPid = DEFAULT_REAL_CALLING_PID;
        int realCallingUid = DEFAULT_REAL_CALLING_UID;
        int startFlags;
        SafeActivityOptions activityOptions;
        boolean ignoreTargetSecurity;
        boolean componentSpecified;
        boolean avoidMoveToFront;
        ActivityRecord[] outActivity;
        Task inTask;
        TaskFragment inTaskFragment;
        String reason;
        ProfilerInfo profilerInfo;
        Configuration globalConfig;
        int userId;
        WaitResult waitResult;
        int filterCallingUid;
        PendingIntentRecord originatingPendingIntent;
        BackgroundStartPrivileges backgroundStartPrivileges;

        final StringBuilder logMessage = new StringBuilder();

        /**
         * The error callback token passed in {@link android.window.WindowContainerTransaction}
         * for TaskFragment operation error handling via
         * {@link android.window.TaskFragmentOrganizer#onTaskFragmentError(IBinder, Throwable)}.
         */
        @Nullable
        IBinder errorCallbackToken;

        /**
         * If set to {@code true}, allows this activity start to look into
         * {@link PendingRemoteAnimationRegistry}
         */
        boolean allowPendingRemoteAnimationRegistryLookup;

        // ......
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

到目前为止,起始就是构建了一个启动 Activity 的辅助类 ActivityStarter 对象,初始化了 ActivityStarter 的内部成员 Request 。

相关的类图如下:

20240901121955

# 2. excute 方法执行过程分析

在构造好 ActivityStarter 对象,Request 对象后,接着调用 ActivityStarter 的 execute 方法。

    // base/services/core/java/com/android/server/wm/ActivityStarter.java

    /**
     * Resolve necessary information according the request parameters provided earlier, and execute
     * the request which begin the journey of starting an activity.
     * @return The starter result.
     */
    int execute() {
        try {
            // 调用 ActivityStartController 中的 onExecutionStarted 回调方法
            onExecutionStarted();

            // Refuse possible leaked file descriptors
            if (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) {
                throw new IllegalArgumentException("File descriptors passed in Intent");
            }

            // ......

            // If the caller hasn't already resolved the activity, we're willing
            // to do so here. If the caller is already holding the WM lock here,
            // and we need to check dynamic Uri permissions, then we're forced
            // to assume those permissions are denied to avoid deadlocking.
            if (mRequest.activityInfo == null) {
                // 关注点1,从 PMS 中获取目标 Activity 信息,解析出的信息保存在 mRequest.activityInfo
                mRequest.resolveActivity(mSupervisor);
            }

            // ......

            int res;
            synchronized (mService.mGlobalLock) {
           
                // ......

                try {
                    // 关注点2
                    res = executeRequest(mRequest);
                } finally {
                    mRequest.logMessage.append(" result code=").append(res);
                    Slog.i(TAG, mRequest.logMessage.toString());
                    mRequest.logMessage.setLength(0);
                }

               // ......
            }
        } finally {
            onExecutionComplete();
        }
    }   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

这部分我们主要关注两点:

  • resolveActivity 方法从 PMS 中获取目标 Activity 信息,获取到的信息保存在 resolveInfo/activityInfo 中
  • executeRequest 执行后续逻辑

# 2.1 resolveActivity 从 PMS 中获取目标 Activity 信息

每个 App 的四大组件信息都声明在其 AndroidManifest.xml 文件中。这些信息,在应用安装的时候,PMS 解析保存起来了。接下来我们会调用 PMS 的接口获取到这些信息。

        // frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
        // 内部类 Request 中

        void resolveActivity(ActivityTaskSupervisor supervisor) {
       
            // ......
        
            // Save a copy in case ephemeral needs it
            ephemeralIntent = new Intent(intent);
            // Don't modify the client's object!
            intent = new Intent(intent);

            // ......


            // 调用 PMS 获取目标 Activity 信息
            // 结果保存在 resolveInfo 中
            resolveInfo = supervisor.resolveIntent(intent, resolvedType, userId,
                    0 /* matchFlags */,
                    computeResolveFilterUid(callingUid, realCallingUid, filterCallingUid),
                    realCallingPid);
        
            // ......

            // 解析 resolveInfo,结果保存在 activityInfo 中
            // Collect information about the target of the Intent.
            activityInfo = supervisor.resolveActivity(intent, resolveInfo, startFlags,
                    profilerInfo);

            //......
            if (activityInfo != null) {
                intentGrants = supervisor.mService.mUgmInternal.(
                        intent, resolvedCallingUid, activityInfo.applicationInfo.packageName,
                        UserHandle.getUserId(activityInfo.applicationInfo.uid));
            }
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

主要关注三点:

  • resolveIntent:调用 PMS 获取目标 Activity 信息,结果保存在 resolveInfo 中
  • resolveActivity:从 resolveInfo 中获取到信息,并将这些信息设置到 Intent 中,同时会返回一个 ActivityInfo 对象

接下来我们看 resolveIntent 的具体实现:

// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java

    ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags,
            int filterCallingUid, int callingPid) {
        try {
        
            // ....
            try {

                // 调用 PMS 的接口,解析出目标 App 对应的 ResolveInfo 对象
                return mService.getPackageManagerInternalLocked().resolveIntentExported(
                        intent, resolvedType, modifiedFlags, privateResolveFlags, userId, true,
                        filterCallingUid, callingPid);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

resolveIntent 内部会调用 PMS 的接口,解析出目标 App 对应的 ResolveInfo 对象。

PackageManagerService 中查询信息的具体过程我们放在 PMS 的章节来分析(分析源码一定要有分层的思想)。这里我们主要关心从 PackageManagerService 中查询到的信息会保存在返回的 ResolveInfo 对象中:

// /frameworks/base/core/java/android/content/pm/ResolveInfo.java
public class ResolveInfo implements Parcelable {
  
    private static final String TAG = "ResolveInfo";

    public ActivityInfo activityInfo;

    public ServiceInfo serviceInfo;

    public ProviderInfo providerInfo;

    // ......
}
1
2
3
4
5
6
7
8
9
10
11
12
13

ResolveInfo 成员很多,其中比较重要的成员有三个:

  • ActivityInfo:用于存储 Activity 或 Broadcast 的信息
  • ServiceInfo:用于存储 Service 相关信息
  • ProviderInfo:用于存储 Content Provider 相关信息

这三个成员只有一个不为空,这里我们启动的是 Activity,所以 ActivityInfo 是不为空的。ActivityInfo 包含了各种各样的 Activity 信息,这些信息都是 PackageManagerService 从 AndroidManifest.xml 文件中获取到的,比较重要的包括 launchMode、theme、screenOrientation 等,其中还包含了 ApplicationInfo,提供 packageName、targetSdkVersion 等重要信息。

// /frameworks/base/core/java/android/content/pm/ActivityInfo.java
public class ActivityInfo extends ComponentInfo implements Parcelable {
    // .....
    public int theme;
    public int launchMode;
    @ScreenOrientation
    public int screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
    
    // .....
}
1
2
3
4
5
6
7
8
9
10

ActivityInfo 的父类:

public class ComponentInfo extends PackageItemInfo {
    // ......
    public ApplicationInfo applicationInfo;
    public String processName;
    // ......
}
1
2
3
4
5
6

接下来我们接着查看 resolveActivity 的实现:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
    // ......
    ActivityInfo resolveActivity(Intent intent, ResolveInfo rInfo, int startFlags,
            ProfilerInfo profilerInfo) {
        // 获取到 ResolveInfo 的 activityInfo 成员
        final ActivityInfo aInfo = rInfo != null ? rInfo.activityInfo : null;
        if (aInfo != null) {
       
            intent.setComponent(new ComponentName(
                    aInfo.applicationInfo.packageName, aInfo.name));

            final boolean requestDebug = (startFlags & (START_FLAG_DEBUG
                    | START_FLAG_NATIVE_DEBUGGING | START_FLAG_TRACK_ALLOCATION)) != 0;
            final boolean requestProfile = profilerInfo != null;
            if (requestDebug || requestProfile) { // 不进入
                // ......
            }
            final String intentLaunchToken = intent.getLaunchToken(); // null
            if (aInfo.launchToken == null && intentLaunchToken != null) { // 不进入
                aInfo.launchToken = intentLaunchToken;
            }
        }
        return aInfo;
    }
    // ......
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

实际上,内容很简单:

  • 从 ResolveInfo 中获取到 ActivityInfo
  • 利用 ActivityInfo 中的信息构建一个 ComponentName 对象,然后设置给 Intent。
  • 返回 ActivityInfo

# 2.2 executeRequest 执行启动后续流程

接下来我们看 executeRequest 的实现:

// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

    private int executeRequest(Request request) {
        if (TextUtils.isEmpty(request.reason)) {
            throw new IllegalArgumentException("Need to specify a reason.");
        }

        // 准备一堆参数
        mLastStartReason = request.reason;
        mLastStartActivityTimeMs = System.currentTimeMillis();
        mLastStartActivityRecord = null;

        final IApplicationThread caller = request.caller;
        Intent intent = request.intent;
        NeededUriGrants intentGrants = request.intentGrants;
        String resolvedType = request.resolvedType;
        ActivityInfo aInfo = request.activityInfo;
        ResolveInfo rInfo = request.resolveInfo;
        final IVoiceInteractionSession voiceSession = request.voiceSession;
        final IBinder resultTo = request.resultTo;
        String resultWho = request.resultWho;
        int requestCode = request.requestCode;
        int callingPid = request.callingPid;
        int callingUid = request.callingUid;
        String callingPackage = request.callingPackage;
        String callingFeatureId = request.callingFeatureId;
        final int realCallingPid = request.realCallingPid;
        final int realCallingUid = request.realCallingUid;
        final int startFlags = request.startFlags;
        final SafeActivityOptions options = request.activityOptions;
        Task inTask = request.inTask;
        TaskFragment inTaskFragment = request.inTaskFragment;

        int err = ActivityManager.START_SUCCESS;
        // Pull the optional Ephemeral Installer-only bundle out of the options early.
        final Bundle verificationBundle =
                options != null ? options.popAppVerificationBundle() : null;

        WindowProcessController callerApp = null;
        if (caller != null) {
            callerApp = mService.getProcessController(caller);
            if (callerApp != null) {
                callingPid = callerApp.getPid();
                callingUid = callerApp.mInfo.uid;
            } else {
                Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid
                        + ") when starting: " + intent.toString());
                err = START_PERMISSION_DENIED;
            }
        }

        final int userId = aInfo != null && aInfo.applicationInfo != null
                ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
        final int launchMode = aInfo != null ? aInfo.launchMode : 0;

        // 日志打印
        if (err == ActivityManager.START_SUCCESS) { // 进入
            request.logMessage.append("START u").append(userId).append(" {")
                    .append(intent.toShortString(true, true, true, false))
                    .append("} with ").append(launchModeToString(launchMode))
                    .append(" from uid ").append(callingUid);
            if (callingUid != realCallingUid
                    && realCallingUid != Request.DEFAULT_REAL_CALLING_UID) {
                request.logMessage.append(" (realCallingUid=").append(realCallingUid).append(")");
            }
        }

        ActivityRecord sourceRecord = null;
        ActivityRecord resultRecord = null;
        if (resultTo != null) { // 进入
            // Launcher 端的 ActivityRecord
            sourceRecord = ActivityRecord.isInAnyTask(resultTo);
            if (DEBUG_RESULTS) {
                Slog.v(TAG_RESULTS, "Will send result to " + resultTo + " " + sourceRecord);
            }
            if (sourceRecord != null) {
                if (requestCode >= 0 && !sourceRecord.finishing) {
                    resultRecord = sourceRecord;
                }
            }
        }

        final int launchFlags = intent.getFlags(); // 270532608
    
        // ......

        final Task resultRootTask = resultRecord == null
                ? null : resultRecord.getRootTask();

        // .....

        boolean abort;
        try {
            // 权限检测
            // 当前场景,返回的 abort 为 false,表示有权限启动目标 Activity
            abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage, callingFeatureId,
                    request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord,
                    resultRootTask);
        } catch (SecurityException e) {
            // Return activity not found for the explicit intent if the caller can't see the target
            // to prevent the disclosure of package existence.
            final Intent originalIntent = request.ephemeralIntent;
            if (originalIntent != null && (originalIntent.getComponent() != null
                    || originalIntent.getPackage() != null)) {
                final String targetPackageName = originalIntent.getComponent() != null
                        ? originalIntent.getComponent().getPackageName()
                        : originalIntent.getPackage();
                if (mService.getPackageManagerInternalLocked()
                        .filterAppAccess(targetPackageName, callingUid, userId)) {
                    if (resultRecord != null) {
                        resultRecord.sendResult(INVALID_UID, resultWho, requestCode,
                                RESULT_CANCELED, null /* data */, null /* dataGrants */);
                    }
                    SafeActivityOptions.abort(options);
                    return ActivityManager.START_CLASS_NOT_FOUND;
                }
            }
            throw e;
        }
        abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
                callingPid, resolvedType, aInfo.applicationInfo);
        abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
                callingPackage);

        // Merge the two options bundles, while realCallerOptions takes precedence.
        ActivityOptions checkedOptions = options != null
                ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null;

        // 后台启动权限处理
        @BalCode int balCode = BAL_ALLOW_DEFAULT;
        if (!abort) {
            try {
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
                        "shouldAbortBackgroundActivityStart");
                BackgroundActivityStartController balController =
                        mController.getBackgroundActivityLaunchController();
                balCode =
                        balController.checkBackgroundActivityStart(
                                callingUid,
                                callingPid,
                                callingPackage,
                                realCallingUid,
                                realCallingPid,
                                callerApp,
                                request.originatingPendingIntent,
                                request.backgroundStartPrivileges,
                                intent,
                                checkedOptions);
                if (balCode != BAL_ALLOW_DEFAULT) {
                    request.logMessage.append(" (").append(
                                    BackgroundActivityStartController.balCodeToString(balCode))
                            .append(")");
                }
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
            }
        }

        if (request.allowPendingRemoteAnimationRegistryLookup) {
            checkedOptions = mService.getActivityStartController()
                    .getPendingRemoteAnimationRegistry()
                    .overrideOptionsIfNeeded(callingPackage, checkedOptions);
        }
        if (mService.mController != null) {
            try {
                // The Intent we give to the watcher has the extra data stripped off, since it
                // can contain private information.
                Intent watchIntent = intent.cloneFilter();
                abort |= !mService.mController.activityStarting(watchIntent,
                        aInfo.applicationInfo.packageName);
            } catch (RemoteException e) {
                mService.mController = null;
            }
        }

        // 拦截器,实际类型是 ActivityStartInterceptor
        mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage,
                callingFeatureId);
        if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, inTaskFragment,
                callingPid, callingUid, checkedOptions)) {
            // activity start was intercepted, e.g. because the target user is currently in quiet
            // mode (turn off work) or the target application is suspended
            intent = mInterceptor.mIntent;
            rInfo = mInterceptor.mRInfo;
            aInfo = mInterceptor.mAInfo;
            resolvedType = mInterceptor.mResolvedType;
            inTask = mInterceptor.mInTask;
            callingPid = mInterceptor.mCallingPid;
            callingUid = mInterceptor.mCallingUid;
            checkedOptions = mInterceptor.mActivityOptions;

            // The interception target shouldn't get any permission grants
            // intended for the original destination
            intentGrants = null;
        }

        if (abort) {
            if (resultRecord != null) {
                resultRecord.sendResult(INVALID_UID, resultWho, requestCode, RESULT_CANCELED,
                        null /* data */, null /* dataGrants */);
            }
            // We pretend to the caller that it was really started, but they will just get a
            // cancel result.
            ActivityOptions.abort(checkedOptions);
            return START_ABORTED;
        }


        // If permissions need a review before any of the app components can run, we
        // launch the review activity and pass a pending intent to start the activity
        // we are to launching now after the review is completed.
        if (aInfo != null) {
            // 权限 review
            if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                    aInfo.packageName, userId)) {
                // ......
            }
        }

        // ......
   
        // 构建一个 ActivityRecord 对象
        final ActivityRecord r = new ActivityRecord.Builder(mService)
                .setCaller(callerApp)
                .setLaunchedFromPid(callingPid)
                .setLaunchedFromUid(callingUid)
                .setLaunchedFromPackage(callingPackage)
                .setLaunchedFromFeature(callingFeatureId)
                .setIntent(intent)
                .setResolvedType(resolvedType)
                .setActivityInfo(aInfo)
                .setConfiguration(mService.getGlobalConfiguration())
                .setResultTo(resultRecord)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setComponentSpecified(request.componentSpecified)
                .setRootVoiceInteraction(voiceSession != null)
                .setActivityOptions(checkedOptions)
                .setSourceRecord(sourceRecord)
                .build();

        mLastStartActivityRecord = r;

        if (r.appTimeTracker == null && sourceRecord != null) {
            // If the caller didn't specify an explicit time tracker, we want to continue
            // tracking under any it has.
            r.appTimeTracker = sourceRecord.appTimeTracker;
        }

        // Only allow app switching to be resumed if activity is not a restricted background
        // activity and target app is not home process, otherwise any background activity
        // started in background task can stop home button protection mode.
        // As the targeted app is not a home process and we don't need to wait for the 2nd
        // activity to be started to resume app switching, we can just enable app switching
        // directly.
        WindowProcessController homeProcess = mService.mHomeProcess;
        boolean isHomeProcess = homeProcess != null
                && aInfo.applicationInfo.uid == homeProcess.mUid;
        if (balCode != BAL_BLOCK && !isHomeProcess) {
            mService.resumeAppSwitches();
        }

        // 接着调用 startActivityUnchecked
        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, checkedOptions,
                inTask, inTaskFragment, balCode, intentGrants, realCallingUid);

        if (request.outActivity != null) {
            request.outActivity[0] = mLastStartActivityRecord;
        }

        return mLastStartActivityResult;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

executeRequest 方法大致可分为 5 个阶段:

  • 准备一大堆参数,这些参数大多来自最开始的 startActivity 方法参数
  • 各类权限检测
  • 启动过程拦截器 mInterceptor 处理
  • 构建待启动的目标 Activity 对应的 ActivityRecord 对象
  • 接着调用 startActivityUnchecked 方法

对于主流程,我们主要关注最后两点。

先看 ActivityRecord 的初始化过程:

        // 日志打印
        if (err == ActivityManager.START_SUCCESS) { // 进入
            request.logMessage.append("START u").append(userId).append(" {")
                    .append(intent.toShortString(true, true, true, false))
                    .append("} with ").append(launchModeToString(launchMode))
                    .append(" from uid ").append(callingUid);
            if (callingUid != realCallingUid
                    && realCallingUid != Request.DEFAULT_REAL_CALLING_UID) {
                request.logMessage.append(" (realCallingUid=").append(realCallingUid).append(")");
            }
        }
    
        // 构建一个 ActivityRecord 对象
        final ActivityRecord r = new ActivityRecord.Builder(mService)
                .setCaller(callerApp)
                .setLaunchedFromPid(callingPid)
                .setLaunchedFromUid(callingUid)
                .setLaunchedFromPackage(callingPackage)
                .setLaunchedFromFeature(callingFeatureId)
                .setIntent(intent)
                .setResolvedType(resolvedType)
                .setActivityInfo(aInfo)
                .setConfiguration(mService.getGlobalConfiguration())
                .setResultTo(resultRecord)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setComponentSpecified(request.componentSpecified)
                .setRootVoiceInteraction(voiceSession != null)
                .setActivityOptions(checkedOptions)
                .setSourceRecord(sourceRecord)
                .build();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

这里会打印一个日志,比如启动 Settings,通过搜索 START u 关键字就能找到对应的启动日志:

2024-09-02 09:09:13.070  1647-19045 ActivityTaskManager     system_process                       I  START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.settings/.Settings bnds=[23,537][230,918]} with LAUNCH_MULTIPLE from uid 10091 (BAL_ALLOW_ALLOWLISTED_COMPONENT) result code=0
1

这样我们就能知道目标 Activity 是 com.android.settings/.Settings,这也是阅读他人代码的常用技巧。

接下来就会初始化一个 ActivityRecord 对象了。

// /frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java

    private ActivityRecord(ActivityTaskManagerService _service, ......) {
            // 创建 Token
            super(_service.mWindowManager, new Token(), TYPE_APPLICATION, true,
                null /* displayContent */, false /* ownerCanManageAppTokens */);
            ......
            packageName = info.applicationInfo.packageName;
            .....
        }
1
2
3
4
5
6
7
8
9
10

这里会初始化一个 Token:

    private static class Token extends Binder {
        @NonNull WeakReference<ActivityRecord> mActivityRef;

        @Override
        public String toString() {
            return "Token{" + Integer.toHexString(System.identityHashCode(this)) + " "
                    + mActivityRef.get() + "}";
        }
    }
1
2
3
4
5
6
7
8
9

Token 实际是一个匿名 Binder 服务,SystemServer 这边 ActivityRecord 持有的是服务端对象,App 那边持有的是客户端对象。当 App 端的客户端对象通过 Binder 传输到 SystemServer 端,会被 Binder 框架修改为一个 Binder 服务端对象,通过这个对象我们就可以索引到对应的 Activity。

接着看下 ActivityRecord 的父类 WindowToken 的构造函数:

// /frameworks/base/services/core/java/com/android/server/wm/WindowToken.java

    final IBinder token;

    protected WindowToken(WindowManagerService service, IBinder _token, int type,
            boolean persistOnEmpty, DisplayContent dc, boolean ownerCanManageAppTokens) {
        this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens,
                false /* roundedCornerOverlay */, false /* fromClientToken */, null /* options */);
    }

    protected WindowToken(WindowManagerService service, IBinder _token, int type,
            boolean persistOnEmpty, DisplayContent dc, boolean ownerCanManageAppTokens,
            boolean roundedCornerOverlay, boolean fromClientToken, @Nullable Bundle options) {
        super(service);
        // token 赋值
        token = _token;
        windowType = type;
        mOptions = options;
        ......
        if (dc != null) {
            // 挂载到窗口树,
            dc.addWindowToken(token, this);
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

这里会把 Token 保存到成员变量中,接着通过 dc.addWindowToken(token, this); 把 ActivityRecord 记录到窗口容器树中,这里还没有挂载.

// /frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java

    private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();

    void addWindowToken(IBinder binder, WindowToken token) {
       
        // ......

        mTokenMap.put(binder, token);
        
        // .....
      
    }
1
2
3
4
5
6
7
8
9
10
11
12
13

实际就是把 Token 和 ActivityRecord 保存到 mTokenMap 中。

接下来就会接着调用 startActivityUnchecked 方法,开始后续的启动流程

        // 接着调用 startActivityUnchecked
        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, checkedOptions,
                inTask, inTaskFragment, balCode, intentGrants, realCallingUid);
1
2
3
4

# 总结

代码很繁琐,实际核心的过程就三点:

  • 构建一个 Activity 启动的辅助类 ActivityStarter 对象
  • 构建待启动的目标 Activity 对应的 ActivityRecord 对象并记录到 DisplayContent 中。
  • 接着调用 startActivityUnchecked 方法

# 参考资料