天天看點

Android framework 源碼分析一Activity啟動流程(android 8.0)概述Activity的啟動流程總結:

Android framework 源碼分析之Activity啟動流程android 8.0

  • 概述
  • Activity的啟動流程
    • 一、從Activity的入口到ActivityManagerService的啟動過程
    • 二、在ActivityManagerService中的啟動過程
    • 三、ActivityStarter、ActivityStackSupervisor、ActivityStack中的啟動流程
    • 四、Activity的在ApplicationThread中的啟動過程
  • 總結:

首先附上我的幾篇其它文章連結感興趣的可以看看,如果文章有異議的地方歡迎指出,共同進步,順便點贊謝謝!!!

Android studio編寫第一個NDK工程的過程詳解(附Demo下載下傳位址)

面試必備1:HashMap(JDK1.8)原理以及源碼分析

面試必備2:JDK1.8LinkedHashMap實作原理及源碼分析

Android事件分發機制原理及源碼分析

View事件的滑動沖突以及解決方案

Handler機制一篇文章深入分析Handler、Message、MessageQueue、Looper流程和源碼

Android三級緩存原理及用LruCache、DiskLruCache實作一個三級緩存的ImageLoader

概述

Android系統對四大元件的工作過程進行了很大程度的封裝,友善開發者使用,Activity作為Android中四大元件之一,直接跟使用者進行互動,對于使用者來說activity就是應用的一切,系統對其工作流程當然也做了很多封裝,本篇文章将介紹Activity的啟動流程,在Android中啟動Activity大緻分為一下兩種場景:

  1. 誇程序:點選桌面圖示啟動應用的activity,這種場景又分為點選的應用所在程序已經啟動和未啟動兩種情況。
  2. 同一程序,同一應用之間的頁面跳轉

    以上兩種場景最終都會調用Activity的startActivity方法,我将從此處入手進行Acivity工作流程的源碼分析,後續将分别推出

    Service、BroadcastReceiver

    以及

    ContentProvider

    的工作流程進行源碼分析。

在此強調一點,本文隻着重分析場景二和場景一點選的應用已啟動的情況,至于場景一未啟動的情況我将會在我的另外一篇部落格點選Launcher圖示activity都做了哪些事情中詳細分析;此外本篇文章是基于Android8.0的源碼,與Android 5.0、6.0、7.0等版本中啟動Activity的源碼有點差異,不同版本隻是對其工作流程進行進行了不同封裝,但是其工作原理都是一樣的,至于想要詳細了解其它版本的源碼,請自行查閱。

本文篇幅較長,閱讀起來可能需要花費較長的時間,為了友善閱讀,我将分了四個子產品共18步去分析啟動流程,大家也可以分子產品去了解Activity的啟動流程。

Activity的啟動流程

一、從Activity的入口到ActivityManagerService的啟動過程

Step1: Activity的startActivity方法源碼:

@Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);//調用startActivityForResult
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);//調用startActivityForResult,注意當沒有傳人Bundle時,requestCode傳入-1
        }
    }
           

Activity的startActivity的方法有幾種重載方法,但是最終都掉用了

startActivityForResult

方法,此處強調一點:

startActivity

中調用

startActivityForResult

方法預設傳入的

requestCode

-1

,當requestCode<0的時候,是不起作用的。具體原因在下面startActivityForResult的源碼中解釋

Step2: Activity的startActivityForResult方法源碼

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {//重點關注mParent==null,
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);//交給mInstrumentation.execStartActivity方法啟動activity
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                //此處可以看出隻有requestCode>=0的時候才起作用,執行mStartedActivity =true
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            //mParent不等于null時,将啟動工作交給了`mParent.startActivityFromChild`,但最終還是交給了mInstrumentation.execStartActivity方法
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

  //mParent.startActivityFromChild方法的源碼
 public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
            int requestCode, @Nullable Bundle options) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, child,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, child.mEmbeddedID, requestCode,
                ar.getResultCode(), ar.getResultData());
        }
        cancelInputsAndStartExitTransition(options);
    }
           

在startActivityForResult中,因為第一次進來mParent==null,是以我們隻需重點關注

mParent == null

中的代碼,mParent代表的是ActivityGroup, 最開始用來在一個界面中嵌入多個子Activity,但是在API13中已經廢棄了, Google推薦我們用Fragment來代替ActivityGroup;将啟動流程交給了

mInstrumentation.execStartActivity()

方法。

  1. mParent==null

    ,可以看出将activity的啟動工作交給了

    mInstrumentation.execStartActivity()

    方法, 這裡的

    mInstrumentation

    是Activity類的成員變量,它的類型是Intrumentation,它用來監控應用程式和系統的互動。
  2. mParent不等于null時,将啟動工作交給了

    mParent.startActivityFromChild

    ,但

    startActivityFromChild

    最終還是将Activity的啟動交給了

    mInstrumentation.execStartActivity

    方法。
  3. 需要特别注意

    mInstrumentation.execStartActivity

    方法的一個參數

    mMainThread.getApplicationThread()

    ,首先

    mMainThread

    是一個

    ActivityThread

    對象,

    ActivityThread

    是應用程式的主線程,

    getApplicationThread()

    的類型是一個

    ApplicationThread

    ,它是ActivityThread的一個内部,本質是一個

    Binder

    對象,

    ActivityManagerService

    會使用

    ApplicationThread

    來和

    ActivityThread

    進行程序間通信,通過後面的分析我們将會發現它們兩個在activity的啟動過程中發揮着重要的作用。
  4. 隻有requestCode>=0的時候,才執行

    mStartedActivity =true

    mStartedActivity

    作用是用來判斷是否執行Activity的

    onActivityResult

    方法。

Step3: mInstrumentation.execStartActivity源碼:

/**
     * @param who 啟動Activity的  上下文
     * @param contextThread  為Binder對象,是主程序的context對象
     * @param token 也是一個Binder對象,指向了服務端一個ActivityRecord對象;
     * @param target  為啟動的Activity
     * @param intent  啟動的Intent對象;
     * @param requestCode  請求碼
     * @param options  參數Bundle對象
     * @return
     */
    public Instrumentation.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);
        }
        //mActivityMonitors !=null則直接從集合中便利擷取Instrumentation.ActivityResult 的結果
        if (mActivityMonitors != null) {
                   ...
                   省略部分代碼,非重點
                   ...
            }
        }
        try {
           //重點
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
           //将啟動工作交給ActivityManager.getService().startActivity
            int result = ActivityManager.getService()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);
             //最後檢查Activity的啟動結果
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
           

從上面可以看出

mInstrumentation.execStartActivity

将啟動

activity

的工作交給了

ActivityManager.getService().startActivity()

方法,那麼問題來了

ActivityManager.getService()

是什麼呢?那帶着這個疑問接着往下看

Step4: ActivityManager.getService()的源碼

public static IActivityManager getService() {
        //IActivityManagerSingleton.get()方法傳回一個IActivityManager 
        return IActivityManagerSingleton.get();
    }
    
    //IActivityManagerSingleton變量的執行個體化
     private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    //擷取一個關聯了系統服務ActivityManagerService的Binder對象
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    //通過IActivityManager.Stub.asInterface(b)擷取IActivityManager 的代理對象
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
           

抽象類Singleton源碼如下:不難看出就是一個單例模式,通過get方法擷取單例對象,通過抽象方法create()方法建立單例對象。

public abstract class Singleton<T> {
    private T mInstance;
    protected abstract T create();
    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}
           

分析:

  1. ActivityManager.getService()

    通過成員變量

    IActivityManagerSingleton

    get()

    方法傳回

    IActivityManager

    對象。
  2. IActivityManagerSingleton

    的類型是

    Singleton

    即通過Singleton的get()方法擷取一個IActivityManager
  3. IActivityManagerSingleton

    create

    方法的具體實作可以得出,

    create

    方法先擷取一個

    ActivityManagerService

    Binder

    對象,然後通過代理的方式擷取

    IActivityManager

    的代理對象,最後通過Binder機制調用代理對象的方法,使得系統服務

    ActivityManagerService

    對應的

    startActivity

    方法被調用。
  4. 此時我們回頭去看Step3:中

    Instrumentation.ActivityResult execStartActivity

    方法中
    Android framework 源碼分析一Activity啟動流程(android 8.0)概述Activity的啟動流程總結:
    就是

    IActivityManager

    的代理對象調用了startActivity方法,通過Binder機制使系統服務

    ActivityManagerService

    startActivity

    方法被調用。是以,啟動Activity的工作就交給了系統服務AMS來處理了。

二、在ActivityManagerService中的啟動過程

Step5: ActivityManagerService的startActivity方法源碼

ActivityManagerService的聲明

Android framework 源碼分析一Activity啟動流程(android 8.0)概述Activity的啟動流程總結:
public class ActivityManagerService extends IActivityManager.Stub
            implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
        ...
        省略部分代碼
        ...
    @Override
    //Activity的啟動工作交給了AMS複寫的IActivityManager.Stub的startActivity方法,
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
            //啟動工作交給startActivityAsUser方法
        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.
        //交給了 mActivityStarter.startActivityMayWait
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null,
                "startActivityAsUser");
    }
}
           

分析:這兩步很簡單,首先AMS的

startActivity()

調用---->

startActivityAsUser()

方法,

startActivityAsUser

接着将啟動Activity的工作交給了成員變量

mActivityStarter

startActivityMayWait()

方法。

mActivityStarter

的類型是

ActivityStarter

,ActivityStarter類主要負責處理Activity的Intent和Flags, 還有關聯相關的Stack和TaskRecord。

**此處需要強調一點:**在AMS(ActivityManagerService)中,

startActivity()

方法有多個,我們要找它複寫的父類

IActivityManager.Stub

提供的

startActivity()

方法,或者說參數類型以及個數都要和Step3

mInstrumentation.execStartActivity()

方法中

ActivityManager.getService() .startActivity()

startActivity

方法一緻。

簡單總結一下:AMS将Activity的啟動工作交給了ActivityStarter的

startActivityMayWait

()方法。

三、ActivityStarter、ActivityStackSupervisor、ActivityStack中的啟動流程

為了更加清晰的說明Activity在ActivityStarter、ActivityStackSupervisor、ActivityStack中的啟動流程,在這裡畫了一張圖,大家在閱讀的時候可按照這個圖的思想去了解記憶。

Android framework 源碼分析一Activity啟動流程(android 8.0)概述Activity的啟動流程總結:

Step6: ActivityStarter的startActivityMayWait()方法源碼分析

/**
     *注意從上面傳下來的參數outResult和globalConfig均為null,看源碼是可以忽略相關代碼
     */
    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,
                                   IActivityContainer iContainer, TaskRecord inTask, String reason) {
        // Refuse possible leaked file descriptors
        //Step1:檢測intent的合法性
        if (intent != null && intent.hasFileDescriptors()) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }
        mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
        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);
        if (componentSpecified
                && intent.getData() != null
                && Intent.ACTION_VIEW.equals(intent.getAction())
                && mService.getPackageManagerInternalLocked()
                .isInstantAppInstallerComponent(intent.getComponent())) {
            // intercept intents targeted directly to the ephemeral installer the
            // ephemeral installer should never be started with a raw URL; instead
            // adjust the intent so it looks like a "normal" instant app launch
            intent.setComponent(null /*component*/);
            componentSpecified = false;
        }
        /**
         * 上面主要是檢測intent的合法性=========
         */

        /**
         * Step2:
         *     1.此方法實際上的調用PackageManagerService的resolveIntent
         *     2.根據intent的資訊查找比對的activity
         */
        //自己點選檢視mSupervisor.resolveIntent源碼可以發現,最後是通過PackageManagerService的resolveIntent擷取rInfo 
        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
        if (rInfo == null) {
            UserInfo userInfo = mSupervisor.getUserInfo(userId);
            if (userInfo != null && userInfo.isManagedProfile()) {
                // Special case for managed profiles, if attempting to launch non-cryto aware
                // app in a locked managed profile from an unlocked parent allow it to resolve
                // as user will be sent via confirm credentials to unlock the profile.
                UserManager userManager = UserManager.get(mService.mContext);
                boolean profileLockedAndParentUnlockingOrUnlocked = false;
                long token = Binder.clearCallingIdentity();
                try {
                    UserInfo parent = userManager.getProfileParent(userId);
                    profileLockedAndParentUnlockingOrUnlocked = (parent != null)
                            && userManager.isUserUnlockingOrUnlocked(parent.id)
                            && !userManager.isUserUnlockingOrUnlocked(userId);
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
                if (profileLockedAndParentUnlockingOrUnlocked) {
                    rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
                            PackageManager.MATCH_DIRECT_BOOT_AWARE
                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
                }
            }
        }
        // Collect information about the target of the Intent.
        /**
         * Step3:
         *      1.收集Intent所指向的Activity資訊,
         *      2.當存在多個可供選擇的Activity,則直接向使用者彈出選擇框供使用者選擇
         *      3.設定Intent的Component
         */
         //根據rInfo, 去比對Activity,擷取到ActivityInfo 
        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 = globalConfig != null
                    && mService.getGlobalConfiguration().diff(globalConfig) != 0;
            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                    "Starting activity when config will change = " + stack.mConfigWillChange);

            final long origId = Binder.clearCallingIdentity();

            if (aInfo != null &&
                    (aInfo.applicationInfo.privateFlags
                            & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
                // This may be a heavy-weight process!  Check to see if we already
                // have another, different heavy-weight process running.
                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
                    final ProcessRecord heavy = mService.mHeavyWeightProcess;
                    if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
                            || !heavy.processName.equals(aInfo.processName))) {
                        ...
                        省略部分源碼
                        這裡主要作用是:如果目前系統中已經存在重量級程序,但不是将要啟動的這個 執行個體化這個重量級的Intent,
                        并且指派給目前的Intent,重量級:所謂重量級在這裡的意思就是有多個任務被比對到
                        ...

                    }
                }
            }

            final ActivityRecord[] outRecord = new ActivityRecord[1];
            // Step4重點:啟動activity并将啟動結果傳回,即将Activity的啟動工作交給了startActivityLocked方法
            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, reason);

            Binder.restoreCallingIdentity(origId);

            if (stack.mConfigWillChange) {
                // If the caller also wants to switch to a new configuration,
                // do so now.  This allows a clean switch, as we are waiting
                // for the current activity to pause (so we will not destroy
                // it), and have not yet started the next activity.
                // 如果configuration發生變化,則調用AMS的updateConfigurationLocked進行處理
                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
                        "updateConfiguration()");
                stack.mConfigWillChange = false;
                if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                        "Updating to new configuration after starting activity.");
                mService.updateConfigurationLocked(globalConfig, null, false);
            }

            //outResult是最為參數被傳遞進來,而且傳進來為null,是以if内的邏輯将不會執行
            if (outResult != null) {
                outResult.result = res; //res是調用startActivityLocked傳回的結果,在startActivityLocked之後給啟動結果指派
                ....
                省略部分代碼
                ....
            }
            //通知監聽者,activity正在啟動,并更新狀态
            mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
            //傳回啟動結果
            return res;
        }
    }
           

分析:startActivityMayWait方法:主要作用:擷取Activity的啟動資訊,包括ResolveInfo和ActivityInfo,以及擷取CallingPid和CallingUid,将Activity啟動任務交給

startActivityLocked()

方法。

startActivityMayWait方法的流程有下面幾點

  1. 首先校驗Intent的合法性
  2. 讓PKMS(PackageManagerService)的resolveIntent方法來解析Intent并得到ResolveInfo
  3. 比對最相符的Intent,根據這個Intent去比對查找Activity
  4. 判斷是否是啟動重量級的任務
  5. 調用

    startActivityLocked()

    ,将Activity啟動任務交給

    startActivityLocked()

    方法。這裡需要注意傳入的

    IApplicationThread caller

    :Activity的程序内的ApplicationThread對象。在後面要用到。

Step7: ActivityStarter的startActivityLocked()方法源碼分析

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, String reason) {

        if (TextUtils.isEmpty(reason)) {
            throw new IllegalArgumentException("Need to specify a reason.");
        }
        mLastStartReason = reason;
        mLastStartActivityTimeMs = System.currentTimeMillis();
        mLastStartActivityRecord[0] = null;
        //調用startActivity(),啟動activity,并将結果傳回
        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                container, inTask);

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

分析:在這個方法裡面傳遞了一些參數給

startActivity()

方法,如IApplicationThread caller,Intent,callingPid調用者的程序pid,realCallingPid目前程序pid,startFlags=0等,将Activity的啟動工作交給了

startActivity()

方法。

Step8: ActivityStarter的startActivity()源碼分析

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, ActivityStackSupervisor.ActivityContainer container,
                              TaskRecord inTask) {
        //err 表示錯誤的啟動結果,在下面會對其賦,值預設是啟動成功
        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;
        //檢測caller是否有權限啟動activity
        if (caller != null) {
            callerApp = mService.getRecordForAppLocked(caller);
            if (callerApp != null) {
                callingPid = callerApp.pid;
                callingUid = callerApp.info.uid;
            } else {
                //調用者沒有權限activity
                Slog.w(TAG, "Unable to find app for caller " + caller
                        + " (pid=" + callingPid + ") when starting: "
                        + intent.toString());
                err = ActivityManager.START_PERMISSION_DENIED;
            }
        }

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

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

        ActivityRecord sourceRecord = null;
        ActivityRecord resultRecord = null;
        if (resultTo != null) {
            sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                    "Will send result to " + resultTo + " " + sourceRecord);
            if (sourceRecord != null) {
                if (requestCode >= 0 && !sourceRecord.finishing) {
                    resultRecord = sourceRecord;
                }
            }
        }

        final int launchFlags = intent.getFlags();

        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
            // Transfer the result target from the source activity to the new
            // one being started, including any failures.
            /**
             *  對IntentFlags為FLAG_ACTIVITY_FORWARD_RESULT這種特殊情況進行特殊處理
             *  1.Activity A 啟動了Activity B,Activity B又啟動了C,A-->B-->C, 這種情況下
             *  2.A啟動B要求B傳回result給A,但是如果B在啟動C時,Intent設定了Intent.FLAG_ACTIVITY_FORWARD_RESULT标志
             *  3.那麼此時将會交由C向A setResult。
             */
            if (requestCode >= 0) {
                ActivityOptions.abort(options);
                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
            }
            resultRecord = sourceRecord.resultTo;
            if (resultRecord != null && !resultRecord.isInStackLocked()) {
                resultRecord = null;
            }
            resultWho = sourceRecord.resultWho;
            requestCode = sourceRecord.requestCode;
            sourceRecord.resultTo = null;
            if (resultRecord != null) {
                resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
            }
            if (sourceRecord.launchedFromUid == callingUid) {
                // The new activity is being launched from the same uid as the previous
                // activity in the flow, and asking to forward its result back to the
                // previous.  In this case the activity is serving as a trampoline between
                // the two, so we also want to update its launchedFromPackage to be the
                // same as the previous activity.  Note that this is safe, since we know
                // these two packages come from the same uid; the caller could just as
                // well have supplied that same package name itself.  This specifially
                // deals with the case of an intent picker/chooser being launched in the app
                // flow to redirect to an activity picked by the user, where we want the final
                // activity to consider it to have been launched by the previous app activity.
                callingPackage = sourceRecord.launchedFromPackage;
            }
        }

        //...省略部分代碼  主要用于檢測參數的合法行

        final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();

        //如果檢查err不SUCCESS,即有異常情況,那麼直接return
        if (err != START_SUCCESS) {
            if (resultRecord != null) {
                resultStack.sendActivityResultLocked(
                        -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
            }
            ActivityOptions.abort(options);
            //直接return err  ,startActivity到此結束直接
            return err;
        }


         //checkStartAnyActivityPermission:檢查啟動被啟動activity它自己的相關權限
        boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
                resultRecord, resultStack, options);
        abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
                callingPid, resolvedType, aInfo.applicationInfo);

        if (mService.mController != null) {
            try {
                // The Intent we give to the watcher has the extra data
                // stripped off, since it can contain private information.
                Intent watchIntent = intent.cloneFilter();
                abort |= !mService.mController.activityStarting(watchIntent,
                        aInfo.applicationInfo.packageName);
            } catch (RemoteException e) {
                mService.mController = null;
            }
        }

        /**
         * mInterceptor 屬于一個攔截類,将資訊攔截下來,複制給自己的變量儲存
         * 然後再重新指派給這些資訊,其實這個值還是和以前一樣沒有變,相當于備份,但是這樣做的好處就是在之後可以攔截器裡進行修改
         */
        mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
        mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
                options);
        intent = mInterceptor.mIntent;
        rInfo = mInterceptor.mRInfo;
        aInfo = mInterceptor.mAInfo;
        resolvedType = mInterceptor.mResolvedType;
        inTask = mInterceptor.mInTask;
        callingPid = mInterceptor.mCallingPid;
        callingUid = mInterceptor.mCallingUid;
        options = mInterceptor.mActivityOptions;//攔截其中備份儲存相關資訊
        if (abort) {
            if (resultRecord != null) {
                resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
                        RESULT_CANCELED, null);
            }
            // We pretend to the caller that it was really started, but
            // they will just get a cancel result.
            ActivityOptions.abort(options);
            return START_SUCCESS;
        }

        // If permissions need a review before any of the app components can run, we
        // launch the review activity and pass a pending intent to start the activity
        // we are to launching now after the review is completed.
        if (mService.mPermissionReviewRequired && aInfo != null) {
            if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                    aInfo.packageName, userId)) {
                IIntentSender target = mService.getIntentSenderLocked(
                        ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
                        callingUid, userId, null, null, 0, new Intent[]{intent},
                        new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
                                | PendingIntent.FLAG_ONE_SHOT, null);

                final int flags = intent.getFlags();
                Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
                newIntent.setFlags(flags
                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
                newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
                if (resultRecord != null) {
                    newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
                }
                intent = newIntent;

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

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

                if (DEBUG_PERMISSIONS_REVIEW) {
                    Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
                            true, false) + "} from uid " + callingUid + " on display "
                            + (container == null ? (mSupervisor.mFocusedStack == null ?
                            DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
                            (container.mActivityDisplay == null ? DEFAULT_DISPLAY :
                                    container.mActivityDisplay.mDisplayId)));
                }
            }
        }

        // If we have an ephemeral app, abort the process of launching the resolved intent.
        // Instead, launch the ephemeral installer. Once the installer is finished, it
        // starts either the intent we resolved here [on install error] or the ephemeral
        // app [on install success].
        if (rInfo != null && rInfo.auxiliaryInfo != null) {
            intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
                    callingPackage, verificationBundle, resolvedType, userId);
            resolvedType = null;
            callingUid = realCallingUid;
            callingPid = realCallingPid;

            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
        }
        //建構ActivityRecord用于存儲Activity的各種狀态和曆史資訊。
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, container, options, sourceRecord);
        if (outActivity != null) {
            outActivity[0] = r;
        }

        if (r.appTimeTracker == null && sourceRecord != null) {
            // If the caller didn't specify an explicit time tracker, we want to continue
            // tracking under any it has.
            r.appTimeTracker = sourceRecord.appTimeTracker;
        }

        final ActivityStack stack = mSupervisor.mFocusedStack;
        if (voiceSession == null && (stack.mResumedActivity == null
                || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                    realCallingPid, realCallingUid, "Activity start")) {
                PendingActivityLaunch pal =  new PendingActivityLaunch(r,
                        sourceRecord, startFlags, stack, callerApp);
                mPendingActivityLaunches.add(pal);
                ActivityOptions.abort(options);
                return ActivityManager.START_SWITCHES_CANCELED;
            }
        }

        if (mService.mDidAppSwitch) {
            // This is the second allowed switch since we stopped switches,
            // so now just generally allow switches.  Use case: user presses
            // home (switches disabled, switch to home, mDidAppSwitch now true);
            // user taps a home icon (coming from home so allowed, we hit here
            // and now allow anyone to switch again).
            mService.mAppSwitchesAllowedTime = 0;
        } else {
            mService.mDidAppSwitch = true;
        }

        doPendingActivityLaunchesLocked(false);
        //如果沒有異常會最終會執行到這裡交給重載的方法startActivity完成啟動過程
        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
                options, inTask, outActivity);
    }

           

對startActivity()方法的流程總結一下

  1. 檢測caller是否有權限啟動activity
  2. 判斷對Intent攜帶的flags,針對特殊flas進行處理
  3. 調用

    mSupervisor.checkStartAnyActivityPermission

    檢查這個activity自己的相關權限
  4. 通過設定mInterceptor 備份變量資訊放到攔截器裡面
  5. 建立ActivityRecord儲存了被啟動Activity的所有資訊;這裡簡單說一下

    ActivityRecord

    的特點:一個

    ActivityRecord

    對應一個

    Activity

    ,儲存了一個

    Activity

    的所有資訊;但是一個

    Activity

    可能會有多個

    ActivityRecord

    ,因為

    Activity

    可以被多次啟動,這個主要取決于其啟動模式。
  6. 将啟動任務交給重載方法

    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask, outActivity);

接着向下看重載的

startActivity()

方法源碼:

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();
            //重點:調用startActivityUnchecked方法,處理activity的啟動
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        } 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;
    }
           

重載的

startActivity

方法主要就是調用

startActivityUnchecked

方法,即把activity的啟動工作交給

startActivityUnchecked()

Step9: ActivityStarter類的startActivityUnchecked方法源碼分析

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

        /**
         * Step1:setInitialState
         *      此方法用于初始化資料和校驗Intent的flag參數是否為特定的flag
         */
        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor);

        /**
         * Step2:computeLaunchingTaskFlags:方法主要用于設定Activity的啟動模式
         */
        computeLaunchingTaskFlags();

        /**
         * Step3:computeSourceStack方法:就是針對啟動模式為FLAG_ACTIVITY_NEW_TASK的時候判斷要不要為其重新NEW一個task
         */
        computeSourceStack();


        mIntent.setFlags(mLaunchFlags);

        //Step4:是否将新的Activity插入到現有的Task中,傳回null表示否,否則新啟動的Activity将插入到該Task的Top位置。
        ActivityRecord reusedActivity = getReusableIntentActivity();

        final int preferredLaunchStackId =
                (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
        final int preferredLaunchDisplayId =
                (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;

        if (reusedActivity != null) {
            // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
            // still needs to be a lock task mode violation since the task gets cleared out and
            // the device would otherwise leave the locked task.
            //當eusedActivity不為null的時候,将新的Activity插入到現有的Task
            if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
                    (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
                mSupervisor.showLockTaskToast();
                Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }

            if (mStartActivity.getTask() == null) {
                mStartActivity.setTask(reusedActivity.getTask());
            }
            if (reusedActivity.getTask().intent == null) {
                // This task was started because of movement of the activity based on affinity...
                // Now that we are actually launching it, we can assign the base intent.
                reusedActivity.getTask().setIntent(mStartActivity);
            }

            // This code path leads to delivering a new intent, we want to make sure we schedule it
            // as the first operation, in case the activity will be resumed as a result of later
            // operations.
            if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                    || isDocumentLaunchesIntoExisting(mLaunchFlags)
                    || mLaunchSingleInstance || mLaunchSingleTask) {
                final TaskRecord task = reusedActivity.getTask();
                // In this situation we want to remove all activities from the task up to the one
                // being started. In most cases this means we are resetting the task to its initial
                // state.SingleTask啟動模式時的處理邏輯 ,清空在它在Activity棧中在它上之上的任務
                final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
                        mLaunchFlags);

                // The above code can remove {@code reusedActivity} from the task, leading to the
                // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
                // task reference is needed in the call below to
                // {@link setTargetStackAndMoveToFrontIfNeeded}.
                if (reusedActivity.getTask() == null) {
                    reusedActivity.setTask(task);
                }

                if (top != null) {
                    if (top.frontOfTask) {
                        // Activity aliases may mean we use different intents for the top activity,
                        // so make sure the task now has the identity of the new intent.
                        top.getTask().setIntent(mStartActivity);
                    }
                    //top就是要啟動的activty,在deliverNewIntentLocked中将會回調它的onNewIntent方法
                    ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
                    top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                            mStartActivity.launchedFromPackage);
                }
            }

            /**
             *  Step5:sendPowerHintForLaunchStartIfNeeded
             *       根據條件去隐藏其他任務棧
             */
            sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);

            /**
             *  Step6:setTargetStackAndMoveToFrontIfNeeded 将這個activity所在的任務棧移動到前台
             *
             */
            reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);

            final ActivityRecord outResult =
                    outActivity != null && outActivity.length > 0 ? outActivity[0] : null;

            // When there is a reused activity and the current result is a trampoline activity,
            // set the reused activity as the result.
            if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
                outActivity[0] = reusedActivity;
            }

            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
                // We don't need to start a new activity, and the client said not to do anything
                // if that is the case, so this is it!  And for paranoia, make sure we have
                // correctly resumed the top activity.
                resumeTargetStackIfNeeded();
                return START_RETURN_INTENT_TO_CALLER;
            }

            //設定這個任務棧的資訊
            setTaskFromIntentActivity(reusedActivity);

            if (!mAddingToTask && mReuseTask == null) {
                // We didn't do anything...  but it was needed (a.k.a., client don't use that
                // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
                resumeTargetStackIfNeeded();
                if (outActivity != null && outActivity.length > 0) {
                    outActivity[0] = reusedActivity;
                }
                return START_TASK_TO_FRONT;
            }
        }

        if (mStartActivity.packageName == null) {
            final ActivityStack sourceStack = mStartActivity.resultTo != null
                    ? mStartActivity.resultTo.getStack() : null;
            if (sourceStack != null) {
                sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
                        mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
                        null /* data */);
            }
            ActivityOptions.abort(mOptions);
            return START_CLASS_NOT_FOUND;
        }

        final ActivityStack topStack = mSupervisor.mFocusedStack;
        final ActivityRecord topFocused = topStack.topActivity();
        final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
        //是否複用activity
        final boolean dontStart = top != null && mStartActivity.resultTo == null
                && top.realActivity.equals(mStartActivity.realActivity)
                && top.userId == mStartActivity.userId
                && top.app != null && top.app.thread != null
                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                || mLaunchSingleTop || mLaunchSingleTask);
        if (dontStart) {
            ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
            ...省略部分代碼  ...
            //這部分代碼主要用複用activity并回掉onNewIntent方法

            return START_DELIVERED_TO_TOP;
        }

        //标記:是否需要建立新的activity棧
        boolean newTask = false;
        //...省略部分代碼  ,該代碼主要是判斷是否建新的activity棧,以及建立過程
        ...代碼
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {

                /**
                 * Step7: 最後調用 mSupervisor.resumeFocusedStackTopActivityLocked
                 *      将activity的啟動工作交給 mSupervisor.resumeFocusedStackTopActivityLocked方法
                 */
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else {
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }
        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

        mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
                preferredLaunchDisplayId, mTargetStack.mStackId);

        return START_SUCCESS;
    }

           

startActivityUnchecked方法小結:

在此方法中做了很多邏輯校驗,為了便于閱讀,我省略了部分代碼,還有此方法中調用的幾個**中要方法源碼不在這裡粘貼分析,**但是在注釋中已經簡單描述幾個方法的作用,例如:

setInitialState

computeLaunchingTaskFlags

computeSourceStack

、以及

deliverNewIntentLocked

方法等等,感興趣的話可以自行檢視。

startActivityUnchecked有以幾個重要的點:

  1. 通過setInitialState()方法初始化資料
  2. 通過

    computeLaunchingTaskFlags()

    這個方法在經過一些邏輯處理之後設定了activity的啟動模式
  3. 判斷定是否要加入現有的Task中去,如果不加入就建立一個新的task。
  4. 如果目前Activity時

    SingleTask

    啟動模式的話,清空棧内在它之上的Activity,即把目前

    Activity

    移動到棧頂,并通過

    deliverNewIntentLocked()

    方法會掉它的

    onNewIntent

    方法
  5. 最後将該activity所在的Activity棧移動到前台,并将activity的啟動任務交給

    ActivityStackSupervisor

    resumeFocusedStackTopActivityLocked

    方法。

Step10: ActivityStackSupervisor

resumeFocusedStackTopActivityLocked`方法源碼分析

boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
        	//	調用ActivityStack的resumeTopActivityUncheckedLocked,此處交給了ActivityStack去處理
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || r.state != RESUMED) {
        	調用ActivityStack的resumeTopActivityUncheckedLocked,此處交給了ActivityStack去處理
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.state == RESUMED) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }
        return false;
    }
           

分析:

resumeFocusedStackTopActivityLocked

方法就是将activity的啟動邏輯交給了

ActivityStack

resumeTopActivityUncheckedLocked

方法處理。即activity的啟動邏輯暫時交給了ActivityStack。

那麼接着分析ActivityStack的處理邏輯。

Step11:ActivityStack的

resumeTopActivityUncheckedLocked

方法源碼

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;
            //調用resumeTopActivityInnerLocked方法去處理
            result = resumeTopActivityInnerLocked(prev, options);
        } 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.
        mStackSupervisor.checkReadyForSleepLocked();

        return result;
    }
           

分析:

resumeTopActivityUncheckedLocked

方法邏輯比較簡單,主要就是調用

resumeTopActivityInnerLocked

方法。

那我們接着向下看resumeTopActivityInnerLocked方法都做了些什麼?

Step12:ActivityStack的

resumeTopActivityInnerLocked

方法源碼

總結一下

resumeTopActivityInnerLocked

方法,做的工作比較多,代碼篇幅比較長,但是方法中的注釋也比較詳細,在這我就不做翻譯工作了,為了便于了解我省略了部分代碼,至于詳細源碼感興趣的朋友話可以自行查閱。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        if (!mService.mBooting && !mService.mBooted) {
            // Not ready yet!
            return false;
        }

        // Find the next top-most activity to resume in this stack that is not finishing and is
        // focusable. If it is not focusable, we will fall into the case below to resume the
        // top activity in the next focusable task.
        //從棧頂取出要起動的activity資訊
        final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);

        final boolean hasRunningActivity = next != null;

        final ActivityRecord parent = mActivityContainer.mParentActivity;
        final boolean isParentNotResumed = parent != null && parent.state != ActivityState.RESUMED;
        //如果父棧沒有  resumed 則不要resume 這個activity所在的棧  直接return false
        if (hasRunningActivity && (isParentNotResumed || !mActivityContainer.isAttachedLocked())) {
            // Do not resume this stack if its parent is not resumed.
            // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
            return false;
        }
            ...省略部分代碼
            if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
            //最終會将啟動工作交給StackSupervisor.startSpecificActivityLocked方法,即工作轉移到mStackSupervisor
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

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

這裡簡單總結一下

resumeTopActivityInnerLocked

的作用:判斷要啟動的Activity所在的棧是否對目前使用者不可見,如果不可見就不需要繼續執行下去,因為即使把這個Activity啟動起來,使用者也看不見,還不如先把它儲存起來,等到下次可見的時候再啟動。若可見,則繼續執行。把要啟動的Activity添加到棧頂。

Step13: ActivityStackSupervisor類的

startSpecificActivityLocked

方法分析

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.getStack().setLaunchTime(r);
        if (app != null && app.thread != null) {
         //app程序已經在運作,直接去啟動
            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.
                    //如果它是一個被标記為在多個程序中運作的平台元件,那麼不要添加它,因為它實際上是架構的一部分,是以在程序中作為單獨的apk進行跟蹤是沒有意義的
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                //重點:将activity的啟動工作轉交給realStartActivityLocked方法
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e);
            }
            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }
        // 如果程序為app 為null或者有異常,則AMS重新fork一個程序來起來,點選桌面啟動圖示如果該應用程序未啟動,走到這裡
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
           

分析:

startSpecificActivityLocked

方法邏輯比較簡單,主要負責跟要啟動的Activity程序相關的工作,首先由AMS根據參數通過

getProcessRecordLocked

方法擷取目前APP程序的記錄

ProcessRecord

,如果擷取到

ProcessRecord

即應用所在程序已經啟動,則最終将activity的啟動工作轉交給

realStartActivityLocked

方法,否則應用程序未啟動,則交給AMS的

startProcessLocked

方法去啟動該程序,本篇文章我隻分析應用程式已經啟動的情況,至于未啟動的情況日後将在另一篇文章應Android8.0用程式的啟動流程中分析,接下來我們繼續分析

realStartActivityLocked

方法。

Step14: ActivityStackSupervisor類的

realStartActivityLocked

方法

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

            //...代碼....先是mWindowManager.updateOrientationFromAppTokens()讓視窗管理器根據新的活動順序重新評估螢幕的方向,
           // 緊接着更新這個activity的覆寫配置mService.updateDisplayOverrideConfigurationLocked() ,
           // 然後判斷是否在啟動的時候顯示軟鍵盤,然後固定螢幕,這個時候不允許其他的activity啟動,

            app.hasShownUi = true;
            app.pendingUiClean = true;
            app.forceProcessStateUpTo(mService.mTopProcessState);
            // Because we could be starting an Activity in the system process this may not go across
            // a Binder interface which would create a new Configuration. Consequently we have to
            // always create a new Configuration here.

            final MergedConfiguration mergedConfiguration = new MergedConfiguration(
                    mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
            r.setLastReportedConfiguration(mergedConfiguration);

        /**
         * 重點:核心
         *     底層通過Binder機制将activity的啟動工作交給了ApplicationThread,即app.thread.scheduleLaunchActivity通過Binder機制使ApplicationThread的scheduleLaunchActivity方法被調用。
         *     app:是一個ProcessRecord對象
         *     thread:IApplicationThread類型,ApplicationThread繼承了IApplicationThread.Stub
         */
        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;
    }
           

分析realStartActivityLocked小結:

最終是通過

app.thread.scheduleLaunchActivity

方法去處理activity的啟動,此方法是Activity啟動的真正入口,通過這裡需要注意的是app.thread調用scheduleLaunchActivity方法,通過Binder機制,使

ApplicationThread

scheduleLaunchActivity

方法被調用。最終activity的啟動工作交給了

ApplicationThread

類。

四、Activity的在ApplicationThread中的啟動過程

  1. 在Step5中說過,

    ApplicationThread

    實作了

    IApplicationThread.Stub

    這個

    Binder

    接口,是以

    ApplicationThread

    本質也是一個Binder。
  2. IApplicationThread這個Binder接口定義了大量的和Activity以及Service啟動、停止等相關功能的接口,即它的實作者ApplicationThread将完成控制Activity和Service的相關工作。
  3. 事實上

    ApplicationThread

    也是

    ActivityThread

    的内部類,

    ApplicationThread

    通過Handler機制發送消息控制

    Activity

    Service

    的生命周期,關于Hadler的底層機制可以參考我另外一片部落格Handler機制一篇文章深入分析Handler、Message、MessageQueue、Looper流程和源碼

ApplicationThread的結構圖,加對ApplicationThread的記憶

Android framework 源碼分析一Activity啟動流程(android 8.0)概述Activity的啟動流程總結:

Step15: ApplicationThread的

scheduleLaunchActivity

方法

@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<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
            updateProcessState(procState, false);
            //建立了一個ActivityClientRecord對象,用于封裝啟動Activity需要的一些參數值
            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方法将ActivityClientRecord 傳遞過去
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }
           

分析:scheduleLaunchActivity方法邏輯比較簡單,通過傳遞進來的參數建立了一個ActivityClientRecord對象,用于封裝啟動Activity需要的一些參數值,最後調用

sendMessage(H.LAUNCH_ACTIVITY, r);

交給sendMessage方法處理。

Step16: ApplicationThread的

sendMessage

方法

此方法有多個重載方法但最後都會執行到下面這個方法

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

,H類是

ActivityThread

的内部類,繼承了Handler,是以Activity的啟動工作就放到了H類的

handleMessage

方法中

Step16: H的

handleMessage

方法

handleMessage處理了大量和Activity、Service、Window等相關的消息處理操作,這裡我們隻分析和Activity啟動的

LAUNCH_ACTIVITY

消息相關操作。

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");
                    //從msg.obj中取出ActivityClientRecord 
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                    //通過getPackageInfoNoCheck方法擷取LoadedApk對象,并将該對象存儲到 r.packageInfo中
                    r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
                    //調用handleLaunchActivity方法去啟動activity
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
               
                //...代碼
                }
       }         
           

最後啟動Activity的工作就交給了ActivityThread的

handleLaunchActivity()

方法,繼續往下看;

Step17: ActivityThread的

handleLaunchActivity()

方法啟動Activity

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        //如果我們準備在背景進行gc,那麼我們就回到活動狀态,跳過它。
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;
        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }
        // Make sure we are running with the most recent config.確定使用最新的配置運作
        handleConfigurationChanged(null, null);
        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);
        // Initialize before creating the activity
        WindowManagerGlobal.initialize();
        //重點  調用performLaunchActivity方法啟動Activity
        Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            //當a 不為null的時候handleResumeActivity,仔細追總源碼 會調用 r = performResumeActivity(token, clearHide, reason);
            //而performResumeActivity方法中會通過r.activity.performResume();  回掉activity的onResume方法
            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.
            //如果啟動的r為null即啟動的activity 異常 則 ActivityManager.getService().finishActivity
            // 通過Binder機制回掉到AMS的finishActivity,即異常操作交給AMS去停止Activity的啟動
           try {
                ActivityManager.getService()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }
           

分析handleLaunchActivity的方法邏輯也比較簡單,将Activity的啟動工作交給了

performLaunchActivity(r, customIntent);

方法。如果啟動正常,則會掉activity的onResume方法,如果異常通過Binder機制交給AMS去處理停止啟動操作。

Step18: ActivityThread的

performLaunchActivity()

方法分析

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
        /**
         * Step1
         * 從ActivityClientRecord中擷取帶啟動Activity的元件資訊
         * 并建立ComponentName,裡面包含了包名,類名相關的資訊
         * */
        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }
        // 建立ComponentName
        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);
        }
        /**
         * Step2:
         *     通過createBaseContextForActivity建立ContextImpl
         */
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            /**
             * Step3:
             * 通過使用mInstrumentation.newActivity方法使用類加載器建立Activity對象
             */
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
            /**
             * Step4
             * 通過LoadedApk的makeApplication方法嘗試建立Application對象
             */
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

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

            if (activity != null) {
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) {
                    config.updateFrom(r.overrideConfig);
                }
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }
                appContext.setOuterContext(activity);
                /**
                 * Step5:
                 *      調用activity的attach方法完成一些重要資料的初始化操作
                 */
                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 (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                /**
                 * Step6:
                 * 通過mInstrumentation的callActivityOnCreate方法調用Activity的onCreate方法
                 * Activity的onCreate方法執行表示啟動完成
                 */
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                    if (!activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPostCreate()");
                    }
                }
            }
            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;
    }
           

小結:

ActivityThread的

performLaunchActivity

方法是Activity的最終啟動者,代碼中在重要的地方都加了詳細注釋,這裡簡單在描述一下

performLaunchActivity

主要完成了以下幾件事情:

  1. 從ActivityClientRecord中擷取帶啟動Activity的元件資訊,并建立ComponentName,裡面包含了包名,類名相關的資訊等。
  2. 通過

    createBaseContextForActivity

    方法建立

    ContextImpl

    ContextImpl

    是一種重要的資料結構,它是Context的具體展現,Context中的大部分邏輯都是由ContextImpl完成的;ContextImpl是通過Activity的attach方法和Activity建立關聯。
  3. 通過使用

    mInstrumentation.newActivity

    方法建立Activity,而

    mInstrumentation.newActivity

    使方法使用類加載器建立Activity對象。
  4. 通過

    LoadedApk的makeApplication方法

    嘗試建立Application對象,建立

    makeApplication

    方法過程和建立Activity的過程也是使用類加載器建立的。
  5. 調用activity的

    attach

    方法完成一些重要資料的初始化操作。
  6. 通過

    mInstrumentation

    callActivityOnCreate

    方法調用Activity的

    onCreate

    方法Activity的onCreate方法執行表示啟動完成。

接下來再看一下上面幾步中出現的方法:

1: ActivityThread的

createBaseContextForActivity

方法建立ContextImpl

private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
        final int displayId;
        try {
            displayId = ActivityManager.getService().getActivityDisplayId(r.token);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        //最終通過ContextImpl的createActivityContext方法去建立ContextImpl對象,至于ContextImpl的操作這裡不詳細分析了,以後我會寫一篇ContextImpl的源碼分析
        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);

        final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
        // For debugging purposes, if the activity's package name contains the value of
        // the "debug.use-second-display" system property as a substring, then show
        // its content on a secondary display if there is one.
        //出于調試目的,如果活動的包名包含“debug”的值。“use-second-display”系統屬性作為子字元串,如果有子字元串,則在輔助顯示中顯示其内容。
        String pkgName = SystemProperties.get("debug.second-display.pkg");
        if (pkgName != null && !pkgName.isEmpty()
                && r.packageInfo.mPackageName.contains(pkgName)) {
            for (int id : dm.getDisplayIds()) {
                if (id != Display.DEFAULT_DISPLAY) {
                    Display display =
                            dm.getCompatibleDisplay(id, appContext.getResources());
                    appContext = (ContextImpl) appContext.createDisplayContext(display);
                    break;
                }
            }
        }
        return appContext;
    }
           

2: mInstrumentation.newActivity`方法建立Activity

public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
            //最終通過類加載器建立activity
        return (Activity)cl.loadClass(className).newInstance();
    }
           

3: LoadedApk類的

makeApplication

方法建立Application

public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        //這裡對對mApplication進行了判斷,這也就是一個應用隻有一個Application對象的原因
        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 {
            //擷取ClassLoader
            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);
            //重點 調用mActivityThread.mInstrumentation.newApplication去建立Application對象,
            // newApplication和activity建立過程一樣,通過類加載機制建立application對象
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
           //...代碼列印異常資訊
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
        if (instrumentation != null) {
            try {
                //通過instrumentation的callApplicationOnCreate方法調用的application的onCreate方法
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                //...代碼列印異常資訊
            }
        }
       //...代碼
        return app;
    }
           

4: Instrumentation類的

newApplication

方法建立Application

static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
            //類加載器建立
        Application app = (Application)clazz.newInstance();
        //綁定上下文
        app.attach(context);
        return app;
    }
           

5:Activity的

attach

方法初始化一些重要資料

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, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);
        //建立視窗對象PhoneWindow
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        //下面三行是給PhoneWindow注冊相關監聽
        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());
            }
        }
        //設定WindowManager
        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;

        mWindow.setColorMode(info.colorMode);
    }
           

總結:

到此為止activity啟動過程分析完畢,5.1的小假期也結束了,在此過程中也學到了不少,framework源碼比較難了解,需要一遍遍的反複去看直到了解。後續将分别推出

Service、BroadcastReceiver

以及

ContentProvider

的工作流程進行等源碼分析。

如果本文有什麼不對的地方請大家指出共同進步,順便揮揮拇指點贊加關注。