Android AMS 完全剖析 —— Activity 管理之启动过程情景分析2

本文基于 android-10.0.0_r41 版本讲解

到了服务端这边,从前面的分析我们知道,当前情景下的工作大概就是:

  • 构造一个目标 Activity 对应的 ActivityRecord 对象
  • 构造目标 App 的 ActivityStack 对象
  • 构造目标任务栈 TaskRecord
  • 把 ActivityRecord 插入到 TaskRecord

我们按照这个流程按图索骥:

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

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

方法的参数有:

  • IApplicationThread caller:启动方应用的 ActivityThread 对象的 ApplicationThread 类型成员 mAppThread
  • String callingPackage:启动方 Activity 所在包名 "com.android.launcher3"
  • Intent intent:启动目的 Activity 的 Intent,携带了目的端 Acitivity 隐式或者显示启动需要的参数
  • String resolvedType:the MIME data type of this intent
  • IBinder resultTo:指向发起端 Activity 的 ActivityRecord 对象中的 Token
  • String resultWho:来自于当前发起端 Activity.mEmbeddedID
  • int requestCode:启动目的端 Activity 的请求码
  • int startFlags:Activity 的启动 flag
  • ProfilerInfo profilerInfo:System private API for passing profiler settings,这里是 null
  • Bundle bOptions:启动 Activity 的额外参数

接着调用 startActivityAsUser:

java 复制代码
    // frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    @Override
    public int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);
    }

    int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
        
        // 确定调用方 uid 的合法性
        enforceNotIsolatedCaller("startActivityAsUser");
        // 当前情景下,userId =0
        // pid 与 userid 相关的权限判断和调整,了解一下即可。
        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // 关注点1
        // TODO: Switch to user app stacks here.
        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 处,先调用 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);
    }   

这里需要注意 ActivityStartController 的成员 mFactory 初始化为 DefaultFactory 对象。

回到启动过程代码,接着会调用 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
    static class DefaultFactory implements Factory {
        // ......

        @Override
        public ActivityStarter obtain() {
            ActivityStarter starter = mStarterPool.acquire();

            if (starter == null) {
                starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
            }

            return starter;
        }       

        // ...... 
    }

接着给 ActivityStarter 对象设置一堆参数:

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();

最后调用 ActivityStarter 的 execute 方法。

java 复制代码
    // base/services/core/java/com/android/server/wm/ActivityStarter.java
    int execute() {
        try {
            // TODO(b/64750076): Look into passing request directly to these methods to allow
            // for transactional diffs and preprocessing.
            if (mRequest.mayWait) { // 走这个分支
                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                        mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid,
                        mRequest.intent, mRequest.resolvedType,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                        mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                        mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                        mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup,
                        mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
            } else {
                return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                        mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                        mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                        mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                        mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                        mRequest.outActivity, mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup,
                        mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
            }
        } finally {
            onExecutionComplete();
        }
    }

    // base/services/core/java/com/android/server/wm/ActivityStarter.java
    ActivityStarter setMayWait(int userId) {
        mRequest.mayWait = true;
        mRequest.userId = userId;

        return this;
    } 

设置参数过程中会调用 setMayWait 方法会将 mRequest.mayWait 设置为 true,所以上面的代码会走第一个 if 分支执行到 startActivityMayWait 方法。startActivityMayWait 方法很长,我们分步查看:

java 复制代码
    // base/services/core/java/com/android/server/wm/ActivityStarter.java
    private int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, int requestRealCallingPid, int requestRealCallingUid,
            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,
            PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {

        // 启动 Activity 不能通过 intent 传递 fd
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors()) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        // ActivityMetricsLogger 用于记录 Activity 启动、绘制等时间,用于程序分析
        mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);

        //intent 中是否有 Component,这里是 true
        boolean componentSpecified = intent.getComponent() != null;


        // 获取几个 id
        final int realCallingPid = requestRealCallingPid != Request.DEFAULT_REAL_CALLING_PID
                ? requestRealCallingPid
                : Binder.getCallingPid();

    
        final int realCallingUid = requestRealCallingUid != Request.DEFAULT_REAL_CALLING_UID
                ? requestRealCallingUid
                : Binder.getCallingUid();

        int callingPid;
        if (callingUid >= 0) {
            callingPid = -1;
        } else if (caller == null) {
            callingPid = realCallingPid;
            callingUid = realCallingUid;
        } else {
            callingPid = callingUid = -1;
        }

        // instant App 使用的,当前情景不用关心
        // Save a copy in case ephemeral needs it
        final Intent ephemeralIntent = new Intent(intent);
        // Don't modify the client's object!

        // 以传递进来的 intent 为参数重新创建新的 Intent 对象,即便 intent 被修改也不受影响
        intent = new Intent(intent);

        
        // ......

        // 通过 PackageManagerService 获取到目标 Activity 信息, 当存在多个可供选择的 Activity,则直接向用户弹出 resolveActivity 
        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
                0 /* matchFlags */,
                        computeResolveFilterUid(
                                callingUid, realCallingUid, mRequest.filterCallingUid));
        
        if (rInfo == null) {
            // ......
        }
        // .......

resolveIntent 方法通过调用 PackageManagerService 服务(这里是 LocalService,没有进程间通信),查询目的端 Activity 的相关信息,查询到的信息保存在 ResolveInfo 对象中:

java 复制代码
    // base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
    ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags,
            int filterCallingUid) {
        try {
            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "resolveIntent");
            int modifiedFlags = flags
                    | PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS;
            if (intent.isWebIntent()
                        || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
                modifiedFlags |= PackageManager.MATCH_INSTANT;
            }

            // In order to allow cross-profile lookup, we clear the calling identity here.
            // Note the binder identity won't affect the result, but filterCallingUid will.

            // Cross-user/profile call check are done at the entry points
            // (e.g. AMS.startActivityAsUser).
            final long token = Binder.clearCallingIdentity();
            try {  
                // 调用 PackageManagerService LocalService
                return mService.getPackageManagerInternalLocked().resolveIntent(
                        intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        } finally {
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
        }
    }

这里会调用到 PackageManagerService 中的 resolveIntent 来查询目标 Activity 的信息,需要注意的是 ATMS 和 PackageManagerService 都在 SystemServer 中运行,这里使用的是 LocalService,不是 Binder RPC 调用。

从 PackageManagerService 中查询到的信息会保存在返回的 ResolveInfo 对象中:

java 复制代码
public class ResolveInfo implements Parcelable {
    
    private static final String TAG = "ResolveInfo";

    public ActivityInfo activityInfo;

    public ServiceInfo serviceInfo;

    public ProviderInfo providerInfo;

    public AuxiliaryResolveInfo auxiliaryInfo;

    public boolean isInstantAppAvailable;

    @Deprecated
    public boolean instantAppAvailable;

    public IntentFilter filter;

    public int priority;

    public int preferredOrder;

    public int match;

    public int specificIndex = -1;

    public boolean isDefault;

    public int labelRes;

    public CharSequence nonLocalizedLabel;

    public int icon;

    public String resolvePackageName;

    @UnsupportedAppUsage
    public int targetUserId;

    public boolean noResourceId;

    public int iconResourceId;

    @UnsupportedAppUsage
    public boolean system;

    @SystemApi
    public boolean handleAllWebDataURI;

    // ......
}

ResolveInfo 中比较重要的成员有三个:

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

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

我们接着回到 startActivityMayWait 方法中:

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

        // ......

        // 根据获取的 rInfo 信息重新配置 intent 和设置启动的参数信息
        // Collect information about the target of the Intent.
        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
        //......
    }

resolveActivity 方法根据获取到的 ResolveInfo 信息重新配置 intent:

java 复制代码
    // frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
    ActivityInfo resolveActivity(Intent intent, ResolveInfo rInfo, int startFlags,
            ProfilerInfo profilerInfo) {
        final ActivityInfo aInfo = rInfo != null ? rInfo.activityInfo : null;
        if (aInfo != null) {
            // Store the found target back into the intent, because now that
            // we have it we never want to do this again.  For example, if the
            // user navigates back to this point in the history, we should
            // always restart the exact same activity.
            // 使用 rInfo 中的信息重新配置 intent 的 Component
            intent.setComponent(new ComponentName(
                    aInfo.applicationInfo.packageName, aInfo.name));

            // 非 system 进程 && startFlags 中有特殊值
            // 给 AMS 发送一个消息,使用 startFlags 设置 debug 相关的参数
            // 了解即可
            // Don't debug things in the system process
            if (!aInfo.processName.equals("system")) { 
                if ((startFlags & (START_FLAG_DEBUG | START_FLAG_NATIVE_DEBUGGING
                        | START_FLAG_TRACK_ALLOCATION)) != 0 || profilerInfo != null) {

                     // Mimic an AMS synchronous call by passing a message to AMS and wait for AMS
                     // to notify us that the task has completed.
                     // TODO(b/80414790) look into further untangling for the situation where the
                     // caller is on the same thread as the handler we are posting to.
                    synchronized (mService.mGlobalLock) {
                        // Post message to AMS.
                        final Message msg = PooledLambda.obtainMessage(
                                ActivityManagerInternal::setDebugFlagsForStartingActivity,
                                mService.mAmInternal, aInfo, startFlags, profilerInfo,
                                mService.mGlobalLock);
                        mService.mH.sendMessage(msg);
                        try {
                            // 等待锁
                            mService.mGlobalLock.wait();
                        } catch (InterruptedException ignore) {

                        }
                    }
                }
            }

            final String intentLaunchToken = intent.getLaunchToken();
            if (aInfo.launchToken == null && intentLaunchToken != null) {
                aInfo.launchToken = intentLaunchToken;
            }
        }
        return aInfo;
    }

接着回到 startActivityMayWait 方法中:

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

        //......

        synchronized (mService.mGlobalLock) {
           
            // Launcher 所在的 ActivityStack
            final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
            stack.mConfigWillChange = globalConfig != null
                    && mService.getGlobalConfiguration().diff(globalConfig) != 0;
            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                    "Starting activity when config will change = " + stack.mConfigWillChange);

            final long origId = Binder.clearCallingIdentity();


            // ......

            final ActivityRecord[] outRecord = new ActivityRecord[1];

            // 调用另一个重载
            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, originatingPendingIntent,
                    allowBackgroundActivityStart);
    
        //......
        }

        // ......
    }

接着调用另一个 startActivity 重载:

java 复制代码
    // base/services/core/java/com/android/server/wm/ActivityStarter.java
    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,
            PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {

        if (TextUtils.isEmpty(reason)) {
            throw new IllegalArgumentException("Need to specify a reason.");
        }
        mLastStartReason = reason;
        mLastStartActivityTimeMs = System.currentTimeMillis();
        mLastStartActivityRecord[0] = null;

        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, originatingPendingIntent,
                allowBackgroundActivityStart);

        if (outActivity != null) {
            // mLastStartActivityRecord[0] is set in the call to startActivity above.
            outActivity[0] = mLastStartActivityRecord[0];
        }

        return getExternalResult(mLastStartActivityResult);
    }

对一些成员变量赋值后,接着调另一个重载 startActivity:

java 复制代码
    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,
            PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
        

        // 信息记录
        // ActivityMetricsLogger 用于记录时间信息
        mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);


        // 参数处理
        int err = ActivityManager.START_SUCCESS;

        // instant app 启动相关的 bundle
        // Pull the optional Ephemeral Installer-only bundle out of the options early.
        final Bundle verificationBundle
                = options != null ? options.popAppVerificationBundle() : null;
        
        // 获取调用者的进程信息
        // WindowProcessController 是 WMS 与 AMS 通信的工具类,内部也保存了进程相关的信息
        // WindowProcessController 涉及其他地方,细节暂放,先梳理流程,后面单独章节再讲
        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 = ActivityManager.START_PERMISSION_DENIED;
            }
        }

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

        if (err == ActivityManager.START_SUCCESS) {
            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
                    + "} from uid " + callingUid);
        }

        // 启动目标 Activity 的 Activity
        ActivityRecord sourceRecord = null;
        // 目标 Activity 如果要返回数据,返回给哪个 Activity
        ActivityRecord resultRecord = null;


        // resultTo 指向发起端 Activity 对应的 ActivityRecord 对象中的 Token
        // Token 内部有个弱引用指向 ActivityRecord,也就是说通过 Token 可以拿到 ActivityRecord
        if (resultTo != null) {
            // Launcher 
            sourceRecord = mRootActivityContainer.isInAnyStack(resultTo);
            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                    "Will send result to " + resultTo + " " + sourceRecord);
            if (sourceRecord != null) {
                // requestCode == -1
                if (requestCode >= 0 && !sourceRecord.finishing) {
                    resultRecord = sourceRecord;
                }
            }
        }

        // 拿到启动的 flag
        final int launchFlags = intent.getFlags();

        //接下里就要处理各种 flag 了,一般遇到哪种看哪种

        // FLAG_ACTIVITY_FORWARD_RESULT 处理,当前情景没有,省略
        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
          // ......
        }

        // 不进入
        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
            // ......
        }

        // 不进入
        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
           // ......
        }

        // 不进入
        if (err == ActivityManager.START_SUCCESS && sourceRecord != null
                && sourceRecord.getTaskRecord().voiceSession != null) {
            // If this activity is being launched as part of a voice session, we need
            // to ensure that it is safe to do so.  If the upcoming activity will also
            // be part of the voice session, we can only launch it if it has explicitly
            // said it supports the VOICE category, or it is a part of the calling app.
            if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
                    && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
               //......
            }
        }

        // 不进入
        if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
            //......
        }

        // resultRecord 为 null
        // 所以 resultStack 为 null
        final ActivityStack resultStack = resultRecord == null
                ? null : resultRecord.getActivityStack();


        // 不进入
        if (err != START_SUCCESS) {
           //......
        }

        // 3. 权限检测
        // 当前场景,返回的 abort 为 false,表示有权限启动
        // 权限和繁琐,单独一篇来分析权限
        boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
                inTask != null, callerApp, resultRecord, resultStack);
        
        abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
                callingPid, resolvedType, aInfo.applicationInfo);

        abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
                callingPackage);

        boolean restrictedBgActivity = false;

        // 后台 Activity 启动的处理
        // Android 10 开始不能直接后台启动 Activity
        if (!abort) {
            try {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        "shouldAbortBackgroundActivityStart");
                restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
                        callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
                        originatingPendingIntent, allowBackgroundActivityStart, intent);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
        }

        // options 参数处理
        // Merge the two options bundles, while realCallerOptions takes precedence.
        ActivityOptions checkedOptions = options != null
                ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null;
        if (allowPendingRemoteAnimationRegistryLookup) {
            checkedOptions = mService.getActivityStartController()
                    .getPendingRemoteAnimationRegistry()
                    .overrideOptionsIfNeeded(callingPackage, checkedOptions);
        }

        // 不进入
        if (mService.mController != null) {
           //......
        }

        // 启动过程支持添加拦截器
        mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
        if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, 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;
        }

        // 如果权限不够,return 退出
        if (abort) {
            if (resultRecord != null) {
                resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
                        RESULT_CANCELED, null);
            }
            // 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)) {
                // ......
            }
        }

        // If we have an ephemeral app, abort the process of launching the resolved intent.
        // Instead, launch the ephemeral installer. Once the installer is finished, it
        // starts either the intent we resolved here [on install error] or the ephemeral
        // app [on install success].

        // 不进入
        if (rInfo != null && rInfo.auxiliaryInfo != null) {
           //......
        }

        // 创建 ActivityRecord
        // 需要注意,构造函数内部 new 了一个 Token
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, checkedOptions, sourceRecord);
        if (outActivity != null) {
            outActivity[0] = 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;
        }

        final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();


        // 不进入
        // If we are starting an activity that is not from the same uid as the currently resumed
        // one, check whether app switches are allowed.
        if (voiceSession == null && (stack.getResumedActivity() == null
                || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
           // ......
        }

        mService.onStartActivitySetDidAppSwitch();
        mController.doPendingActivityLaunches(false);

        // 接着调另一个重载
        final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity);
        mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outActivity[0]);
        return res;
    }

方法很长,基本的流程如下:

  • 获取到调用者的进程信息 WindowProcessController callerApp,WindowProcessController 是 WMS 与 AMS 通信的工具类,内部也保存了进程相关的信息
  • 各类权限检测
  • 调用 Activity 启动过程拦截器
  • new 一个 ActivityRecord
  • 调用另一个重载 startActivity

参考资料

相关推荐
敲代码敲到头发茂密25 分钟前
【大语言模型】LangChain 核心模块介绍(Memorys)
android·语言模型·langchain
H1001 小时前
重构(二)
android·重构
拓端研究室2 小时前
R基于贝叶斯加法回归树BART、MCMC的DLNM分布滞后非线性模型分析母婴PM2.5暴露与出生体重数据及GAM模型对比、关键窗口识别
android·开发语言·kotlin
zhangphil2 小时前
Android简洁缩放Matrix实现图像马赛克,Kotlin
android·kotlin
m0_512744642 小时前
极客大挑战2024-web-wp(详细)
android·前端
lw向北.3 小时前
Qt For Android之环境搭建(Qt 5.12.11 Qt下载SDK的处理方案)
android·开发语言·qt
不爱学习的啊Biao3 小时前
【13】MySQL如何选择合适的索引?
android·数据库·mysql
Clockwiseee3 小时前
PHP伪协议总结
android·开发语言·php
mmsx10 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
众拾达人13 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言