Android--Activity的创建过程

Activity的创建过程概述

Activity的启动可以是应用启动时默认Activity的创建启动,也可以是从当前Activity跳转到未创建的目标Activity,本篇主要针对当前Activity跳转到未创建目标Activity的过程,新Activity的创建过程进行解析。

当前Activity启动新Activity的操作

当某个Activity要跳转到另一个Activity时,会发起startActivity,从程序员编写的Activity中跳转到Activity.java中;

  • Activity中的startActivity()方法
  1. 首先会检查是否存在需要恢复的自动填充会话mIntent, 如果包含额外的恢复会话令牌和恢复交叉活动需要执行一些额外操作;
  2. 如果当前活动与即将启动的活动在同一个包中,应用会自动填充恢复机制,获取AutofillManager.EXTRA_RESTORE_SESSION_TOKEN 的 IBinder 对象存储在intent中,以便在启动的新活动中进行恢复操作;
  3. 然后将恢复能力从当前活动中移除,添加到即将启动的活动中。然后根据选项options参数调用startActivityForResult方法启动新的Activity。
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    // 检查是否存在需要恢复的自动填充会话
    if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)
            && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) {
        // 检查当前活动和要启动的活动是否属于同一个应用程序
        if (TextUtils.equals(getPackageName(),
                intent.resolveActivity(getPackageManager()).getPackageName())) {
            // 应用自动填充恢复机制到通过startActivity()启动的活动
            final IBinder token =
                    mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
            // 从当前活动中移除恢复能力
            mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
            mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY);
            // 将恢复令牌放入intent中
            intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
            intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);
        }
    }
    // 如果提供了选项,则使用选项启动活动
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        // 注意我们想要通过这个调用来兼容可能已经重写了该方法的应用程序
        startActivityForResult(intent, -1);
    }
}

  • Activity中的startActivityForResult()方法

startActivityForResult方法用于启动一个新Activity并等待返回结果的。首先会检查当前活动是否有父活动,如果有的话需要调用startActivityForChild方法来启动新的Activity,如果没有的话则在当前方法中启动新的Activity。
当前活动无父活动,启动新的Activity:

  1. 首先对options选项进行处理,如果options参数是空会默认获取当前活动的选项,选项中的是场景过度的动画类型;
  2. 然后使用mInstrumentation.execStartActivity() 方法启动新的活动,并将启动结果存储在 ar 变量中;
  3. 当启动结果不为空时,通过ActivityThread.sendActivityResult()方法将活动启动结果发送给启动该活动的父活动;
  4. 如果requestCode大于等于0表示需要等待返回结果,将mStartedActivity设置为true,在结果返回之前保持活动不可见;
  5. 最后清除输入焦点、停止动画。
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
    if (mParent == null) {
        // 处理传入的选项,可能用于对选项进行一些特定的处理或配置
        options = transferSpringboardActivityOptions(options);
        // 启动新的活动,返回一个ActivityResult对象,该对象包含了新活动的启动结果
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            // 如果ActivityResult对象不为空,说明新活动已经成功启动,sendActivityResult()方法发送活动结果,
            // 将令牌、嵌入式ID、请求码、结果代码和结果数据作为参数传递给新活动
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            // 如果requestCode大于等于0,表示需要等待返回结果,将mStartedActivity设置为true,以便在结果返回之前保持活动不可见
            mStartedActivity = true;
        }
        // 取消输入并开始退出过渡动画,用于清除输入焦点、停止动画等操作
        cancelInputsAndStartExitTransition(options);
    } else {
        // 如果该活动非父活动,则走startActivityFromChild方法,执行流程与startActivityForResult()一致,
        // execStartActivity和sendActivityResult传递的参数改为子活动
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

  • Instrumentation中的execStartActivity()方法

execStartActivity()是用于启动一个新活动的公共方法,接收7个参数(Context 当前活动上下文,IBinder contextThread当前活动的线程,IBinder token 当前活动的标识符,Activity target 目标活动,Intent intent 要启动的活动的意图,int requestCode 请求码,Bundle options 启动选项)。

execStartActivity()方法内部,会根据传入的参数调用startActivityAsUser方法创建一个新的Activity实例,并调用其onCreate()方法进行初始化,然后将新的Activity实例添加到Activity栈中,并将其设置为当前运行的Activity。

execStartActivity()方法是在应用程序的主线程中执行的,如果该方法中有耗时的操作,可能会导致界面卡顿或ANR错误;在实际应用中,通常会使用Handler或其他异步机制来避免这种情况的发生。

  1. 将 contextThread 转换为 IApplicationThread 类型的 whoThread;
  2. 调用 target.onProvideReferrer() 方法获取引用者referrer,并将其添加到意图中;
  3. 如果有活动监视器存在,遍历所有ActivityMonitor:
    ① 如果有当前ActivityMonitor忽略特定意图匹配,则直接通过onStartActivity(intent) 方法启动活动,将结果存储在 result 变量中;如果result不会空则增加ActivityMonitor的命中次数mHits,将result返回;
    ② 否则需要判断特定意图匹配,如果活动监视器与给定的上下文、包名和意图匹配,则增加活动监视器的命中次数(mHits);如果活动监视器是阻塞的,则根据请求码返回相应的结果或 null,否则,跳出循环。
  4. 最后代码会尝试启动新的活动:
    ① 首先调用 intent.migrateExtraStreamToClipData(who) 方法将额外数据迁移到剪贴板;
    ② 然后调用 intent.prepareToLeaveProcess(who) 方法准备离开进程;
    ③ 最后使用 ActivityTaskManager.getService().startActivity() 方法启动新的活动,并检查启动结果。
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, String resultWho,
            Intent intent, int requestCode, Bundle options, UserHandle user) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        result = am.onStartActivity(intent);
                    }
                    if (result != null) {
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
            int result = ActivityTaskManager.getService().startActivityAsUser(whoThread,
                    who.getBasePackageName(), who.getAttributionTag(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()), token, resultWho,
                    requestCode, 0, null, options, user.getIdentifier());
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }


总的来说,execStartActivity()启动新活动分为2种:

  1. 当活动监视器存在且忽略特定意图匹配时,会通过ActivityMonitor中的onStartActivity(intent) 方法处理应用程序中的启动意图,根据需要进行相应操作,从而启动新活动;
  2. 其他情况下都会通过ActivityTaskManager.getService().startActivity()方法,将活动的启动意图传递给系统服务器来启动目标活动的。
系统服务器启动新的Activity

LauncherAppsService和ActivityTaskManagerService中都有用于启动一个Activity的startActivityAsUser方法,ActivityTaskManagerService是负责管理Activity的生命周期和调度,而LauncherAppsService是用于管理从启动器Launcher启动的应用,所以当从一个Activity跳转到另一个Activity的过程调用的是ActivityTaskManagerService中的startActivityAsUser方法。

  • ATMS,即ActivityTaskManagerService,是Android 10中引入的一个新的系统服务,专门负责管理Activity及其容器(任务、堆栈、显示等)。
  • 在Android 10之前,Android的四大组件(Activity、Service、BroadcastReceiver和ContentProvider)统一由AMS(ActivityManagerService)进行管理。但随着Android系统的发展和功能的增加,为了更好地管理和优化Activity,Android 10对这一部分功能进行了分离,将AMS中与Activity相关的管理职责划分给了新的ATMS。
  • ActivityTaskManagerService中的startActivityAsUser()方法

ActivityTaskManagerService中startActivityAsUser方法用于启动一个Activity,并指定用户ID,该方法会接收13个参数:

  • IApplicationThread caller:调用者的应用线程,用于标识启动Activity的应用程序。
  • String callingPackage:调用者的包名,用于验证调用者的权限。
  • @Nullable String callingFeatureId:调用者的功能ID,用于处理特定的功能请求。
  • Intent intent:要启动的Activity的意图(Intent),包含了启动Activity所需的信息。
  • String resolvedType:意图中指定的数据类型,用于解析Intent的数据。
  • IBinder resultTo:用于接收结果的Binder对象,如果不需要返回结果则为null。
  • String resultWho:用于标识结果接收者的字符串,如果不需要返回结果则为null。
  • int requestCode:请求码,用于标识启动Activity的请求。
  • int startFlags:启动标志,用于控制Activity的启动行为。
  • ProfilerInfo profilerInfo:性能分析信息,用于监控Activity的启动过程。
  • Bundle bOptions:Activity选项,用于配置Activity的行为。
  • int userId:目标用户的ID,用于指定要启动Activity的用户。
  • boolean validateIncomingUser:是否验证传入的用户ID,如果为true则进行验证。
  1. 首先通过assertPackageMatchesCallingUid方法验证调用者的包名与调用者的UID是否匹配,并使用enforceNotIsolatedCaller方法检查调用者是否为隔离进程,确保只有非隔离进程可以进行接下来的步骤启动新的Activity,以保护系统的安全性和稳定性;
  2. 然后通过getActivityStartController().checkTargetUser方法检查目标用户ID是否有效,并获取目标用户的进程ID和UID;
  3. 最后使用getActivityStartController().obtainStarter方法创建一个启动器(Starter)对象,并通过链式调用设置各种参数,最后调用execute方法执行启动操作。
    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) {
        assertPackageMatchesCallingUid(callingPackage);
        enforceNotIsolatedCaller("startActivityAsUser");

        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // 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(bOptions)
                .setUserId(userId)
                .execute();

    }

obtainStarter会获取ActivityStarter,该对象提供了一些列设置方法配置启动的Activity,并执行了ActivityStarter的execute()方法:

  • ActivityStarter中的execute()方法
  1. 检查Intent中是否包含文件描述符,如果有则抛出异常;
  2. 获取ActivityRecord对象和LaunchingState对象;
  3. 如果调用者还没有解析Activity,那么在这里进行解析;
  4. 根据全局配置是否发生变化,执行相应的操作:

① 如果发生变化设置标志位;② 清除调用者的身份信息;③ 尝试解析到重量级切换器(如果需要),如果解析失败,则返回错误码;④ 执行请求executeRequest(),并恢复调用者的身份信息;⑤ 如果全局配置发生了变化,那么在当前活动暂停时进行新的配置切换;⑥ 等待当前活动暂停,更新全局配置;

  1. 通知ActivityMetricsLogger活动已启动,并返回结果。
  1. ActivityStarter是一个控制器,负责解释解释如何在特定的时间和方式下启动一个Activity;
  2. execute()作为外部接口,触发整个启动过程,而新Activity的具体的启动逻辑和记录创建会走到executeRequest()方法中执行;
    int execute() {
        try {
            // Refuse possible leaked file descriptors
            if (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) {
                throw new IllegalArgumentException("File descriptors passed in Intent");
            }

            final LaunchingState launchingState;
            synchronized (mService.mGlobalLock) {
                final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo);
                launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(
                        mRequest.intent, caller);
            }

            // 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) {
                mRequest.resolveActivity(mSupervisor);
            }

            int res;
            synchronized (mService.mGlobalLock) {
                final boolean globalConfigWillChange = mRequest.globalConfig != null
                        && mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;
                final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
                if (stack != null) {
                    stack.mConfigWillChange = globalConfigWillChange;
                }
                if (DEBUG_CONFIGURATION) {
                    Slog.v(TAG_CONFIGURATION, "Starting activity when config will change = "
                            + globalConfigWillChange);
                }

                final long origId = Binder.clearCallingIdentity();

                res = resolveToHeavyWeightSwitcherIfNeeded();
                if (res != START_SUCCESS) {
                    return res;
                }
                res = executeRequest(mRequest);

                Binder.restoreCallingIdentity(origId);

                if (globalConfigWillChange) {
                    // If the caller also wants to switch to a new configuration, do so now.
                    // This allows a clean switch, as we are waiting for the current activity
                    // to pause (so we will not destroy it), and have not yet started the
                    // next activity.
                    mService.mAmInternal.enforceCallingPermission(
                            android.Manifest.permission.CHANGE_CONFIGURATION,
                            "updateConfiguration()");
                    if (stack != null) {
                        stack.mConfigWillChange = false;
                    }
                    if (DEBUG_CONFIGURATION) {
                        Slog.v(TAG_CONFIGURATION,
                                "Updating to new configuration after starting activity.");
                    }
                    mService.updateConfigurationLocked(mRequest.globalConfig, null, false);
                }

                // Notify ActivityMetricsLogger that the activity has launched.
                // ActivityMetricsLogger will then wait for the windows to be drawn and populate
                // WaitResult.
                mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
                        mLastStartActivityRecord);
                return getExternalResult(mRequest.waitResult == null ? res
                        : waitForResult(res, mLastStartActivityRecord));
            }
        } finally {
            onExecutionComplete();
        }
    }


  • ActivityStarter中的executeRequest()方法

执行启动新Activity的请求会进行以下操作:

  1. 清除调用者的身份信息:使用Binder.clearCallingIdentity()方法清除调用者的身份信息,以便在后续的操作中以系统权限运行。
  2. 检查并处理启动模式:根据请求中的启动模式(如标准启动、单实例启动等),确定如何处理Activity的启动。这可能涉及检查任务栈中是否存在要启动的Activity实例,并根据需要处理启动模式。
  3. 解析Activity:如果调用者尚未解析目标Activity,executeRequest会在这里进行解析。这包括查找匹配的Activity组件、验证其存在并获取相关的ActivityInfo对象。
  4. 检查权限和URI权限:在启动Activity之前,executeRequest还会进行权限检查。如果Intent携带了数据URI,并且需要动态检查URI权限,那么会在此进行相应的权限验证。
  5. 启动Activity:通过调用mService.startActivity方法来启动目标Activity。这会将请求传递给系统的ActivityManagerService,由其负责实际的Activity启动过程。
  6. 恢复调用者的身份信息:使用Binder.restoreCallingIdentity(origId)方法恢复之前清除的调用者身份信息。
  7. 处理结果:如果请求中指定了等待结果,那么executeRequest会等待目标Activity的结果返回,并将其返回给调用者。
  8. 处理全局配置变更:如果在启动过程中全局配置发生了变化,executeRequest会根据需要进行相应的处理,例如更新系统的配置信息。
  9. 通知ActivityMetricsLogger:最后,executeRequest会通知ActivityMetricsLogger活动已启动,以便进行性能数据的收集和记录。

其中在执行请求的过程中,创建了本次将要启动的ActivityRecord(目标Activity在AMS中的数据结构)

    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;

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

        ActivityRecord sourceRecord = null;
        ActivityRecord resultRecord = null;
        if (resultTo != null) {
            sourceRecord = mRootWindowContainer.isInAnyStack(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();
        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
            // Transfer the result target from the source activity to the new one being started,
            // including any failures.
            if (requestCode >= 0) {
                SafeActivityOptions.abort(options);
                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
            }
            resultRecord = sourceRecord.resultTo;
            if (resultRecord != null && !resultRecord.isInStackLocked()) {
                resultRecord = null;
            }
            resultWho = sourceRecord.resultWho;
            requestCode = sourceRecord.requestCode;
            sourceRecord.resultTo = null;
            if (resultRecord != null) {
                resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
            }
            if (sourceRecord.launchedFromUid == callingUid) {
                // The new activity is being launched from the same uid as the previous activity
                // in the flow, and asking to forward its result back to the previous.  In this
                // case the activity is serving as a trampoline between the two, so we also want
                // to update its launchedFromPackage to be the same as the previous activity.
                // Note that this is safe, since we know these two packages come from the same
                // uid; the caller could just as well have supplied that same package name itself
                // . This specifially deals with the case of an intent picker/chooser being
                // launched in the app flow to redirect to an activity picked by the user, where
                // we want the final activity to consider it to have been launched by the
                // previous app activity.
                callingPackage = sourceRecord.launchedFromPackage;
                callingFeatureId = sourceRecord.launchedFromFeatureId;
            }
        }

        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
            // We couldn't find a class that can handle the given Intent.
            // That's the end of that!
            err = ActivityManager.START_INTENT_NOT_RESOLVED;
        }

        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
            // We couldn't find the specific class specified in the Intent.
            // Also the end of the line.
            err = ActivityManager.START_CLASS_NOT_FOUND;
        }

        if (err == ActivityManager.START_SUCCESS && sourceRecord != null
                && sourceRecord.getTask().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) {
                try {
                    intent.addCategory(Intent.CATEGORY_VOICE);
                    if (!mService.getPackageManager().activitySupportsIntent(
                            intent.getComponent(), intent, resolvedType)) {
                        Slog.w(TAG, "Activity being started in current voice task does not support "
                                + "voice: " + intent);
                        err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                    }
                } catch (RemoteException e) {
                    Slog.w(TAG, "Failure checking voice capabilities", e);
                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                }
            }
        }

        if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
            // If the caller is starting a new voice session, just make sure the target
            // is actually allowing it to run this way.
            try {
                if (!mService.getPackageManager().activitySupportsIntent(intent.getComponent(),
                        intent, resolvedType)) {
                    Slog.w(TAG,
                            "Activity being started in new voice task does not support: " + intent);
                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Failure checking voice capabilities", e);
                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
            }
        }

        final ActivityStack resultStack = 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 = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                requestCode, callingPid, callingUid, callingPackage, callingFeatureId,
                request.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;
        if (!abort) {
            try {
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
                        "shouldAbortBackgroundActivityStart");
                restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
                        callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
                        request.originatingPendingIntent, request.allowBackgroundActivityStart,
                        intent);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
            }
        }

        // Merge the two options bundles, while realCallerOptions takes precedence.
        ActivityOptions checkedOptions = options != null
                ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null;
        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, 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)) {
                final IIntentSender target = mService.getIntentSenderLocked(
                        ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, callingFeatureId,
                        callingUid, userId, null, null, 0, new Intent[]{intent},
                        new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
                                | PendingIntent.FLAG_ONE_SHOT, null);

                Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);

                int flags = intent.getFlags();
                flags |= Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;

                /*
                 * Prevent reuse of review activity: Each app needs their own review activity. By
                 * default activities launched with NEW_TASK or NEW_DOCUMENT try to reuse activities
                 * with the same launch parameters (extras are ignored). Hence to avoid possible
                 * reuse force a new activity via the MULTIPLE_TASK flag.
                 *
                 * Activities that are not launched with NEW_TASK or NEW_DOCUMENT are not re-used,
                 * hence no need to add the flag in this case.
                 */
                if ((flags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT)) != 0) {
                    flags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
                }
                newIntent.setFlags(flags);

                newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
                newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
                if (resultRecord != null) {
                    newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
                }
                intent = newIntent;

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

                resolvedType = null;
                callingUid = realCallingUid;
                callingPid = realCallingPid;

                rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0,
                        computeResolveFilterUid(
                                callingUid, realCallingUid, request.filterCallingUid));
                aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
                        null /*profilerInfo*/);

                if (DEBUG_PERMISSIONS_REVIEW) {
                    final ActivityStack focusedStack =
                            mRootWindowContainer.getTopDisplayFocusedStack();
                    Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
                            true, false) + "} from uid " + callingUid + " on display "
                            + (focusedStack == null ? DEFAULT_DISPLAY
                                    : focusedStack.getDisplayId()));
                }
            }
        }

        // 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) {
            intent = createLaunchIntent(rInfo.auxiliaryInfo, request.ephemeralIntent,
                    callingPackage, callingFeatureId, verificationBundle, resolvedType, userId);
            resolvedType = null;
            callingUid = realCallingUid;
            callingPid = realCallingPid;

            // The ephemeral installer shouldn't get any permission grants
            // intended for the original destination
            intentGrants = null;

            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
        }

        final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, callingFeatureId, intent, resolvedType, aInfo,
                mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode,
                request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions,
                sourceRecord);
        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;
        }

        final ActivityStack stack = mRootWindowContainer.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 != null && (stack.getResumedActivity() == null
                || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                    realCallingPid, realCallingUid, "Activity start")) {
                if (!(restrictedBgActivity && handleBackgroundActivityAbort(r))) {
                    mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
                            sourceRecord, startFlags, stack, callerApp, intentGrants));
                }
                ActivityOptions.abort(checkedOptions);
                return ActivityManager.START_SWITCHES_CANCELED;
            }
        }

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

        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
                restrictedBgActivity, intentGrants);

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

        return mLastStartActivityResult;
    }


  • ActivityStarter中的startActivityUnchecked()方法

执行请求executeRequest,主要通过调用startActivityUnchecked方法来启动目标Activity,将请求传递给系统的ActivityManagerService执行Activity启动过程:

  1. 首先调用mService.deferWindowLayout()来暂停窗口布局更新;
  2. 然后调用startActivityInner()方法执行实际的Activity启动操作,并将返回的结果赋值给result变量;
  3. 通过handleStartResult()方法处理启动结果,并获取启动的Activity所在的任务栈startedActivityStack;
  4. 调用postStartActivityProcessing()方法进行后续处理,并返回启动结果。

startActivityUnchecked()方法更多地处理与客户端相关的逻辑,而startActivityInner()方法则处理与服务端即系统服务进程(system_server)的交互。

    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, Task inTask,
                boolean restrictedBgActivity, NeededUriGrants intentGrants) {
        int result = START_CANCELED;
        final ActivityStack startedActivityStack;
        try {
            mService.deferWindowLayout();
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
            result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
            startedActivityStack = handleStartResult(r, result);
            mService.continueWindowLayout();
        }

        postStartActivityProcessing(r, result, startedActivityStack);

        return result;
    }

  • ActivityStarter中的startActivityInner()方法

startActivityInner方法是启动一个Activity的核心方法,处理了启动Activity所需的各种参数和逻辑,包括任务栈管理、权限检查、URI权限授予等:

  1. setInitialState设置初始状态:根据传入的参数设置Activity的初始状态,如启动标志、任务栈等。
  2. computeLaunchingTaskFlags计算任务栈标志:根据当前任务栈的情况计算任务栈标志。
  3. computeSourceStack计算源任务栈:获取启动Activity的任务栈。
  4. Intent.setFlags设置Intent标志:将计算出的任务栈标志设置到Intent中。
  5. getReusableTask获取可重用的任务:尝试从最近任务列表中获取可重用的任务。
  6. isAllowedToStart检查是否有权限启动:检查调用者是否有权限启动目标Activity。
  7. recycleTask回收任务:如果有可重用的任务,将其回收到目标任务栈中。
  8. getLaunchStack获取目标任务栈:根据计算出的任务栈标志获取目标任务栈。
  9. 创建新任务:如果需要创建新任务,则创建新任务并将其setNewTask关联到目标任务栈。
  10. Service.getLockTaskController().isLockTaskModeViolation检查锁屏模式:如果启动的Activity违反了锁屏模式,则返回错误。
  11. addOrReparentStartingActivity添加或重新设置启动活动Activity的父级:将启动的Activity添加到目标任务栈中。
  12. isTopStackInDisplayArea移动到前台:如果需要,将目标任务栈移动到前台。
  13. getUriPermissionsLocked授予URI权限:从Intent中获取URI权限并授予给目标Activity。
  14. getPackageManagerInternalLocked授予隐式访问权限:如果需要,为目标Activity授予隐式访问权限。
  15. logStartActivity记录任务创建事件:记录任务创建事件。
  16. 启动Activity:调用目标任务栈的startActivityLocked方法启动Activity。
  17. resumeFocusedStacksTopActivities恢复焦点:如果需要,恢复目标任务栈的焦点。
  18. updateUserStack更新用户任务栈:更新用户的任务栈信息。
  19. handleNonResizableTaskIfNeeded处理不可调整大小的Task:如果需要,处理不可调整大小的Task。
  20. 最后,return START_SUCCESS返回成功启动的结果。
  1. 这个方法会判断目标Activity应该归属哪个TaskRecord和ActivityStack,默认情况下会调用setTaskFromSourceRecord(),即新建的Activity默认是属于发起方Activity所在的TaskRecord;
  2. 新的Activity的启动是调用ActivityStack中的startActivityLocked方法,将新的Activity放到栈顶;
  3. 新的Activity移到栈顶后调用RootWindowContainer中的resumeFocusedStacksTopActivities()方法显示新的Activity;
    int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            boolean restrictedBgActivity, NeededUriGrants intentGrants) {
        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor, restrictedBgActivity);

        computeLaunchingTaskFlags();

        computeSourceStack();

        mIntent.setFlags(mLaunchFlags);

        final Task reusedTask = getReusableTask();

        // If requested, freeze the task list
        if (mOptions != null && mOptions.freezeRecentTasksReordering()
                && mSupervisor.mRecentTasks.isCallerRecents(r.launchedFromUid)
                && !mSupervisor.mRecentTasks.isFreezeTaskListReorderingSet()) {
            mFrozeTaskList = true;
            mSupervisor.mRecentTasks.setFreezeTaskListReordering();
        }

        // Compute if there is an existing task that should be used for.
        final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
        final boolean newTask = targetTask == null;
        mTargetTask = targetTask;

        computeLaunchParams(r, sourceRecord, targetTask);

        // Check if starting activity on given task or on a new task is allowed.
        int startResult = isAllowedToStart(r, newTask, targetTask);
        if (startResult != START_SUCCESS) {
            return startResult;
        }

        final ActivityRecord targetTaskTop = newTask
                ? null : targetTask.getTopNonFinishingActivity();
        if (targetTaskTop != null) {
            // Recycle the target task for this launch.
            startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);
            if (startResult != START_SUCCESS) {
                return startResult;
            }
        } else {
            mAddingToTask = true;
        }

        // If the activity being launched is the same as the one currently at the top, then
        // we need to check if it should only be launched once.
        final ActivityStack topStack = mRootWindowContainer.getTopDisplayFocusedStack();
        if (topStack != null) {
            startResult = deliverToCurrentTopIfNeeded(topStack, intentGrants);
            if (startResult != START_SUCCESS) {
                return startResult;
            }
        }

        if (mTargetStack == null) {
            mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, targetTask, mOptions);
        }
        if (newTask) {
            final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                    ? mSourceRecord.getTask() : null;
            setNewTask(taskToAffiliate);
            if (mService.getLockTaskController().isLockTaskModeViolation(
                    mStartActivity.getTask())) {
                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }
        } else if (mAddingToTask) {
            addOrReparentStartingActivity(targetTask, "adding to task");
        }

        if (!mAvoidMoveToFront && mDoResume) {
            mTargetStack.getStack().moveToFront("reuseOrNewTask", targetTask);
            if (mOptions != null) {
                if (mOptions.getTaskAlwaysOnTop()) {
                    mTargetStack.setAlwaysOnTop(true);
                }
            }
            if (!mTargetStack.isTopStackInDisplayArea() && mService.mInternal.isDreaming()) {
                // Launching underneath dream activity (fullscreen, always-on-top). Run the launch-
                // -behind transition so the Activity gets created and starts in visible state.
                mLaunchTaskBehind = true;
                r.mLaunchTaskBehind = true;
            }
        }

        mService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants,
                mStartActivity.getUriPermissionsLocked());
        if (mStartActivity.resultTo != null && mStartActivity.resultTo.info != null) {
            // we need to resolve resultTo to a uid as grantImplicitAccess deals explicitly in UIDs
            final PackageManagerInternal pmInternal =
                    mService.getPackageManagerInternalLocked();
            final int resultToUid = pmInternal.getPackageUidInternal(
                            mStartActivity.resultTo.info.packageName, 0, mStartActivity.mUserId);
            pmInternal.grantImplicitAccess(mStartActivity.mUserId, mIntent,
                    UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) /*recipient*/,
                    resultToUid /*visible*/, true /*direct*/);
        }
        if (newTask) {
            EventLogTags.writeWmCreateTask(mStartActivity.mUserId,
                    mStartActivity.getTask().mTaskId);
        }
        mStartActivity.logStartActivity(
                EventLogTags.WM_CREATE_ACTIVITY, mStartActivity.getTask());

        mTargetStack.mLastPausedActivity = null;

        mRootWindowContainer.sendPowerHintForLaunchStartIfNeeded(
                false /* forceSend */, mStartActivity);

        mTargetStack.startActivityLocked(mStartActivity, topStack.getTopNonFinishingActivity(),
                newTask, mKeepCurTransition, mOptions);
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isTopActivityFocusable()
                    || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                    && mStartActivity != topTaskActivity)) {
                // If the activity is not focusable, we can't resume it, but still would like to
                // make sure it becomes visible as it starts (this will also trigger entry
                // animation). An example of this are PIP activities.
                // Also, we don't want to resume activities in a task that currently has an overlay
                // as the starting activity just needs to be in the visible paused state until the
                // over is removed.
                // Passing {@code null} as the start parameter ensures all activities are made
                // visible.
                mTargetStack.ensureActivitiesVisible(null /* starting */,
                        0 /* configChanges */, !PRESERVE_WINDOWS);
                // Go ahead and tell window manager to execute app transition for this activity
                // since the app transition will not be triggered through the resume channel.
                mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
            } else {
                // If the target stack was not previously focusable (previous top running activity
                // on that stack was not visible) then any prior calls to move the stack to the
                // will not update the focused stack.  If starting the new activity now allows the
                // task stack to be focusable, then ensure that we now update the focused stack
                // accordingly.
                if (mTargetStack.isTopActivityFocusable()
                        && !mRootWindowContainer.isTopDisplayFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityInner");
                }
                mRootWindowContainer.resumeFocusedStacksTopActivities(
                        mTargetStack, mStartActivity, mOptions);
            }
        }
        mRootWindowContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);

        // Update the recent tasks list immediately when the activity starts
        mSupervisor.mRecentTasks.add(mStartActivity.getTask());
        mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
                mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetStack);

        return START_SUCCESS;
    }


  • ActivityStack中的startActivityLocked()方法

该方法主要负责实际的Task和Activity的进栈处理:

  1. 获取ActivityRecore所属的任务,并将其任务positionChildAtTop移到栈顶;
  2. 如果有其他Activity遮挡新Activity,将新Activity放在已有任务的顶部;
  3. 根据新Activity的Intent来准备启动的过渡动画;
  4. 根据Intent来设置新Activity是否显示的变量doShow;
  5. 设置后台启动逻辑,调用ensureActivitiesVisible方法确保所有活动都可见;
  6. 根据doShow变量处理新Activity显示启动预览逻辑,调用showStartingWindow方法来显示新Activity的启动预览窗口;
  7. 如果不满足条件,则ActivityOptions.abort(options)取消动画选项;
void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
            boolean newTask, boolean keepCurTransition, ActivityOptions options) {
        Task rTask = r.getTask();
        final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
        final boolean isOrhasTask = rTask == this || hasChild(rTask);
        // mLaunchTaskBehind tasks get placed at the back of the task stack.
        if (!r.mLaunchTaskBehind && allowMoveToFront && (!isOrhasTask || newTask)) {
            // Last activity in task had been removed or ActivityManagerService is reusing task.
            // Insert or replace.
            // Might not even be in.
            positionChildAtTop(rTask);
        }
        Task task = null;
        if (!newTask && isOrhasTask) {
            // Starting activity cannot be occluding activity, otherwise starting window could be
            // remove immediately without transferring to starting activity.
            final ActivityRecord occludingActivity = getOccludingActivityAbove(r);
            if (occludingActivity != null) {
                // Here it is!  Now, if this is not yet visible (occluded by another task) to the
                // user, then just add it without starting; it will get started when the user
                // navigates back to it.
                if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task " + task,
                        new RuntimeException("here").fillInStackTrace());
                rTask.positionChildAtTop(r);
                ActivityOptions.abort(options);
                return;
            }
        }

        // Place a new activity at top of stack, so it is next to interact with the user.

        // If we are not placing the new activity frontmost, we do not want to deliver the
        // onUserLeaving callback to the actual frontmost activity
        final Task activityTask = r.getTask();
        if (task == activityTask && mChildren.indexOf(task) != (getChildCount() - 1)) {
            mStackSupervisor.mUserLeaving = false;
            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                    "startActivity() behind front, mUserLeaving=false");
        }

        task = activityTask;

        // Slot the activity into the history stack and proceed
        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
                new RuntimeException("here").fillInStackTrace());
        task.positionChildAtTop(r);

        // The transition animation and starting window are not needed if {@code allowMoveToFront}
        // is false, because the activity won't be visible.
        if ((!isHomeOrRecentsStack() || hasActivity()) && allowMoveToFront) {
            final DisplayContent dc = getDisplay().mDisplayContent;
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare open transition: starting " + r);
            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                dc.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
                mStackSupervisor.mNoAnimActivities.add(r);
            } else {
                int transit = TRANSIT_ACTIVITY_OPEN;
                if (newTask) {
                    if (r.mLaunchTaskBehind) {
                        transit = TRANSIT_TASK_OPEN_BEHIND;
                    } else if (getDisplay().isSingleTaskInstance()) {
                        // If a new task is being launched in a single task display, we don't need
                        // to play normal animation, but need to trigger a callback when an app
                        // transition is actually handled. So ignore already prepared activity, and
                        // override it.
                        transit = TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
                        keepCurTransition = false;
                    } else {
                        // If a new task is being launched, then mark the existing top activity as
                        // supporting picture-in-picture while pausing only if the starting activity
                        // would not be considered an overlay on top of the current activity
                        // (eg. not fullscreen, or the assistant)
                        if (canEnterPipOnTaskSwitch(focusedTopActivity,
                                null /* toFrontTask */, r, options)) {
                            focusedTopActivity.supportsEnterPipOnTaskSwitch = true;
                        }
                        transit = TRANSIT_TASK_OPEN;
                    }
                }
                dc.prepareAppTransition(transit, keepCurTransition);
                mStackSupervisor.mNoAnimActivities.remove(r);
            }
            boolean doShow = true;
            if (newTask) {
                // Even though this activity is starting fresh, we still need
                // to reset it to make sure we apply affinities to move any
                // existing activities from other tasks in to it.
                // If the caller has requested that the target task be
                // reset, then do so.
                if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                    resetTaskIfNeeded(r, r);
                    doShow = topRunningNonDelayedActivityLocked(null) == r;
                }
            } else if (options != null && options.getAnimationType()
                    == ActivityOptions.ANIM_SCENE_TRANSITION) {
                doShow = false;
            }
            if (r.mLaunchTaskBehind) {
                // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
                // tell WindowManager that r is visible even though it is at the back of the stack.
                r.setVisibility(true);
                ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
                // Go ahead to execute app transition for this activity since the app transition
                // will not be triggered through the resume channel.
                getDisplay().mDisplayContent.executeAppTransition();
            } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
                // Figure out if we are transitioning from another activity that is
                // "has the same starting icon" as the next one.  This allows the
                // window manager to keep the previous window it had previously
                // created, if it still had one.
                Task prevTask = r.getTask();
                ActivityRecord prev = prevTask.topActivityWithStartingWindow();
                if (prev != null) {
                    // We don't want to reuse the previous starting preview if:
                    // (1) The current activity is in a different task.
                    if (prev.getTask() != prevTask) {
                        prev = null;
                    }
                    // (2) The current activity is already displayed.
                    else if (prev.nowVisible) {
                        prev = null;
                    }
                }
                r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity));
            }
        } else {
            // If this is the first activity, don't do any fancy animations,
            // because there is nothing for it to animate on top of.
            ActivityOptions.abort(options);
        }
    }

  • RootWindowContainer中的resumeFocusedStacksTopActivities()方法

resumeFocusedStacksTopActivities()方法的作用是恢复焦点栈顶部的Activity,即将当前处于焦点状态的Activity恢复到栈顶,使其成为用户界面中可见和可交互的状态;

在Android系统中,每个窗口容器ActivityStack都有一个焦点栈,用于管理当前处于焦点状态的Activity,当用户切换到其他应用程序或任务时,焦点栈会发生变化,此时需要调用resumeFocusedStacksTopActivities()方法来恢复焦点栈顶部的Activity,确保用户界面的正确显示和交互体验;

  1. 首先检查是否准备好恢复,如果目标栈不为空且目标栈位于显示区域顶部或当前焦点栈为目标栈,那么调用;targetStack.resumeTopActivityUncheckedLocked()方法恢复目标栈顶部的Activity,并将结果赋值给result变量;
  2. 遍历所有显示区域,找到可聚焦且可见的堆栈,如果任务显示区域中的堆栈是顶部堆栈且顶部运行的Activity处于RESUMED状态,则executeAppTransition执行应用界面间的过渡操作;否则,调用makeActiveIfNeeded()方法使顶部运行的Activity变为活动状态;
  3. 如果在显示区域中没有恢复任何有效的Activity,则请求显式恢复焦点堆栈中的顶部Activity,以确保至少启动并恢复主Activity,并且不会发生递归;
  4. 最后,返回result变量的值。
    boolean resumeFocusedStacksTopActivities(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

        if (!mStackSupervisor.readyToResume()) {
            return false;
        }

        boolean result = false;
        if (targetStack != null && (targetStack.isTopStackInDisplayArea()
                || getTopDisplayFocusedStack() == targetStack)) {
            result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }

        for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
            boolean resumedOnDisplay = false;
            final DisplayContent display = getChildAt(displayNdx);
            for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
                final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
                for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
                    final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
                    final ActivityRecord topRunningActivity = stack.topRunningActivity();
                    if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
                        continue;
                    }
                    if (stack == targetStack) {
                        // Simply update the result for targetStack because the targetStack had
                        // already resumed in above. We don't want to resume it again, especially in
                        // some cases, it would cause a second launch failure if app process was
                        // dead.
                        resumedOnDisplay |= result;
                        continue;
                    }
                    if (taskDisplayArea.isTopStack(stack) && topRunningActivity.isState(RESUMED)) {
                        // Kick off any lingering app transitions form the MoveTaskToFront
                        // operation, but only consider the top task and stack on that display.
                        stack.executeAppTransition(targetOptions);
                    } else {
                        resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
                    }
                }
            }
            if (!resumedOnDisplay) {
                // In cases when there are no valid activities (e.g. device just booted or launcher
                // crashed) it's possible that nothing was resumed on a display. Requesting resume
                // of top activity in focused stack explicitly will make sure that at least home
                // activity is started and resumed, and no recursion occurs.
                final ActivityStack focusedStack = display.getFocusedStack();
                if (focusedStack != null) {
                    result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
                } else if (targetStack == null) {
                    result |= resumeHomeActivity(null /* prev */, "no-focusable-task",
                            display.getDefaultTaskDisplayArea());
                }
            }
        }

        return result;
    }


  • ActivityStack中的resumeTopActivityUncheckedLocked()方法

从一个Activity跳转到另一个Activity通常会调用ActivityStack中的resumeTopActivityUncheckedLocked()方法恢复目标栈顶部的Activity,该方法的作用是恢复栈顶的Activity实例,使其进入活动状态;

  1. 检查是否已经在恢复栈顶的Activity,然后调用resumeTopActivityInnerLocked()方法来实际恢复栈顶的Activity,并将结果保存在result变量中;

  2. 在恢复栈顶的Activity之后,需要调用checkReadyForSleep方法来确保必要的暂停逻辑发生;

  3. 在finally块中将mInResumeTopActivity设置为false,以允许后续的恢复操作。最终,方法返回result变量的值,表示恢复操作是否成功。

  4. 遍历所有窗口容器(如ActivityStack),找到当前处于焦点状态的窗口容器。

  5. 将焦点栈顶部的Activity设置为可见状态,并调用其onResume()方法,使其进入活动状态。

  6. 如果焦点栈中存在多个Activity,则依次将它们从栈顶向下移动,直到找到下一个处于暂停状态的Activity。

  7. 对于处于暂停状态的Activity,将其设置为不可见状态,并调用其onPause()方法,使其进入非活动状态。

  8. 将焦点栈顶部的Activity设置为可见状态,并调用其onResume()方法,使其进入活动状态。

  • RootWindowContainer中resumeTopActivityInnerLocked()方法

启动Activity之后调用resumeFocusedStacksTopActivities恢复焦点,最后会跳转到ActivityStack.resumeTopActivityInnerLocked()中,将正在显示的Activity onPause掉,然后显示目标Activity;

 private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {

    ...

        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            // 终止当前的activity
            pausing |= startPausingLocked(userLeaving, false /* uiSleeping */, next);
        }

    ...

        if (next.attachedToProcess()) {

            ...

        }else {
            // Whoops, need to restart this activity!
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else {
                if (SHOW_APP_STARTING_PREVIEW) {
                    next.showStartingWindow(null /* prev */, false /* newTask */,
                            false /* taskSwich */);
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
            }
            if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
            // 重新启动这个activity
            mStackSupervisor.startSpecificActivity(next, true, true);
        }

  • startSpecificActivity()方法

resumeTopActivityInnerLocked中调用ActivityStackSupervisor.startSpecificActivity()方法,该方法会判断Activity对应的进程是否存在,如果不存在,那么就会给ActivityManagerService发送一条创建新进程的消息。

  1. 检查目标Activity的应用程序是否已经在运行。如果应用程序已经在运行,realStartActivityLocked尝试直接启动目标Activity;
  2. 如果应用程序没有在运行,或者在尝试启动Activity时发生了异常(例如,因为进程已经死亡),那么它会重新启动应用程序;
  3. 如果这个Activity是当前任务栈的顶部Activity,并且需要恢复(用户正在与这个Activity交互),Service.startProcessAsync异步地启动目标Activity。
    void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        final WindowProcessController wpc =
                mService.getProcessController(r.processName, r.info.applicationInfo.uid);

        boolean knownToBeDead = false;
        if (wpc != null && wpc.hasThread()) {
            try {
                realStartActivityLocked(r, wpc, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

            // If a dead object exception was thrown -- fall through to
            // restart the application.
            knownToBeDead = true;
        }

        r.notifyUnknownVisibilityLaunchedForKeyguardTransition();

        final boolean isTop = andResume && r.isTopRunningActivity();
        mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
    }

  • startProcessAsync()方法

startSpecificActivity()未启动目标Activity就会走到ATMS中的startProcessAsync()方法,给AMS发送一条创建新进程的消息,创建目标Activity对应的进程:

  1. 首先检查是否启用了跟踪标签。如果启用了,那么它会开始跟踪这个操作;
  2. 创建一个消息,这个消息包含了启动进程所需的所有信息,包括进程名、应用程序信息、是否已知进程已经死亡、是否是顶层Activity以及宿主类型等;
  3. 将这个消息发送给Handler,由Handler来处理这个消息并启动进程。这样做的目的是避免在调用AMS时可能发生的死锁。
    void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
            String hostingType) {
        try {
            if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"
                        + activity.processName);
            }
            // Post message to start process to avoid possible deadlock of calling into AMS with the
            // ATMS lock held.
            final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
                    mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
                    isTop, hostingType, activity.intent.getComponent());
            mH.sendMessage(m);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }

  • startProcessLocked()方法

创建新线程的消息进入到AMS的startProcessLocked()中:

  1. 首先调用ProcessList的startProcessLocked方法来启动进程,需要传入进程名、应用程序信息、是否已知进程已经死亡、意图标志、宿主记录、Zygote策略标志、是否允许在系统启动时启动进程、是否隔离进程、是否保留大进程等参数;
  2. 然后返回一个ProcessRecord对象,这个对象代表了新启动的进程。

ProcessList内部会创建一个AppZygote对象,然后孵化出新的进程,

    final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
                hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
                keepIfLarge, null /* ABI override */, null /* entryPoint */,
                null /* entryPointArgs */, null /* crashHandler */);
    }

  • startProcess()

通过ProcessList.startProcessLocked()方法启动一个新进程会走到ProcessList类中的startProcess()方法:

  1. 检查是否需要使用WebView Zygote或App Zygote来启动新进程。
  2. 如果需要,为新进程创建一个App Zygote实例。
  3. 根据不同的条件,调用Process类的start方法来启动新进程。
  4. 返回一个ProcessStartResult对象,表示新进程的启动结果。
    private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
            int mountExternal, String seInfo, String requiredAbi, String instructionSet,
            String invokeWith, long startTime) {
        try {

            ...

            final Process.ProcessStartResult startResult;
            if (hostingRecord.usesWebviewZygote()) {
                startResult = startWebView(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName, app.mDisabledCompatChanges,
                        new String[]{PROC_START_SEQ_IDENT + app.startSeq});
            } else if (hostingRecord.usesAppZygote()) {
                final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);

                // We can't isolate app data and storage data as parent zygote already did that.
                startResult = appZygote.getProcess().start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName,
                        /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
                        app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
                        false, false,
                        new String[]{PROC_START_SEQ_IDENT + app.startSeq});
            } else {

            ...

            }
         }
      }

  • ActivityThread.main()

创建好新启动的进程后就走到了ActivityThread的主函数main()方法:

  1. 开始跟踪ActivityManager的启动过程。
  2. 安装选择性系统调用拦截。
  3. 关闭CloseGuard,因为它可能会产生很多不必要的日志。
  4. 初始化当前用户的环境。
  5. 确保TrustedCertificateStore在正确的位置查找CA证书。
  6. 调用每个进程的主要模块初始化。
  7. 设置进程参数。
  8. 准备主线程的Looper。
  9. 从命令行中查找PROC_START_SEQ_IDENT的值,如果提供了该值,它将以"seq=114"的格式出现。
  10. 创建一个新的ActivityThread实例,并将其附加到主线程。
  11. 如果sMainThreadHandler为null,则将其设置为新创建的ActivityThread的Handler。
  12. 如果需要,启用消息日志记录。
  13. 结束跟踪ActivityManager的启动过程。
  14. 进入主线程的Looper循环。
  15. 如果主线程循环意外退出,则抛出一个运行时异常。

其中主要步骤是:

  1. Looper.prepareMainLooper()初始化looper;
  2. new ActivityThread()创建一个新的ActivityThread实例,thread.attach将其附加到主线程上。
    public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        // Install selective syscall interception
        AndroidOs.install();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        // Call per-process mainline module initialization.
        initializeMainlineModules();

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();

        // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
        // It will be in the format "seq=114"
        long startSeq = 0;
        if (args != null) {
            for (int i = args.length - 1; i >= 0; --i) {
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

  • ActivityThread的attach()方法

该方法主要是把新创建的目标Activity对应的进程关联到AMS中;

  1. attachApplication()传入的mAppThread类型是ApplicationThread,是IApplicationThread的Binder接口本地实现类,用来接收AMS等其他进程的信息;
  2. mgr.attachApplication(mAppThread, startSeq)是一次IPC过程,会调用AMS服务中对应的方法;
    private void attach(boolean system, long startSeq) {

        ...

        if (!system) {
            ...
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }

            ...

        }

        ...


  • AMS的attachApplicationLocked()方法

AMS处理attachApplication的调用,主要是把进程名等进程的信息,通过IApplicationThread这个Binder接口传递给新创建的进程;

    private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
        ProcessRecord app;

        ...

if (app.isolatedEntryPoint != null) {
                // This is an isolated process which should just call an entry point instead of
                // being bound to an application.
                thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
            } else if (instr2 != null) {
                thread.bindApplication(processName, appInfo, providerList,
                        instr2.mClass,
                        profilerInfo, instr2.mArguments,
                        instr2.mWatcher,
                        instr2.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions,
                        app.mDisabledCompatChanges);
            } else {
                thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions,
                        app.mDisabledCompatChanges);
            }

        ...


  • RootWindowContainer的startActivityForAttachedApplicationIfNeeded()方法

在执行完bindApplication之后,AMS会继续调用到RootWindowContainer里面的realStartActivityLocked方法,找到与此进程相关联的Activity,并打开此Activity;

   private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
            WindowProcessController app, ActivityRecord top) {
        if (r.finishing || !r.okToShowLocked() || !r.visibleIgnoringKeyguard || r.app != null
                || app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {
            return false;
        }

        try {
            if (mStackSupervisor.realStartActivityLocked(r, app, top == r /*andResume*/,
                    true /*checkConfig*/)) {
                mTmpBoolean = true;
            }
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception in new application when starting activity "
                    + top.intent.getComponent().flattenToShortString(), e);
            mTmpRemoteException = e;
            return true;
        }
        return false;
    }

  • ActivityStackSupervisor的realStartActivityLocked()方法

AMS调用ActivityStackSupervisor的realStartActivityLocked()方法找到与进程相关联的Activity,这里的ClientTransaction,具备IPC的能力,通过内部的IApplicationThread Binder接口,会把自己作为参数传递给对应要操作的进程。本次的事务处理,ClientTransaction添加了一个LaunchActivityItem,说明要显示Activity的意图,打开目标Activity。

    boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
            boolean andResume, boolean checkConfig) throws RemoteException {

            ...

                final DisplayContent dc = r.getDisplay().mDisplayContent;
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
                        r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
                        dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
                        r.assistToken, r.createFixedRotationAdjustmentsIfNeeded()));

                ...
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);

  • ActivityThread的bindApplication()方法

应用进程首先会接收到AMS对bindApplication的回调,接收的位置是在ActivityThread内部,它是IApplicationThread的本地实现;

  1. bindApplication接收到来自AMS的绑定信息,主要是processName和ApplicationInfo;
  2. 最后给主线程Handler H 发送送一条信息,进程接收到的信息交由H处理;
        public final void bindApplication(String processName, ApplicationInfo appInfo,
                ProviderInfoList providerList, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                String buildSerial, AutofillOptions autofillOptions,
                ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) {

            ...

            setCoreSettings(coreSettings);\
            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providerList.getList();
            ...
            sendMessage(H.BIND_APPLICATION, data);

  • ActivityThread的主线程H

主线程H接收bindApplication发送的BIND_APPLICATION消息,处理应用程序绑定;

    class H extends Handler {
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

              ...


  • ActivityThread的handleBindApplication()方法

handleBindApplication方法用来处理应用程序绑定,该方法初始化了Android的上下文环境,同时还初始化了Application,并且回调了Application的onCreat()方法。其中关键代码行:

  1. setArgV0进程设置名称;
  2. setProcessPackageName设置包名;
  3. createAppContext创建ContextImpl;
  4. 创建mInstrumentation
  5. makeApplication利用反射创建了Manifest文件中对应的Application
  6. 调用Application的onCreat()方法
    private void handleBindApplication(AppBindData data) {

        ...

        Process.setArgV0(data.processName);
        ...
        VMRuntime.setProcessPackageName(data.appInfo.packageName);

        ...

            final ContextImpl instrContext = ContextImpl.createAppContext(this, pi,
                    appContext.getOpPackageName());

            try {
                final ClassLoader cl = instrContext.getClassLoader();
                mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
            } catch (Exception e) {
              ...
            }

            final ComponentName component = new ComponentName(ii.packageName, ii.name);
            mInstrumentation.init(this, instrContext, appContext, component,
                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection);

        ...

        Application app;
       ...
        try {
            app = data.info.makeApplication(data.restrictedBackupMode, null);
           ...
            try {
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
            catch (Exception e) {
               ...
            }
            try {
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
               ...
            }

  • ActivityThread的ApplicationThread 类

应用进程会收到ClientTransaction的方法回调;

    private class ApplicationThread extends IApplicationThread.Stub {

        ...

        @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            ActivityThread.this.scheduleTransaction(transaction);
        }

        ...

    }

    ...

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }


  • TransactionExecutor的executeCallbacks类

在接收到scheduleTransaction的回调之后,还是会把消息给到ActivityThread的H处理,H会把ClientTransaction这个消息给到TransactionExecutor处理;

TransactionExecutor会去执行ClientTransactionItem 内部的逻辑;

    public void executeCallbacks(ClientTransaction transaction) {
        final List<ClientTransactionItem> callbacks = transaction.getCallbacks();

        ...

for (int i = 0; i < size; ++i) {
            final ClientTransactionItem item = callbacks.get(i);
            if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);
            final int postExecutionState = item.getPostExecutionState();
            final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
                    item.getPostExecutionState());
            if (closestPreExecutionState != UNDEFINED) {
                cycleToPath(r, closestPreExecutionState, transaction);
            }

            item.execute(mTransactionHandler, token, mPendingActions);
            item.postExecute(mTransactionHandler, token, mPendingActions);

        ...


  • LaunchActivityItem类

execute中的client参数就是ActivityThread,ActivityThread实现了ClientTransactionHandler,这里就调用到了ActivityThread的handleLaunchActivity方法,同时把Activity的相关信息封装成了ActivityClientRecord 数据结构作为参数传递;

public class LaunchActivityItem extends ClientTransactionItem {

    ...

    @Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments);
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

    ...


  • ActivityThread的handleLaunchActivity()方法

该方法主要功能是处理启动Activity的操作:

  1. 首先,调用unscheduleGcIdler()方法取消垃圾回收的调度。
  2. 设置mSomeActivitiesChanged为true,表示有活动发生了变化。
  3. 如果r.profilerInfo不为空,则设置Profiler并开始分析。
  4. 确保运行的是最新的配置,如果需要的话预加载硬件渲染器。
  5. 初始化WindowManagerGlobal。
  6. 提示GraphicsEnvironment一个进程上的活动正在启动。
  7. 调用performLaunchActivity方法执行实际的启动操作,并将返回的Activity对象赋值给变量a。
  8. 如果a不为空,则进行以下操作:
    创建一个新的Configuration对象,并将其赋值给r.createdConfig。
    报告尺寸配置信息。
    如果r.activity未完成且pendingActions不为空,则设置pendingActions的旧状态、恢复实例状态和调用onPostCreate标志。
  9. 如果a为空,则表示有错误发生,通知ActivityManager停止当前进程。
  10. 最后,返回Activity对象a。
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        // Initialize before creating the activity
        if (!ThreadedRenderer.sRendererDisabled
                && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
            HardwareRenderer.preload();
        }
        WindowManagerGlobal.initialize();

        // Hint the GraphicsEnvironment that an activity is launching on the process.
        GraphicsEnvironment.hintActivityLaunch();

        final Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            if (!r.activity.mFinished && pendingActions != null) {
                pendingActions.setOldState(r.state);
                pendingActions.setRestoreInstanceState(true);
                pendingActions.setCallOnPostCreate(true);
            }
        } else {
            // If there was an error, for any reason, tell the activity manager to stop us.
            try {
                ActivityTaskManager.getService()
                        .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }

        return a;
    }

  • ActivityThread的performLaunchActivity()方法

performLaunchActivity方法执行实际的启动Activity操作:

  1. 首先会调用Activity的onCreate方法来创建Activity实例;
  2. 根据传入的Intent对象,可能会进行一些额外的处理,例如启动其他Activity、发送广播等;
  3. 将创建的Activity实例返回给调用者。

performLaunchActivity方法只是执行启动Activity的操作,具体的生命周期管理、消息传递等功能是由ActivityThread类的其他方法来完成的。

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            // AppComponentFactory利用反射生成Activity
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) {
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) {
                    config.updateFrom(r.overrideConfig);
                }
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }

                // Activity resources must be initialized with the same loaders as the
                // application context.
                appContext.getResources().addLoaders(
                        app.getResources().getLoaders().toArray(new ResourcesLoader[0]));

                appContext.setOuterContext(activity);
                // activity关联相关的信息,包括创建PhoneWindow
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    // 回调Activity的OnCreate回调方法
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                mLastReportedWindowingMode.put(activity.getActivityToken(),
                        config.windowConfiguration.getWindowingMode());
            }
            r.setState(ON_CREATE);

            // updatePendingActivityConfiguration() reads from mActivities to update
            // ActivityClientRecord which runs in a different thread. Protect modifications to
            // mActivities to avoid race.
            synchronized (mResourcesManager) {
                mActivities.put(r.token, r);
            }

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            }
        }

        return activity;
    }


在回调了OnCreate方法之后,目标Activity就算创建完成了;
下一步就是在设置contentview,attach到WMS上显示了。

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
img
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓(文末还有ChatGPT机器人小福利哦,大家千万不要错过)

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题
图片

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值