解析Activity的启动过程

Activity启动过程

     Activity 的启动过程分为两种, 一 种是根 Activity 的启动过程,另一 种是普通 Activity(子Activity)的启动过程。
 
      根Activity:以快捷图标的形式显示在Launcher中,它的启动过程代表了一个Android应用程序的启动过程。
      子Activity:由根Activity或其他子Activity启动,他们有可能与启动他们的Activity运行在同一个进程中,也可能运行在不同的进程中。
      
      本篇文章基于Android8.1系统来分析Activity的启动过程。
 

    1 根Activity 的启动过程

       根 Activity 指的是应用程序启动的第一个Activity,因此根 Activity 的启动过程一般情况下也可以理解为应用程序的启动过程。根Activity的启动过程比较复杂,这里我们分为三个部分来分析,分别是Launcher请求AMS过程、AMS到ApplicationThread的调用过程和ActivityThread启动Activity。

     1.1 Launcher 请求 AMS 过程

       Launcher启动后会将已安装应用程序的快捷图标显示到桌面上,这些应用程序的快捷图标就是启动跟Activity的入口,当我们点击某个应用程序的快捷图标时,就会动过Launcher请求AMS来启动该应用程序。      

       当我 们点 击应用程序 的快捷图标时,就会 调用 Launcher的 sta rtActivi tySafely方法 ,代码如 下所示:
 
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
       
         ...

        // Prepare intent
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // ... 1
        if (v != null) {
            intent.setSourceBounds(getViewBounds(v));
        }
        try {
            if (Utilities.ATLEAST_MARSHMALLOW
                    && (item instanceof ShortcutInfo)
                    && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
                     || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
                    && !((ShortcutInfo) item).isPromise()) {
                // Shortcuts need some special checks due to legacy reasons.
                startShortcutIntentSafely(intent, optsBundle, item);
            } else if (user == null || user.equals(Process.myUserHandle())) {
                // Could be launching some bookkeeping activity
                startActivity(intent, optsBundle); // ... 2
            } else {
                LauncherAppsCompat.getInstance(this).startActivityForProfile(
                        intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
            }
            return true;
        } catch (ActivityNotFoundException|SecurityException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
        }
        return false;
    }

       在注释1处将Flag设置为Intent.FLAG_ACTIVITY_NEW_TASK ,这样根 Activity会在新的任务栈中启动。在注释2处调用startActivity方法,这个startActivity方法Activity 中实现,代码如下所示:

frameworks/base/core/java/android/app/Activity.java

    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.

            /**
             * 如果options为空时,startActivityForResult(intent, -1)调用最终
             * 还是调用startActivityForResult(intent, -1,null);
             */
            startActivityForResult(intent, -1);
        }
    }

       在startActivity方法中会调用startActivityForResult方法,它的第二个参数为-1,表示Launcher不需要知道Activity启动的结果,startActivityForResult方法的代码如下所示:

 frameworks/base/core/java/android/app/Activity.java

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) { // ... 1
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options); // ... 2
            
            ....

        } else {
            
            ....

        }
    }
       注释1 处的 mParent是 Activity 类型的,表示当前 Activity 的父 类。 因为目前根 Activity 还没有创建出来, 因此, mParent == null 成 立。 接着 调用 Instrumentation的 execStartActivity 方法, Instrumentation 主 要用来监控应用程序和系统的交互, execStartActivity方法 的代码 如下所示:
 

frameworks/base/core/java/android/app/Instrumentation.java

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
      
        ...          

        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options); // ... 1
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
       在注释1处调用 Activity Manager的 getService 方法来获取 AMS 的代理对象 ,接着 调用它的 startActivity方法。下面 查看 Activity Manager的getService 方法做 什么,代码如下所示:
 
frameworks/base/core/java/android/app/ActivityManager .java
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

       在getService方法中调用了IActivityManagerSingleton的get方法,IActivityManagerSingleton的定义如下:

frameworks/base/core/java/android/app/ActivityManager.java

    private static final Singleton IActivityManagerSingleton =
            new Singleton() {
                @Override
                protected IActivityManager create() {
                    // Context.ACTIVITY_SERVICE = "activity"
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); // ... 1
                    final IActivityManager am = IActivityManager.Stub.asInterface(b); // ... 2
                    return am;
                }
   };
       IActivityManagerSingleton是一个 Singleton 类。 在 注释1处得到名 为“ activity ”的 Service 引用, 也就是I Binder 类型的 AMS 的引用 。接 着在注释2 处将它转换成I Activity Manager 类型的对象,这段代码采用的是 AIDL, IActivityManager.java 是由 AIDL 工具在编译时自动成的, IActivityManager.aidl 的文件路径为  frameworks/ base/ core/ java/android/app/IActivityManager.aidl。要实 现进程间通信,服务器 端也就是 AMS 只需要继承 IActi vityManager.Stub  并实 现相应 方法也 就可以了。 注意 Android 8.0 之前并没有采用 AIDL ,而是采用了类似 AIDL 的形 式,用 AMS 的代理对象 Activity Manager Proxy 来与 AMS 进行进程间通信, Android 8.0 去除了 Activity ManagerN ative 的内部类 ActivityManagerProxy, 代替它的是IActivity Manager ,它是 AMS 在本 地的代理 。回 到 Instrumentation 类的 execStartActivity 方法中,从上 面得知 execStartActi vi ty方法 终调用的是 AMS的startActivity 方法。
 

    1.2 AMS到ApplicationThread的调用过程

       Launcher 请求 AMS 代码逻辑已经 进入 AMS 中,接着是  AMS到 Application Thread 的调用流程,下面开始分析AMS的startActivity方法,代码如下所示:
 
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.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());
    }
       在AMS的 startActivity 方法中返回了 s tartActivityAsUser 方法, 可以发现 startActivity As User方法比 startActivity 方法多了一个 参数 UserHandle.getCallingU serld() , 这 个方法 会获得 调用 者的 Userld, AMS 根据这个 User Id 来确定 调用者 的权限。
 

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {

        // 判断调用者进程是否被隔离
        enforceNotIsolatedCaller("startActivity"); // ... 1
        
        // 检查调用者权限
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null); // ... 2
        // TODO: Switch to user app stacks here.
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
    }
       在注释1 处判断调用者进程是否被隔离,如果被隔离则抛出 Security Exception 异常, 在注释2 处检 查调用者是否有权限, 如果没有权限也会抛出 Security Exception 异常 。最后 调用了 ActivityStarter的startActivityMayWait方法, startActivityMayWait方法的 参数 要比 startActivity As User多 几个 ,需要注意 的是倒数第二个 参数类型 TaskRecord ,代表启动的 Activ ity 所 在的栈。最后一个参数" startAct ivityAsUs er"表示 启动的理由。 startActivityMayWait 方法 的代码如下所示:
 
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

    final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            TaskRecord inTask, String reason) {
       
            ... 

            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
                    reason);

            ...            

            return res;
        }
    }
       ActivityStarter的 startActivityMayWait 方法调 用了 startActivityLocked 方法 ,代码如下所示:
 

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


    int startActivityLocked(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,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, TaskRecord inTask, String reason) {

        // 判断启动的理由是否为空
        if (TextUtils.isEmpty(reason)) { // ... 1
            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); // ... 2

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

        // Aborted results are treated as successes externally, but we must track them internally.
        return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS;
    }
       在注释1处判断启动的理由是否为空,如果为空则抛出 IllegalArgumentException异常,在注释2处调用startActivity方法,代码如下所示:
 

frameworks/base/services/core/java/com/android/server/am/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,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, TaskRecord 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;

        ProcessRecord callerApp = null;
        if (caller != null) { // ... 1
            // 得到Launcher进程
            callerApp = mService.getRecordForAppLocked(caller); // ... 2
            if (callerApp != null) {
                // 获取Launcher进程的pid和uid
                callingPid = callerApp.pid;
                callingUid = callerApp.info.uid;
            } else {
                Slog.w(TAG, "Unable to find app for caller " + caller
                        + " (pid=" + callingPid + ") when starting: "
                        + intent.toString());
                err = ActivityManager.START_PERMISSION_DENIED;
            }
        }

        ...

       
        // 创建即将要启动的Activity的描述类ActivityRecord
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, options, sourceRecord);
        if (outActivity != null) {
            outActivity[0] = r; // ... 3
        }

        ...

        doPendingActivityLaunchesLocked(false);

        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
                options, inTask, outActivity); // ... 4
    }

       在注释1处判断 IApplicationThread 类型的 caller 是否为 null ,这个 caller 是方法调 用一 路传过来的,指向的是 Launcher 所在的应 用程序进程的 Application Thread 对象,在注释2 处调 AMS的getRecordF or AppLocked方法 得到的是代表 Launcher 进程的 caller App 对象,它是ProcessRecord 类型的, ProcessRecord 用于描述一 个应用程序进程。 同样地, Activity R eco rd 用于描述 一个Activity ,用来记录 Activity 的所有信息 。接 下来创建 Activity Record, 用于描述将要启动的 Activity ,并在注释3 处将创建的 Activity Record 赋值给 Activity Record[] 类型的 outActivity ,这个 outActivity 会作为注释4 处的 startActivity 方法的参数传递下去。startActivity 方法的代码如下所示:
 

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


    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
        int result = START_CANCELED;
        try {
            mService.mWindowManager.deferSurfaceLayout();
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity); // ... 1
        } finally {
            // If we are not able to proceed, disassociate the activity from the task. Leaving an
            // activity in an incomplete state can lead to issues, such as performing operations
            // without a window container.
            if (!ActivityManager.isStartResultSuccessful(result)
                    && mStartActivity.getTask() != null) {
                mStartActivity.getTask().removeActivity(mStartActivity);
            }
            mService.mWindowManager.continueSurfaceLayout();
        }

        postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId,  mSourceRecord,
                mTargetStack);

        return result;
    }

       在注释1处调用startActivityUnchecked方法,代码如下所示:

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


    // Note: This method should only be called from {@link startActivity}.
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {

        ...

        // Should this be considered a new task?
        int result = START_SUCCESS;
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { // ... 1
            newTask = true;

            // 创建新的TaskRecord
            result = setTaskFromReuseOrCreateNewTask(
                    taskToAffiliate, preferredLaunchStackId, topStack); // ... 2
        } else if (mSourceRecord != null) {
            result = setTaskFromSourceRecord();
        } else if (mInTask != null) {
            result = setTaskFromInTask();
        } else {
            // This not being started from an existing activity, and not part of a new task...
            // just put it in the top task, though these days this case should never happen.
            setTaskToCurrentTopOrCreateNewTask();
        }

        ...


        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && 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.
                mTargetStack.ensureActivitiesVisibleLocked(null, 0, !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.
                mWindowManager.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.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions); // ... 3
            }
        } else {
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }
        
        ...

        return START_SUCCESS;
    }
       startActi vi ty Unchecked 方法主 要处理与栈管理相关的逻辑   启动根 Activity 时会将 Intent 的 Flag 设置为 FLAG_ ACTIVITY_ NEW_ TASK ,这样注释1处的条件判断就会满足,接着执行注释2 处的 setTaskFromReuseOrCreateNewTask 方法 , 其内部会创建一个新的 TaskRecord ,用来描述 Activity 任务栈,也就是说 setTaskFromReuseOrCreateNewTask 方法内部会创建一 个新的 Activity 任务栈。   在注释3处会调用 ActivityStackSupervisor的 resumeFocusedStackTopActivityLocked 方法, 如下所 示:
 
frameworks/base/services/core/java/com/android/service/am/ActivityStackSupervisor.java

    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

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

        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }

        // 获取要启动的Activity所在栈的栈顶是不是处于停止状态的ActivityRecord
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked(); // ... 1
        if (r == null || r.state != RESUMED) { // ... 2
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null); // ... 3
        } else if (r.state == RESUMED) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }

        return false;
    }
       在注释1处调 ActivityStack的 topR unning Activ ityLocked 方法 获取要启动的 A ctivity 所在栈的栈顶是 不是 处于停止状态的 Activity Record 。在 注释2 处,如果 Ac ti vi ty Record不为 null ,或者要启动A ctivity 的状 态不是 RESUMED 状 态,就调 注释3 处的 Ac tivi tyStack的 resumeTopA ctivityUnch eckedLocked 方法 ,对于 即将 启动的 Act ivity ,注释2 处的条件判断是肯定满足的,我们来 查看 A ctivityStack的 resumeTopActivity UncheckedLocked 方法,如下所示:
 
frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options); // ... 1
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }

        // When resuming the top activity, it may be necessary to pause the top activity (for
        // example, returning to the lock screen. We suppress the normal pause logic in
        // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the end.
        // We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here to ensure
        // any necessary pause logic occurs. In the case where the Activity will be shown regardless
        // of the lock screen, the call to {@link ActivityStackSupervisor#checkReadyForSleepLocked}
        // is skipped.
        final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
        if (next == null || !next.canTurnScreenOn()) {
            checkReadyForSleep();
        }

        return result;
    }

       在注释1处调用了resumeTopActivityInnerLocked方法,代码如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java


    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
  
           ...

            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }

       resumeTopActivityInnerLocked 方法代码非常多,我们只需要关注调用了 ActivityStackSupervisor的startSpecificActivityLocked 方法即可,代码如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?

        // 获取即将启动的Activity的所在的应用程序进程
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true); // ... 1

        r.getStack().setLaunchTime(r);

        if (app != null && app.thread != null) { // ... 2
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, andResume, checkConfig); // ... 3
                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.
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
       在注释1 获取即将启动的 A ctivity 应用程序进程,在注释2处 判断要 启动 Activity 所在的应用程序进程如果已经运行的话,就会调用注释3 处的 realStartActi v i ty Locked 方法 ,这个方法的第二 参数是代 表要启 动的 Activity 应用程序进程 ProcessRecord。 realStartActi v i ty Locked代码如下所示:
 
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
 

    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {

            ...              

                app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                        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, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, !andResume,
                        mService.isNextTransitionForward(), profilerInfo);

        ...

        return true;
    }
       这里的 app.thread 指的是I Application Thread ,它的实现是 ActivityThread 的内部类 Application Thread ,其中 Application Thread 继承了I Application Thread. Stub。 app 指的是传入 的要启动的 Activity 所在的应用程序进程,因此,这段代码指的就是要在目标应用程序进 程启动 Activ ity 。当前代码逻辑运行在 AMS 所在的进程( SystemServer 进程)中,通过 ApplicationThread 来与应用程序进程进行 Binder 通信,换句话说, App lication Thread AMS 所在进程( SystemServer 进程)和应用程序进程的通信桥梁,如图所示:
解析Activity的启动过程_第1张图片
 

     1.3 ActivityThread 启动 Activity 的过程

       接着查看 Application Thread的 schedul LaunchActivity 方法,代码如下所示:
 
frameworks/base/core/java/android/app/ActivityThread.java
 

        // we use token to identify this activity without having to send the
        // activity itself back to the activity manager. (matters more with ipc)
        @Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List pendingResults, List pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }
       scheduleLaunchActivity 方法将启动 Activity 的参数封装成 ActivityClientRecord, sendMessage 方法向H 类发送 类型为 LAUN CH_ ACTIVITY 的消 息,并将A ctivity ClientRecord 传递过 去, sendMessage方法 多个重载方法  ,最终调用的 sendMessage 方法 如下所示:
 
frameworks/base/core/java/android/app/ActivityThread.java
    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }
       这里 mH 指的是 H ,它是 ActivityThread 的内部类 并继承 Handler ,是应用程序进程线程的消息管理 类。 因为 ApplicationTh read 是一个  Binder ,它的调用逻辑运行在 Binder 线程池中,所以这 里需要用H 将代码的逻辑切换到主 线程中。H 的代码如下所示:
 
frameworks/base/core/java/android/app/ActivityThread.java
    private class H extends Handler {
       
       ...

        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj; // ... 1

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo); // ... 2
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY"); // ... 3
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case RELAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                    handleRelaunchActivity(r);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
             
                ...               

            }
            Object obj = msg.obj;
            if (obj instanceof SomeArgs) {
                ((SomeArgs) obj).recycle();
            }
            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
        }
    }
       查看H的handleMessage 方法 中对 LAUNCH_ ACTIVITY 的处理,在注释1 处将传过来的 msg 的成员变量  obj 转换为 ActivityClientRecord 。 在注释2处通过 getPackagelnfoNoCheck 方法 获得 LoadedApk 类 型的对象 并赋值给 ActivityClientRecord 的成员变量 packagelnfo 。应 用程序进 程要启动  Activity 需要 将该 Activity 所属的 APK 加载进来,而 LoadedApk 就是用来描述己加载的 APK 文件的 。在注释3 处调用 handleLaunchActivity 方法,代码如下所示:
 
frameworks/base/core/java/android/app/ActivityThread.java

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        
        ...
  
        WindowManagerGlobal.initialize();

        // 启动Activity
        Activity a = performLaunchActivity(r, customIntent); // ... 1

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;

            // 将Activity的状态设置为resume
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

            if (!r.activity.mFinished && r.startsNotResumed) {
                // The activity manager actually wants this one to start out paused, because it
                // needs to be visible but isn't in the foreground. We accomplish this by going
                // through the normal startup (because activities expect to go through onResume()
                // the first time they run, before their window is displayed), and then pausing it.
                // However, in this case we do -not- need to do the full pause cycle (of freezing
                // and such) because the activity manager assumes it can just retain the current
                // state it has.
                performPauseActivityIfNeeded(r, reason);

                // We need to keep around the original state, in case we need to be created again.
                // But we only do this for pre-Honeycomb apps, which always save their state when
                // pausing, so we can not have them save their state when restarting from a paused
                // state. For HC and later, we want to (and can) let the state be saved as the
                // normal part of stopping the activity.
                if (r.isPreHoneycomb()) {
                    r.state = oldState;
                }
            }
        } else {
            // If there was an error, for any reason, tell the activity manager to stop us.
            try {
                // 停止启动Activity
                ActivityManager.getService()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }
注释1 处的 performLaunchActi vi ty 方法 用来 启动 Activity,  注释2 处的代码 用来将 Activity 的状态设 Resume ,如 果该 Activity 为 null 则会通知 AMS 停止启动 Activity 。 下面来 查看 performLaunchActi vi ty 方法 做了什么,代码如下所示:
 
frameworks/base/core/java/android/app/ActivityThread.java
 

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
        
        // 获取ActivityInfo类
        ActivityInfo aInfo = r.activityInfo; // ... 1
        if (r.packageInfo == null) {
            // 获取APK文件的描述类LoadApk
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE); // ... 2
        }

        ComponentName component = r.intent.getComponent(); // ...3
       
        ...

        // 创建需要启动Activity的上下文环境
        ContextImpl appContext = createBaseContextForActivity(r); // ... 4
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            // 用类加载器来创建改Activity的实例
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent); // ... 5
            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
            Application app = r.packageInfo.makeApplication(false, mInstrumentation); // ... 6

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

                // 初始化Activity    ... 7            
                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);

                
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); // ... 8
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
               
               ...

            }
            r.paused = true;

            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;
    }
       注释1 处用来获取 Activity Info ,用于存储代码以及  AndroidManifes设置的 Activity和Receiver 节点信息,比如 Activity的 theme和 laun chMode 。在注释2 处获取 APK 文件的描述类 LoadedApk 。在注释3处获 取要启动的 Activity的 ComponentName 类,在ComponentName 类中保存了 Activity 的包名和 类名。注释4 处用来创 建要启动 Activity的上下文环境。注释5 处根据 ComponentName 中存储的 Activity 类名, 用类加 载器来创建  Activity 的实例。注释6 处用来 创建 Application, makeApplication 方法内 部会 调用 Application的on Create 方法 。注释7 处调用 Activity的 attach 方法 始化 Activity, 在 attach 方法中会创建 Window对象( Phone Window )并与 Activity 自身进行关联  。在注释8 处调用 Instrumentation的callActivityOnCre ate 方法来 启动 Activity ,代码如下所示:
 
frameworks/base/core/java/android/app/Instrumentation.java
    public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState); // ... 1
        postPerformCreate(activity);
    }
    

        在注释1处调用了Activity的performCreate方法,代码如下所示:

 frameworks/base/core/java/android/app/Activity.java

    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        mCanEnterPictureInPicture = true;
        restoreHasCurrentPermissionRequest(icicle);
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
        mActivityTransitionState.readState(icicle);

        mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
                com.android.internal.R.styleable.Window_windowNoDisplay, false);
        mFragments.dispatchActivityCreated();
        mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
    }

       在performCreate方法中会调用Activity的onCreate方法,分析到这里,跟Activity就启动了,即应用程序就启动了。

     1.4 根Activity启动过程中涉及的进程

       根Activity 启动过程中会 涉及4 个进程,分别是 Zygote进程、  Launcher 进程、 AMS 所在进程( SystemServer 进程)、应用程序进程,它们的关系如下图所示:
 

解析Activity的启动过程_第2张图片

       首先 Launcher 进程向 AMS 请求创建根 Activity, AMS 会判断根 Activity 所需的应用程序进程是否存在并启动,如果不存在就会请求 Zygote 进程创建应用程序进程, 应用程序进程启动后, AMS 会请求应用程序进程启动根 Activity 。上图 中步骤2 采用的是 Socket 通信,步骤1 和步骤4 采用的是 Binder 通信。

 

     2 普通Activity启动过程

       普通Activity启动过程与根Activity的启动有很多重复的过程,普通Activity启动过程中会涉及两个进程,分别是AMS所在的进程和应用程序进程,实际上理解了根 Activity 的启动过程(根 Activity的onCreate 过程),根 Activity 和普通 Activity 其他生命周期状态(比如 onStart 、onResume 等)过程也会很轻松掌握,感兴趣的同学可以阅读源码继续分析,这里就不做具体分析了。

你可能感兴趣的:(根Activity启动过程,Activity启动过程,android,安卓)