Android 源碼解析之 應用(Activity)啓動流程

我們在Android手機桌面上點擊不同的圖標,就可以進入到不用的應用中,非常方便。那麼,應用順利啓動背後的流程,你知道多少呢?

這種情況下,Android 應用的啓動流程大致可以認爲就是 Activity 的啓動過程。本文基於 Android 7.0 (API 24)源碼進行分析,各個版本的源碼略有差異,但這塊內容的總體思路和框架都是不變的。

1、Launcher啓動應用

我們知道,Android 應用是一般由 Launcher(即通常說的桌面)負責啓動的。關於 Launcher 的源碼分析,可以看我的系列文章 [傳送門]。其中用於啓動每個應用的 Intent 信息是存儲在每個桌面圖標 view 綁定的 tag 中的。拿到啓動所需信息後,交由 Activity 的 startActivity 去完成啓動過程。

public class Launcher extends Activity
        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
                   View.OnTouchListener, PageSwitchListener, LauncherProviderChangeListener,
                    MTKUnreadLoader.UnreadCallbacks {
    ......

    private boolean startActivity(View v, Intent intent, Object tag) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        ......
        startActivity(intent, optsBundle);
    }
}

2、Activity.startActivity

源碼位置:frameworks/base/core/java/android/app/Activity.java

Google原生桌面 Launcher.java 繼承自 Activity,進入父類的方法。由 startActivity 又調用了 startActivityForResult 方法,傳入 -1 表示不需要Activity結束後的返回結果。

22 行的 mInstrumentation 是 Activity 類的成員對象,類型是 Intrumentation。當需要創建或暫停某個 Activity 時,都需要通過 Instrumentation 來進行具體的操作。後面的源碼分析,會經常看到 Intrumentation 的身影。

26 行的 mMainThread 也是 Activity 類的成員對象,類型是 ActivityThread,它代表的是應用程序的主線程。這裏通過 mMainThread.getApplicationThread 獲得到 ApplicationThread 實例,它是一個 Binder 接口,後面我們會看到 ActivityManagerService 會使用它來和 ActivityThread 來進行進程間通信。

需注意的是,這裏的 mInstrumentation 和 mMainThread 對象都還是 Launcher 所在應用進程裏的對象。調用 Intrumentation 的 execStartActivity 方法進行下一步操作。

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback {
    ......
    
    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.
            startActivityForResult(intent, -1);
        }
    }

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            ......
        } else {
            ......
        }
    }
    ......
}

3、 Instrumentation.execStartActivity

源碼位置:frameworks/base/core/java/android/app/Instrumentation.java

15 行的 ActivityManagerNative.getDefault 返回了與 ActivityManagerService 跨進程通信的接口—— IActivityManager,具體實現類是 ActivityManagerProxy。通過該接口的 startActivity 函數,通知 AMS,我要啓動一個新的 Activity 啦!

在 startActivity 傳入的參數中,intent.resolveTypeIfNeeded 返回這個 inten t的 MIME 類型,很多應用並沒有配置這個參數,因此,本文返回 null。這裏的 target 不爲 null,但是target.mEmbddedID 爲 null,所以這些參數我們不用關注。

調用 ActivityManagerProxy 的 startActivity 方法進行下一步操作。

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
            ......
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

4、ActivityManagerProxy.startActivity

ActivityManagerProxy 是 frameworks/base/core/java/android/app/ActivityManagerNative.java 的內部類。

這裏的參數比較多,我們先整理一下。從上面的調用可以知道,這裏的參數 resolvedType 和resultWho 均爲 null;參數 caller 爲 ApplicationThread 類型的 Binder 接口;參數 resultTo 爲一個 Binder 的遠程接口,我們先不關注它;參數 startFlags 爲 0,我們也先不關注它;參數 requestCode 爲 -1;profilerInfo 的值爲 null。

通過 Binder 接口我們就直接跨進程進入到 ActivityManagerService 的 startActivity 函數去了。

    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

5、ActivityManagerService.startActivity

源碼位置:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

在 18 行中調用了成員對象 mActivityStarter 的 startActivityMayWait 方法。

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

    @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");
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        // 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, null);
    }

6、ActivityStarter.startActivityMayWait

源碼位置:
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

參數中 outResult 和 config 均爲 null,且表達式 (aInfo.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT
_SAVE_STATE) != 0) 爲 false,所以忽略一些無關代碼。

代碼挺長,但要關注的地方主要就幾處:
1、解析 Intent 獲取 ResolveInfo 對象賦值給 rInfo。詳見6.1;
2、調用 startActivityLocked 進行下一步操作,詳見6.2。

    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, IActivityManager.WaitResult outResult, Configuration config,
            Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {

        boolean componentSpecified = intent.getComponent() != null;

        // Save a copy in case ephemeral needs it
        final Intent ephemeralIntent = new Intent(intent);
        // Don't modify the client's object!
        intent = new Intent(intent);

        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
        if (rInfo == null) {
            ......
        }
        // Collect information about the target of the Intent.
        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

        ActivityOptions options = ActivityOptions.fromBundle(bOptions);
        ActivityStackSupervisor.ActivityContainer container =
                (ActivityStackSupervisor.ActivityContainer)iContainer;
        synchronized (mService) {
            if (container != null && container.mParentActivity != null &&
                    container.mParentActivity.state != RESUMED) {
                // Cannot start a child activity if the parent is not resumed.
                return ActivityManager.START_CANCELED;
            }
            final int realCallingPid = Binder.getCallingPid();
            final int realCallingUid = Binder.getCallingUid();
            int callingPid;
            if (callingUid >= 0) {
                callingPid = -1;
            } else if (caller == null) {
                callingPid = realCallingPid;
                callingUid = realCallingUid;
            } else {
                callingPid = callingUid = -1;
            }

            final ActivityStack stack;
            if (container == null || container.mStack.isOnHomeDisplay()) {
                stack = mSupervisor.mFocusedStack;
            } else {
                stack = container.mStack;
            }
            stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
            final long origId = Binder.clearCallingIdentity();

            if (aInfo != null &&
                    (aInfo.applicationInfo.privateFlags
                            & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
                ......
            }

            final ActivityRecord[] outRecord = new ActivityRecord[1];
            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                    inTask);

            ......

            final ActivityRecord launchedActivity = mReusedActivity != null
                    ? mReusedActivity : outRecord[0];
            mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
            return res;
        }
    }

6.1 ActivityStackSupervisor.resolveIntent(解析Intent)

以上 16 行,AppGlobals.getPackageManager() 返回一個Binder接口 —— IPackageManager,通過該接口,調用到了 PackageManagerService 中的 resolveIntent 方法。

該方法主要做了一件事情,就是通過啓動 Activity 時傳入的 Intent ,拿到目標 Activity 的 ComponentName(即包名和類名)。然後 PMS 通過 ComponentName 生成其對應的 ActivityInfo 對象,該對象中包含了將要啓動的 Activity 在 AndroidManifest.xml 配置的屬性信息(如啓動模式等)。

    ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId) {
        return resolveIntent(intent, resolvedType, userId, 0);
    }

    ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) {
        try {
            return AppGlobals.getPackageManager().resolveIntent(intent, resolvedType,
                    PackageManager.MATCH_DEFAULT_ONLY | flags
                    | ActivityManagerService.STOCK_PM_FLAGS, userId);
        } catch (RemoteException e) {
        }
        return null;
    }

6.2 調用 startActivityLocked

以上 60 行,主要就是把一大堆的變量作爲參數傳入到 startActivityLocked 中進行下一步處理。

7、ActivityStarter.startActivityLocked

又是一個幾百行代碼的方法,看的我頭皮發麻,把跟本章內容無關的內容就先省略了。

首先,從傳進來的參數 caller 得到調用者(本文是 Launcher 應用程序)的進程信息,並保存在 ProcessRecord 類型的 callerApp 對象中。前面說過,參數 resultTo 是 Launcher 這個 Activity 裏面的一個 Binder 對象,通過它可以獲得 Launcher 這個 Activity 的相關信息,保存在 ActivityRecord 類型的 sourceRecord 變量中。

從 45 行開始,是一系列的異常處理,如果傳入的參數有問題,將會中斷Activity的啓動,然後直接退出。然後是權限檢查,如果權限檢查未通過,同樣直接退出,這裏就不詳細說了。

92 行是重要的一步,新建了一個 ActivityRecord 對象,該對象記錄了 Acitivty 的相關信息。

接着,把剛剛創建的 ActivityRecord 對象作爲參數,調用 startActivityUnchecked 方法。

    final 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, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask) {
        int err = ActivityManager.START_SUCCESS;

        ProcessRecord callerApp = null;
        if (caller != null) {
            callerApp = mService.getRecordForAppLocked(caller);
            if (callerApp != null) {
                callingPid = callerApp.pid;
                callingUid = callerApp.info.uid;
            } else {
                err = ActivityManager.START_PERMISSION_DENIED;
            }
        }

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

        ActivityRecord sourceRecord = null;
        ActivityRecord resultRecord = null;
        if (resultTo != null) {
            sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
            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) {
              ......
        }

        //一系列異常判斷
        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
            err = ActivityManager.START_INTENT_NOT_RESOLVED;
        }

        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
            err = ActivityManager.START_CLASS_NOT_FOUND;
        }

        if (err == ActivityManager.START_SUCCESS && sourceRecord != null
            ......
        }

        if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
            ......
        }

        final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;

        //異常處理
        if (err != START_SUCCESS) {
            if (resultRecord != null) {
                resultStack.sendActivityResultLocked(
                        -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
            }
            ActivityOptions.abort(options);
            return err;
        }
        ......
        
        //權限檢查
        // 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.
        /// M: CTA requirement - permission control
        if (Build.isPermissionReviewRequired() && aInfo != null) {
            if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                    aInfo.packageName, userId)) {
                ......
            }
        }

        // If we have an ephemeral app, abort the process of launching the resolved intent.
        // Instead, launch the ephemeral installer. Once the installer is finished, it
        // starts either the intent we resolved here [on install error] or the ephemeral
        // app [on install success].
        if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
            // Create a pending intent to start the intent resolved here.
            ......
        }

        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
                options, sourceRecord);
        if (outActivity != null) {
            outActivity[0] = r;
        }
        ......
        
        try {
            mService.mWindowManager.deferSurfaceLayout();
            err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                    true, options, inTask);
        } finally {
            mService.mWindowManager.continueSurfaceLayout();
        }
        postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
        return err;
    }

8、ActivityStarter.startActivityUnchecked

該方法主要做了以下操作:

1、第 5 行,首先初始化一些狀態值,保存在對應的成員對象中。詳見 8.1。

然後 getReusableIntentActivity 方法查找是否有可以重用的 Activity。這裏就跟啓動模式相關了。如果啓動模式不是默認的 standard,那麼就可能會有可複用的 ActivityRecord 實例。本文探討應用第一次啓動的流程,所以沒有可重用的實例對象,返回 null。

2、第 27 行,新建 TaskRecord 和 ActivityStack ,對啓動的Activity進行管理。詳見8.2。

3、第 49 行,然後調用到 ActivityStack.startActivityLocked,完成 Activity 啓動前的一些操作。詳見8.3。

4、第 62 行,通過 resumeFocusedStackTopActivityLocked 繼續往下執行。詳見8.4

    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {

        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor);
        computeLaunchingTaskFlags();
        computeSourceStack();
        mIntent.setFlags(mLaunchFlags);
        
        mReusedActivity = getReusableIntentActivity();
        if (mReusedActivity != null) {
            ......
        }

        final ActivityStack topStack = mSupervisor.mFocusedStack;
        ......

        boolean newTask = false;
        final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                ? mSourceRecord.task : null;

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

            if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
                mSupervisor.showLockTaskToast();

                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }
            if (!mMovedOtherTask) {
                updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
            }
        } else if (mSourceRecord != null) {
            ......
        } else if (mInTask != null) {
            ......
        } else {
            ......
        }
        
        mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
                mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
        
        mTargetStack.mLastPausedActivity = null;
        mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
        
        if (mDoResume) {
            if (!mLaunchTaskBehind) {
                mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
            }

            final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                ......
            } else {
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else {
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }
        ......
        
        return START_SUCCESS;
    }

8.1 ActivityStarter.setInitialState(Activity狀態初始化)

setInitialState 方法做了一些狀態的初始化工作。將之前創建的 ActivityRecord 對象傳遞給成員對象 mStartActivity 並保存起來,後面會用到。

然後將一些啓動相關的 flag 信息保存到成員變量 mLaunchFlags 中。其中,Activity 的啓動模式就是在這裏初始化的。我們知道,Activity 一共有四種啓動模式,在源碼中有三個 boolean 值:mLaunchSingleTop,mLaunchSingleTask 和 mLaunchSingleInstance。如果這幾個值都爲 false,那麼當前的 Activity 就是默認的啓動模式 standard。因爲應用初始啓動時,Activity 肯定是新建的,所以本文不探討啓動模式的設計和實現。

    private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
            boolean doResume, int startFlags, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
        reset();

        mStartActivity = r;
        mIntent = r.intent;
        mOptions = options;
        mCallingUid = r.launchedFromUid;
        mSourceRecord = sourceRecord;
        mVoiceSession = voiceSession;
        mVoiceInteractor = voiceInteractor;

        mLaunchBounds = getOverrideBounds(r, options, inTask);

        mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
        mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
        mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
        mLaunchFlags = adjustLaunchFlagsToDocumentMode(
                r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
        mLaunchTaskBehind = r.mLaunchTaskBehind
                && !mLaunchSingleTask && !mLaunchSingleInstance
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;

        sendNewTaskResultRequestIfNeeded();
        
        ......
    }

8.2 ActivityStarter.setTaskFromReuseOrCreateNewTask(新建Task和Stack)

這裏涉及到 TaskRecord 和 ActivityStack 的概念:

TaskRecord 是記錄 ActivityRecord 的棧,一個 TaskRecord 用鏈表存有若干 ActivityRecord,已後進先出的棧的形式進行管理。AMS 用 TaskRecord 確保 Activity 啓動和退出的順序。 一般默認情況下,一個應用默認只有一個 TaskRecord,屬性 taskAffinity 默認爲應用的包名。
ActivityStack 是管理這些 TaskRecord 的,它內部以鏈表的形式存有歷史啓動的 TaskRecord。

startActivity 時,如果沒有添加 FLAG_ACTIVITY_NEW_TASK 的標誌位,默認使用當前的 Task 來啓動 Activity。本文在啓動應用時是加了這個標記位的,那就需要新建 Task 來啓動 Activity。變量 newTask 置爲 true, 通過 setTaskFromReuseOrCreateNewTask 方法新建 TaskRecord 和 ActivityStack 。

step 1: 首先,通過 computeStackFocus 方法獲取到 ActivityStack 對象,賦給成員對象 mTargetStack 。
step 2: 本文的情況沒有可複用的 Task,所以 mReuseTask 爲 null。通過 createTaskRecord 方法創建 TaskRecord 對象。
step 3: 最後,通過 setTask 函數把 Task 和 Activity 進行關聯。

    private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
        mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
                mOptions);

        if (mReuseTask == null) {
            final TaskRecord task = mTargetStack.createTaskRecord(
                    mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                    mNewTaskIntent != null ? mNewTaskIntent : mIntent,
                    mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
            mStartActivity.setTask(task, taskToAffiliate);
            if (mLaunchBounds != null) {
                final int stackId = mTargetStack.mStackId;
                if (StackId.resizeStackWithLaunchBounds(stackId)) {
                    mService.resizeStack(
                            stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
                } else {
                    mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
                }
            }
        } else {
            ......
        }
    }

8.3 ActivityStack.startActivityLocked

源碼地址:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

根據上面可知,傳入的參數 newTask 爲 true,所以無關代碼本文忽略了。

首先,取出傳入參數包含的 task 和 taskId。通過 insertTaskAtTop() 方法,把之前新建的 TaskRecord 對象保存到 ActivityStack 的成員對象 mTaskHistory 中。再通過 WindowManagerService,根據 taskId 把當前的創建的 Task 放到系統任務棧的棧頂。

然後通過 addActivityToTop() 方法把 Activity 對應的 ActivityRecord 對象插入 TaskRecord 對象的內部鏈表 mActivities 的尾部。

最後,在 Activity 啓動完成之前,通過 showStartingWindow() 方法顯示啓動中的預覽窗口。系統在加載 Activity 佈局時,會先顯示 window 的背景。這就是爲什麼我們在啓動 Activity 時會先顯示一下白屏或者黑屏(跟主題有關)的原因,在 Activity 佈局加載完畢後再顯示內容。所以這個黑白屏其實就是 window 的背景。

    final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
            ActivityOptions options) {
        TaskRecord rTask = r.task;
        final int taskId = rTask.taskId;
        if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
            // Last activity in task had been removed or ActivityManagerService is reusing task.
            // Insert or replace.
            // Might not even be in.
            insertTaskAtTop(rTask, r);
            mWindowManager.moveTaskToTop(taskId);
        }
        TaskRecord task = null;
        if (!newTask) {
            ......
        }

        ......

        task = r.task;

        task.addActivityToTop(r);
        task.setFrontOfTask();

        r.putInHistory();
        if (!isHomeStack() || numActivities() > 0) {
            // We want to show the starting preview window if we are
            // switching to a new task, or the next activity's process is
            // not currently running.
            boolean showStartingIcon = newTask;
            ProcessRecord proc = r.app;
            if (proc == null) {
                proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
            }
            if (proc == null || proc.thread == null) {
                showStartingIcon = true;
            }

            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                ......
            } else {
                mWindowManager.prepareAppTransition(newTask
                        ? r.mLaunchTaskBehind
                                ? TRANSIT_TASK_OPEN_BEHIND
                                : TRANSIT_TASK_OPEN
                        : TRANSIT_ACTIVITY_OPEN, keepCurTransition);
                mNoAnimActivities.remove(r);
            }
            addConfigOverride(r, task);
            boolean doShow = true;
            if (newTask) {
                if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                    resetTaskIfNeededLocked(r, r);
                    doShow = topRunningNonDelayedActivityLocked(null) == r;
                }
            } else if (options != null && options.getAnimationType()
                    == ActivityOptions.ANIM_SCENE_TRANSITION) {
                ......
            }
            if (r.mLaunchTaskBehind) {
                ......
            } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
                ActivityRecord prev = r.task.topRunningActivityWithStartingWindowLocked();
                if (prev != null) {
                    ......
                }
                r.showStartingWindow(prev, showStartingIcon);
            }
        } else {
            ......
        }
    }

8.4 ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

這裏只是一個參數的傳遞,又回到 ActivityStack 對象的 resumeTopActivityUncheckedLocked 方法中。

    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        ......
    }

9、ActivityStack.resumeTopActivityUncheckedLocked

這裏主要也是參數的傳遞,調用 resumeTopActivityInnerLocked() 方法。

    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;
            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
                mService.updateSleepIfNeededLocked();
            }
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }

10、ActivityStack.resumeTopActivityInnerLocked

函數先通過調用 topRunningActivityLocked 函數獲得棧頂的 Activity,該 Activity 信息就是在上面的第8節裏設置進去的。本文中獲取到的就是我們將要啓動的 Activity 了,然後保存到 next 變量中。

我們忽略掉幾百行代碼,直接來到最後,因爲第一次啓動,next.app 爲 null。所以調用 ActivityStackSupervisor 的 startSpecificActivityLocked 方法。這裏把剛剛獲取的棧頂 Activity 作爲參數傳入。

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

        mStackSupervisor.cancelInitializingActivities();

        // Find the first activity that is not finishing.
        final ActivityRecord next = topRunningActivityLocked();

        // Remember how we'll process this pause/resume situation, and ensure
        // that the state is reset however we wind up proceeding.
        final boolean userLeaving = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;

        final TaskRecord prevTask = prev != null ? prev.task : null;
        if (next == null) {
            ......
        }
        ......
        
        ActivityStack lastStack = mStackSupervisor.getLastStack();
        if (next.app != null && next.app.thread != null) {
            ......
        } else {
            // Whoops, need to restart this activity!
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else {
                if (SHOW_APP_STARTING_PREVIEW) {
                    next.showStartingWindow(null, true);
                }
            }
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

        return true;
    }

11、ActivityStackSupervisor.startSpecificActivityLocked

首先,根據進程名(其實就是應用的包名)和 uid,從 AMS 中查找是否有緩存的 ProcessRecord 實例對象。

如果應用已經啓動過,那麼可以獲取到緩存的 ProcessRecord 實例,直接調用 realStartActivityLocked 即可;

但是本文探討的是應用第一次啓動的過程,所以 getProcessRecordLocked 將會返回 null。那麼需要先調用 AMS 的 startProcessLocked 創建相應的實例對象。

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);

        if (app != null && app.thread != null) {
            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);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

12、ActivityManagerService.startProcessLocked

startProcessLocked 重寫了幾個入參個數不一樣的方法。總的來說,主要做了兩件事情:

1、創建 ProcessRecord 實例對象並返回。看到 18 行,前面 isolated 傳入的 false,所以先通過 getProcessRecordLocked 獲取緩存對象,如果返回 null,再通過 32 行的 newProcessRecordLocked 方法新建一個 ProcessRecord 實例對象,同時將該對象加入緩存,留待下次直接取用;

2、創建了應用的主線程 —— ActivityThread 。ActivityThread 就是我們所說的主線程或者UI線程,一個應用不管有多少 Activity,都只有一個 ActivityThread 實例。
看到 94 行, Process.start 方法中通過調用 ActivityThread.main 方法完成創建。創建完成後,通過 Binder 接口(IActivityManager)調用 AMS 的 attachApplication 方法,把 ActivityThread 端的 Binder 接口實現類(ApplicationThread)作爲參數傳遞給 AMS。AMS 就可以通過這個 Binder 接口,實現與 ActivityThread 通信了。

在 AMS 中,通過 attachApplication —> attachApplicationLocked —> ActivityStackSupervisor.attachApplicationLocked 的調用順序,最終還是回到了之前所說的 realStartActivityLocked 方法。

    final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }


    final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
            boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
        long startTime = SystemClock.elapsedRealtime();
        ProcessRecord app;
        if (!isolated) {
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
            checkTime(startTime, "startProcess: after getProcessRecord");

            ......
        } else {
            // If this is an isolated process, it can't re-use an existing process.
            app = null;
        }

        ......

        if (app == null) {
            checkTime(startTime, "startProcess: creating new process record");
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
            if (app == null) {
                Slog.w(TAG, "Failed making new process record for "
                        + processName + "/" + info.uid + " isolated=" + isolated);
                return null;
            }
            app.crashHandler = crashHandler;
            checkTime(startTime, "startProcess: done creating new process record");
        } else {
            // If this is a new package in the process, add the package to the list
            app.addPackage(info.packageName, info.versionCode, mProcessStats);
            checkTime(startTime, "startProcess: added package to existing proc");
        }

        ......

        checkTime(startTime, "startProcess: stepping in to startProcess");
        startProcessLocked(
                app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
        checkTime(startTime, "startProcess: done starting proc!");
        return (app.pid != 0) ? app : null;
    }


    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        long startTime = SystemClock.elapsedRealtime();
        if (app.pid > 0 && app.pid != MY_PID) {
            checkTime(startTime, "startProcess: removing from pids map");
            synchronized (mPidsSelfLocked) {
                mPidsSelfLocked.remove(app.pid);
                mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
            }
            checkTime(startTime, "startProcess: done removing from pids map");
            app.setPid(0);
        }

        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
                "startProcessLocked removing on hold: " + app);
        mProcessesOnHold.remove(app);

        checkTime(startTime, "startProcess: starting to update cpu stats");
        updateCpuStats();
        checkTime(startTime, "startProcess: done updating cpu stats");

        try {
            try {
                final int userId = UserHandle.getUserId(app.uid);
                AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }

            ......

            // Start the process.  It will either succeed and return a result containing
            // the PID of the new process, or else throw a RuntimeException.
            boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
            
            ......
        } catch (RuntimeException e) {
            Slog.e(TAG, "Failure starting process " + app.processName, e);
            ......
        }
    }

13、ActivityStackSupervisor.realStartActivityLocked

看到這個方法的命名,是不是留下了激動的淚水?文章分析了大半篇,好像要真正開始啓動 Activity 了。

看到 61 行的 scheduleLaunchActivity 方法,調用它的 app.thread 的類型是 IApplicationThread。它繼承了 IInterface 接口,是一個 Binder 接口。那麼它的實現類是什麼呢?答案就是 ActivityThread 中的內部類 ApplicationThread。

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

        ......

        final ActivityStack stack = task.stack;
        try {
            if (app.thread == null) {
                throw new RemoteException();
            }
            List<ResultInfo> results = null;
            List<ReferrerIntent> newIntents = null;
            if (andResume) {
                results = r.results;
                newIntents = r.newIntents;
            }

            if (r.isHomeActivity()) {
                // Home process is the root process of the task.
                mService.mHomeProcess = task.mActivities.get(0).app;
            }
            mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
                                      PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
            r.sleeping = false;
            r.forceNewConfig = false;
            mService.showUnsupportedZoomDialogIfNeededLocked(r);
            mService.showAskCompatModeDialogLocked(r);
            r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
            ProfilerInfo profilerInfo = null;
            if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
                if (mService.mProfileProc == null || mService.mProfileProc == app) {
                    mService.mProfileProc = app;
                    final String profileFile = mService.mProfileFile;
                    if (profileFile != null) {
                        ParcelFileDescriptor profileFd = mService.mProfileFd;
                        if (profileFd != null) {
                            try {
                                profileFd = profileFd.dup();
                            } catch (IOException e) {
                                if (profileFd != null) {
                                    try {
                                        profileFd.close();
                                    } catch (IOException o) {
                                    }
                                    profileFd = null;
                                }
                            }
                        }

                        profilerInfo = new ProfilerInfo(profileFile, profileFd,
                                mService.mSamplingInterval, mService.mAutoStopProfiler);
                    }
                }
            }

            if (andResume) {
                app.hasShownUi = true;
                app.pendingUiClean = true;
            }
            app.forceProcessStateUpTo(mService.mTopProcessState);
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

            if ((app.info.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
                // This may be a heavy-weight process!  Note that the package
                // manager will ensure that only activity can run in the main
                // process of the .apk, which is the only thing that will be
                // considered heavy-weight.
                if (app.processName.equals(app.info.packageName)) {
                    mService.mHeavyWeightProcess = app;
                    Message msg = mService.mHandler.obtainMessage(
                            ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
                    msg.obj = r;
                    mService.mHandler.sendMessage(msg);
                }
            }

        } catch (RemoteException e) {
            ,,,,,,
            throw e;
        }

        ......
        return true;
    }

14、ApplicationThread.scheduleLaunchActivity

這裏就是發送一個啓動 Activity 的消息交由 Handler 去處理。

        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<ResultInfo> pendingResults, List<ReferrerIntent> 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);
        }
        

15、Handler消息處理

剛剛發送的消息類型爲 LAUNCH_ACTIVITY,那麼就來到了 handleLaunchActivity 方法。

    private class H extends Handler {

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    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;
                ......
            }
        }
    }

16、ActivityThread.handleLaunchActivity

終於看到了熟悉的類 —— Activity ,由此可見,performLaunchActivity 最終完成了 Activity 對象的創建和啓動過程,然後通過 handleResumeActivity 方法回調 Activity 生命週期中的 onResume 方法。

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

        // Initialize before creating the activity
        WindowManagerGlobal.initialize();

        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            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 {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

17、ActivityThread.performLaunchActivity

其中,performLaunchActivity 方法主要完成了如下幾項工作:
1、3~19 行,獲取待啓動的 Activity 的組件信息;
2、24 行完成了 Activity 實例的創建;
3、41 行完成了 Application 實例的創建;
4、57 行通過 attach 方法完成了 Activity 對象內部一些重要成員對象的賦值;
5、76 行調用 Instrumentation 的 callActivityOnCreate,通知 Activity 已經創建完成,可以回調生命週期了。

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

        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            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 (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) {
                    config.updateFrom(r.overrideConfig);
                }

                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }
                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);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                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 {
                    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;
    }

17.1 Instrumentation.newActivity(通過類加載器新建 Activity 對象)

將需要啓動的 Activity 的類名,傳入 Instrumentation 對象的 newActivity 方法,通過 類加載器完成了對象的創建。

    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }

17.2 LoadedApk.makeApplication(創建 Application 對象)

該方法內部主要做了三項工作:
1、24 行創建了 Application 級別的 Context(單例對象裏經常需要這個上下文對象);
1、25 行通過類加載器的方式完成 Application 對象的創建;
3、通過 Instrumentation 回調了 Application 的 onCreate 方法。

    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

        Application app = null;

        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        "initializeJavaContextClassLoader");
                initializeJavaContextClassLoader();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + ": " + e.toString(), e);
            }
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;

        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!instrumentation.onException(app, e)) {
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
        }

        ......

        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        return app;
    }

17.3 Activity.attach(通過 Activity 的 attach 方法完成一些重要成員對象的初始化)

首先,創建了 Activity 級別的 Context 對象;

接着調用了 Activity 中的 attach 方法,主要完成兩項工作:
1、通過 attach 方法傳入的參數,賦值給了 Activity 對象內部的成員對象,完成了 ActivityThread、ActivityInfo 等重要成員對象的初始化;
2、創建了 Window 對象並與其建立關聯,這樣觸摸事件就可以從 Window 向 Activity 進行傳遞。

    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();

        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }

        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
    }

17.4 Instrumentation.callActivityOnCreate

通過 Instrumentation 的 callActivityOnCreate 方法,通知 Activity 準備工作已經完畢,可以進行生命週期的回調了。

    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }

18、Activity.performCreate (完成 onCreate 的回調)

看到第 3 行,原來我們熟悉的 onCreate 方法是在這裏被調用的。

    final void performCreate(Bundle icicle) {
        restoreHasCurrentPermissionRequest(icicle);
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

19、總結

從我們經常使用的 startActivity 方法,到完成目標 Activity 的 onCreate 方法的回調,原來中間經歷了這麼多波折。篇幅有點長,是不是有點被繞暈了,下面來總結一波。

二話不說,先上一張流程圖(畫的有點醜,將就一下)。
調用流程圖

18.1 應用啓動的主要步驟

結合上面的流程圖,可以總結出大致的流程:

1、Launcher 通過 Binder 進程間通信機制通知 ActivityManagerService,我要啓動一個 Activity 啦;

2、然後 ActivityManagerService 通過內部持有的 ActivityStarter 類型的對象,完成了目標 Activity 啓動前的一些準備工作(如上文所說的解析Intent、權限檢查,Activity啓動順序管理等);

3、準備工作完成後,通過包名判斷當前的應用是否啓動過,如果未啓動過,則需要執行第4步操作新建一個應用主線程 ActivityThread ;如果曾經啓動過,那麼 ActivityThread 已經創建了,直接跳過第4步即可;

4、創建完成後,ActivityThread 通過 Binder 接口通知 ActivityManagerService ,並將 ApplicationThread (用於和 ActivityThread 通信的 Binder 接口實現類)對象傳遞給 ActivityManagerService 。ActivityManagerService 通過這個Binder 接口,完成了一些綁定操作;

5、綁定完成後,再通過這個 Binder 接口跨進程通知 ActivityThread 。接着 ActivityThread 就開始 Application 和 Activity 這兩個重要實例對象的創建和初始化工作;

6、創建完畢後,即可回調 Activity 的生命週期方法 onCreate,告訴開發者,可以加載佈局了。

18.2 啓動過程中涉及到的重要類和對象

1、ActivityManagerService:負責系統中所有 Activity 的生命週期。Activity 的創建和銷燬都需要通過 AMS 來完成;其實當應用 Crash 或者 ANR 時,也是通過 AMS 去捕獲異常,並彈出 Diaog 來提示用戶的。

2、ActivityThread:當應用啓動之後,會調用 main() 開始運行,開啓消息循環隊列,這就是傳說中的UI線程或者叫主線程。ActivityManagerService 就是通過 ActivityThread,實現對 Activity 的管理;

3、ApplicationThread:本質上是一個 Binder 接口,用於 ActivityManagerService 與 ActivityThread 之間的通信。

4、Instrumentation:從上面的流程圖可以發現,Activity 都是通過 Instrumentation 對象與外界進行交互的。每個 Activity 內都有一個對該對象的引用,可以把 Instrumentation 理解爲應用進程的忠實幹將。ActivityThread 要創建或暫停某個 Activity 時,都需要通過 Instrumentation 來進行具體
的操作。

5、ActivityRecord:每一個啓動的 Activity 都對應着一個 ActivityRecord,存儲了該 Activity 相關的所有信息。

6、TaskRecord:是記錄對應應用的所有 Activity 啓動順序的類,其通過鏈表的形式保存 ActivityRecord 來實現管理的目的。

7、ActivityStack:管理所有的 TaskRecord。Activity 在 AMS 的棧管理,用來記錄未被銷燬的 Activity 的先後順序,狀態信息等。通過 ActivityStack 決定是否需要啓動新的進程。


文章有點長,能看到最後,說明你穩的一匹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章