Android14 Activity 启动过程详解 2 —— SystemServer 处理请求之构建

上一节我们分析到客户端发起 Binder RPC 调用,接下来就会远程调用到 SystemServer 进程中 ActivityTaskManagerService 服务的 startActivity 方法:

java 复制代码
    // frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    @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*/);
    }

方法的参数有:

  • 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:

java 复制代码
    // 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) {

        // ......

        // 关注点1
        // 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 处,先调用 getActivityStartController 方法,方法中返回 ActivityTaskManagerService 类的成员变量 mActivityStartController。

java 复制代码
    // base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    ActivityStartController getActivityStartController() {
        return mActivityStartController;
    }    

mActivityStartController 是 ActivityTaskManagerService 类的成员,ATMS 中 Activity 启动相关的功能都放在 ActivityStartController 类中:

java 复制代码
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    // ......
    private ActivityStartController mActivityStartController;
    // ......
}

mActivityStartController 在 ActivityTaskManagerService 的 initialize 方法中初始化

java 复制代码
    // base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    public void initialize(IntentFirewall intentFirewall, PendingIntentController intentController,
            Looper looper) {
              // ......
              mActivityStartController = new ActivityStartController(this);
              // ......
    }

    // ActivityStartController 构造函数
    ActivityStartController(ActivityTaskManagerService service) {
        this(service, service.mStackSupervisor,
                new DefaultFactory(service, service.mStackSupervisor,
                    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);
    }   

在 initialize 方法中,会去 new 一个 ActivityStartController 对象,在其构造函数中主要是对内部的成员进行赋值。

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

回到启动过程代码,接着会调用 mActivityStartController 的 obtainStarter 方法:

java 复制代码
    // frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
    ActivityStarter obtainStarter(Intent intent, String reason) {
        return mFactory.obtain().setIntent(intent).setReason(reason);
    }

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

java 复制代码
    // 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;
        }

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

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

java 复制代码
        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();

到目前为止,起始就是构建了一个启动 Activity 的辅助类 ActivityStarter 对象。

接着调用 ActivityStarter 的 execute 方法。

java 复制代码
    // base/services/core/java/com/android/server/wm/ActivityStarter.java
    int execute() {
        try {

            // 启动 Activity 前的回调
            onExecutionStarted();

                // ......

                try {
                    // 启动 Activity
                    res = executeRequest(mRequest);
                } finally {
                    mRequest.logMessage.append(" result code=").append(res);
                    Slog.i(TAG, mRequest.logMessage.toString());
                    mRequest.logMessage.setLength(0);
                }

                // .......
        } finally {
            // 启动 Activity 后的回调
            onExecutionComplete();
        }
    }

接着我们重点看 executeRequest 的实现:

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 的实际类型是 ProcessRecord
            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();

        if (err != START_SUCCESS) {
            if (resultRecord != null) {
                resultRecord.sendResult(INVALID_UID, resultWho, requestCode, RESULT_CANCELED,
                        null /* data */, null /* dataGrants */);
            }
            SafeActivityOptions.abort(options);
            return err;
        }

        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;
            }
        }

        // 拦截器
        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) {
            // // 运行时权限检测,当前情景下不进入
            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;
    }

大致可分为 5 个阶段:

  • 准备一大堆参数
  • 各类权限检测
  • 启动过程拦截器处理
  • 构建待启动的目标 Activity 对应的 ActivityRecord 对象
  • 接着调用 startActivityUnchecked 方法

总结

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

  • 构建一个 Activity 启动的辅助类 ActivityStarter 对象
  • 构建待启动的目标 Activity 对应的 ActivityRecord 对象
  • 接着调用 startActivityUnchecked 方法

参考资料

相关推荐
戏谑8 分钟前
Android 常用布局
android·view
拭心12 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王14 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡14 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道15 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库15 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道16 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe16 小时前
Android Hook - 动态加载so库
android
居居飒17 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He20 小时前
桌面列表小部件不能点击的问题分析
android