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 方法

参考资料

相关推荐
水瓶丫头站住19 分钟前
安卓APP如何适配不同的手机分辨率
android·智能手机
xvch1 小时前
Kotlin 2.1.0 入门教程(五)
android·kotlin
xvch5 小时前
Kotlin 2.1.0 入门教程(七)
android·kotlin
望风的懒蜗牛5 小时前
编译Android平台使用的FFmpeg库
android
浩宇软件开发5 小时前
Android开发,待办事项提醒App的设计与实现(个人中心页)
android·android studio·android开发
ac-er88886 小时前
Yii框架中的多语言支持:如何实现国际化
android·开发语言·php
苏金标7 小时前
The maximum compatible Gradle JVM version is 17.
android
zhangphil7 小时前
Android BitmapShader简洁实现马赛克,Kotlin(一)
android·kotlin
iofomo11 小时前
Android平台从上到下,无需ROOT/解锁/刷机,应用级拦截框架的最后一环,SVC系统调用拦截。
android
我叫特踏实12 小时前
SensorManager开发参考
android·sensormanager