Android App啟動(dòng)流程(上)

轉(zhuǎn)自 http://cheelok.com/aosp/54/

啟動(dòng)一個(gè)App的流程:
Android系統(tǒng)桌面->點(diǎn)擊應(yīng)用圖標(biāo)->啟動(dòng)App
從這個(gè)過程來看奈泪,只要弄明白:

  1. Android系統(tǒng)桌面是什么
  2. 點(diǎn)擊應(yīng)用圖標(biāo)后Android系統(tǒng)執(zhí)行了什么操作
    就可以解決我們“App如何被啟動(dòng)”的疑問征绸。

Android系統(tǒng)桌面是什么

如何分析Android系統(tǒng)桌面是什么

在Android系統(tǒng)中,Activity是視圖存在的根本暖呕,那么我們可以通過命令adb shell dumpsys activity activities判斷是哪個(gè)Activity為我們呈現(xiàn)桌面視圖的湾盒。
以小米5為例,通過USB連上電腦后,輸入命令adb shell dumpsys activity activities得到結(jié)果如下:

可以看到坐梯,顯示桌面視圖的Activity是com.miui.home包下的名為Launcher的Activity。

因?yàn)樘摂M機(jī)編譯AOSP實(shí)在是太慢了刹帕,所以我沒有編譯AOSP得到系統(tǒng)鏡像吵血,然后運(yùn)行模擬器跑AOSP,再通過Ubuntu的Shell跑命令偷溺。國內(nèi)手機(jī)廠商雖然
會(huì)對Android系統(tǒng)進(jìn)行定制蹋辅,但是命名和包名都會(huì)和原生盡可能保持一致的。
那么我們在IDE中搜索Launcher挫掏,看看這個(gè)Activity是什么侦另。結(jié)果如下:

這里摘選的是Launcher2的Launcher進(jìn)行分析,雖然新版本Android已經(jīng)使用Launcher3作為桌面App了尉共,但是我進(jìn)入源碼看了看發(fā)現(xiàn)核心的邏輯是沒有變化的褒傅,所以選取了代碼更短的Launcher2的Launcher進(jìn)行分析。

點(diǎn)擊應(yīng)用圖標(biāo)后Android系統(tǒng)執(zhí)行了什么操作

既然Launcher是Activity袄友,那就意味著我們點(diǎn)擊桌面的事件可以表達(dá)為:

呈現(xiàn)Android桌面視圖(View)->點(diǎn)擊View上某個(gè)應(yīng)用圖標(biāo)->產(chǎn)生點(diǎn)擊事件->點(diǎn)擊事件被響應(yīng)->通知Android系統(tǒng)的某個(gè)/某些進(jìn)程->Android系統(tǒng)執(zhí)行某些操作->啟動(dòng)App

Launcher如何響應(yīng)由我們產(chǎn)生的點(diǎn)擊事件

/**
     * Launches the intent referred by the clicked shortcut.
     *
     * @param v The view representing the clicked shortcut.
     */
    public void onClick(View v) {
        // Make sure that rogue clicks don't get through while allapps is launching, or after the
        // view has detached (it's possible for this to happen if the view is removed mid touch).
        if (v.getWindowToken() == null) {
            return;
        }

        if (!mWorkspace.isFinishedSwitchingState()) {
            return;
        }

        Object tag = v.getTag();
        if (tag instanceof ShortcutInfo) {
            // Open shortcut
            final Intent intent = ((ShortcutInfo) tag).intent;
            int[] pos = new int[2];
            v.getLocationOnScreen(pos);
            intent.setSourceBounds(new Rect(pos[0], pos[1],
                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));

            boolean success = startActivitySafely(v, intent, tag);

            if (success && v instanceof BubbleTextView) {
                mWaitingForResume = (BubbleTextView) v;
                mWaitingForResume.setStayPressed(true);
            }
        } else if (tag instanceof FolderInfo) {
            if (v instanceof FolderIcon) {
                FolderIcon fi = (FolderIcon) v;
                handleFolderClick(fi);
            }
        } else if (v == mAllAppsButton) {
            if (isAllAppsVisible()) {
                showWorkspace(true);
            } else {
                onClickAllAppsButton(v);
            }
        }
    }
boolean startActivitySafely(View v, Intent intent, Object tag) {
        boolean success = false;
        try {
            success = startActivity(v, intent, tag);
        } catch (ActivityNotFoundException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
        }
        return success;
    }

從代碼來看殿托,產(chǎn)生點(diǎn)擊事件后,如果產(chǎn)生點(diǎn)擊事件的View的Tag是ShortcutInfo(即啟動(dòng)應(yīng)用的快捷方式)杠河,就會(huì)取得ShortcutInfo中保存的Intent(這個(gè)Intent指向我們要啟動(dòng)的App)碌尔,然后執(zhí)行startActivitySafely(v, intent, tag)方法浇辜,而startActivitySafely方法只是對startActivity方法的簡單封裝。

所以唾戚,Launcher響應(yīng)我們產(chǎn)生的點(diǎn)擊事件后柳洋,實(shí)際上就是啟動(dòng)一個(gè)新的Activity。

我們現(xiàn)在回想下App開發(fā)時(shí)叹坦,每個(gè)App都需要有一個(gè)“MainActivity”熊镣,這個(gè)Activity必須在AndroidManifest.xml文件中有以下配置:

<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

在配置AndroidManifest.xml文件時(shí),將Activity的Action指定為android.intent.action.MAIN募书,會(huì)使Activity在一個(gè)新的Task中啟動(dòng)(Task是一個(gè)Activity棧)绪囱。將category指定為android.intent.category.LAUNCHER,表示通過Intent啟動(dòng)此Activity時(shí)莹捡,只接受category為LAUNCHER的Intent鬼吵。

所以,Launcher將會(huì)通過App的快捷方式(ShortcutInfo)得到應(yīng)用的Intent篮赢,并通過這個(gè)Intent啟動(dòng)應(yīng)用的“MainActivity”齿椅,從而啟動(dòng)應(yīng)用。

所以我們研究的問題就從“App啟動(dòng)流程”變?yōu)椤癆ctivity啟動(dòng)流程”启泣。

Launcher通過Binder通知ActivityManagerService啟動(dòng)Activity

現(xiàn)在我們就進(jìn)入Launcher的startActivity方法里面探索“Activity啟動(dòng)流程”吧:

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

        try {
            // Only launch using the new animation if the shortcut has not opted out (this is a
            // private contract between launcher and may be ignored in the future).
            boolean useLaunchAnimation = (v != null) &&
                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
            UserHandle user = (UserHandle) intent.getParcelableExtra(ApplicationInfo.EXTRA_PROFILE);
            LauncherApps launcherApps = (LauncherApps)
                    this.getSystemService(Context.LAUNCHER_APPS_SERVICE);
            if (useLaunchAnimation) {
                ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
                        v.getMeasuredWidth(), v.getMeasuredHeight());
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
                    // Could be launching some bookkeeping activity
                    startActivity(intent, opts.toBundle());
                } else {
                    launcherApps.startMainActivity(intent.getComponent(), user,
                            intent.getSourceBounds(),
                            opts.toBundle());
                }
            } else {
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
                    startActivity(intent);
                } else {
                    launcherApps.startMainActivity(intent.getComponent(), user,
                            intent.getSourceBounds(), null);
                }
            }
            return true;
        } catch (SecurityException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Launcher does not have the permission to launch " + intent +
                    ". Make sure to create a MAIN intent-filter for the corresponding activity " +
                    "or use the exported attribute for this activity. "
                    + "tag="+ tag + " intent=" + intent, e);
        }
        return false;
    }

在這個(gè)方法中涣脚,首先,將Intent的Flag設(shè)為Intent.FLAG_ACTIVITY_NEW_TASK寥茫,使得Android系統(tǒng)將創(chuàng)建一個(gè)新的Task來放置即將被打開的新Activity(應(yīng)用的“MainActivity)遣蚀。然后獲取一個(gè)布爾值以用于后續(xù)判斷是否顯示啟動(dòng)App的動(dòng)畫。

然后獲取Intent中是否傳輸了Parcelable格式的用戶句柄纱耻,并通過Context.LAUNCHER_APPS_SERVICE獲取用于在多用戶情境下啟動(dòng)App的系統(tǒng)服務(wù)芭梯。

不管是否顯示啟動(dòng)App的動(dòng)畫,最終都會(huì)執(zhí)行startActivity(intent)或launcherApps.startMainActivity方法以啟動(dòng)應(yīng)用的“MainActivity”膝迎。而launcherApps.startMainActivity只在用戶句柄不為空且用戶句柄不等于當(dāng)前進(jìn)程句柄時(shí)(其他用戶的句柄)調(diào)用粥帚。

為什么用戶句柄會(huì)影響Activity的啟動(dòng)方式

這一點(diǎn)和Android的多用戶安全機(jī)制有關(guān)胰耗。

假設(shè)我們有用戶A和用戶B在使用同一臺(tái)手機(jī)限次,用戶A是無法訪問到用戶B的文件或者和用戶B的App通信的。所以假如我們現(xiàn)在是用戶A柴灯,但我們想啟動(dòng)用戶B的App卖漫,是無法直接實(shí)現(xiàn)的,因?yàn)橛脩鬉沒有權(quán)限訪問到用戶B的數(shù)據(jù)赠群,即使我們在代碼中強(qiáng)行把user id設(shè)為用戶B的user id羊始,交給內(nèi)核執(zhí)行時(shí)也會(huì)拋出SecurityException。因此我們需要取得用戶A的句柄(和用戶A相關(guān)的數(shù)據(jù))查描,將我們想啟動(dòng)的用戶B的App的Intent突委、用戶A的句柄交給內(nèi)核柏卤,讓擁有權(quán)限的Android系統(tǒng)服務(wù)(內(nèi)核態(tài)進(jìn)程)去訪問用戶B的數(shù)據(jù)并執(zhí)行相關(guān)的操作。

假如是單用戶情境匀油,就會(huì)相對簡單了缘缚。因?yàn)榇藭r(shí)只有一個(gè)用戶,而該用戶始終有權(quán)限直接訪問自己的數(shù)據(jù)敌蚜。

startActivity(intent)如何啟動(dòng)Activity

進(jìn)入Activity類后層層深入就可以看到最終調(diào)用的是startActivityForResult方法:

public void startActivityForResult(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());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received.  Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}

cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
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);
}
}
}

從代碼上看桥滨,如果Launcher有mParent Activity,就會(huì)執(zhí)行mParent.startActivityFromChild弛车;如果沒有齐媒,就會(huì)執(zhí)行mInstrumentation.execStartActivity。進(jìn)入mParent.startActivityFromChild方法會(huì)看到最終也是執(zhí)行了mInstrumentation.execStartActivity纷跛。執(zhí)行完成后喻括,會(huì)取得一個(gè)ActivityResult對象,用于給調(diào)用者Activity傳遞一些數(shù)據(jù)贫奠,最后在Activity切換時(shí)顯示Transition動(dòng)畫双妨。

這里有一點(diǎn)需要指出的是:這里的ParentActivity指的是類似TabActivity、ActivityGroup關(guān)系的嵌套Activity叮阅。之所以要強(qiáng)調(diào)parent和child刁品,是要避免混亂的Activity嵌套關(guān)系。

我們進(jìn)入Instrumentation類看看execStartActivity方法吧:

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) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i = 0; i < N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            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;
    }

首先浩姥,我們通過參數(shù)IBinder contextThread取得一個(gè)IApplicationThread類型的對象whoThread挑随,而contextThread是由mMainThread.getApplicationThread()取得的ApplicationThread對象,此時(shí)mMainThread指的就是Launcher應(yīng)用的主線程勒叠,所以whoThread指代的自然是Launcher的ApplicationThread兜挨。

因?yàn)锳ctivity的onProvideReferrer()方法默認(rèn)返回null,除非該方法被重寫眯分,而我們使用的Launcher并沒有重寫該方法拌汇,所以不用管referrer。

然后判斷是否有ActivityMonitor弊决,如果有噪舀,則即將要打開的Activity是否和ActivityMonitor中保存的IntentFilter匹配,如果匹配則增加ActivityMonitor的計(jì)數(shù)飘诗。大致是用于監(jiān)控符合匹配規(guī)則的Activity的數(shù)量的与倡。

最后調(diào)用ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);啟動(dòng)Activity,并檢查啟動(dòng)是否成功昆稿。換句話說纺座,最終負(fù)責(zé)啟動(dòng)Activity的是ActivityManager,前面得到的ApplicationThread也是在這里使用的溉潭。

那么ActivityManager净响、ApplicationThread少欺、ActivityThread都是什么呢?

ActivityManagerService通過Binder將Launcher切換到pause狀態(tài)

首先馋贤,調(diào)用ActivityManagerNative.getDefault()方法實(shí)際調(diào)用的是asInterface(IBinder obj)方法狈茉,也就意味著我們使用的其實(shí)是ActivityManagerProxy,而ActivityManagerProxy則是ActivityManagerService的代理掸掸,詳見下面的代碼:

static public IActivityManager getDefault() {
        return gDefault.get();
    }

    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
                (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

那么進(jìn)入ActivityManagerProxy:


    class ActivityManagerProxy implements IActivityManager
    {
        public ActivityManagerProxy(IBinder remote)
        {
            mRemote = remote;
        }

        public IBinder asBinder()
        {
            return mRemote;
        }

        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 {
            // 創(chuàng)建兩個(gè)Parcel對象氯庆,data用于傳輸啟動(dòng)Activity需要的數(shù)據(jù),reply用于獲取
            // 啟動(dòng)Activity操作執(zhí)行后系統(tǒng)返回的響應(yīng)
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            data.writeInterfaceToken(IActivityManager.descriptor);
            // caller 就是Launcher提供的ApplicationThread(也就是前面提到的whoThread)
            data.writeStrongBinder(caller != null ? caller.asBinder() : null);
            // 記錄啟動(dòng)新Activity的應(yīng)用的包名扰付,也就是Launcher的包名
            data.writeString(callingPackage);
            intent.writeToParcel(data, 0);
            data.writeString(resolvedType);
            // 將resultTo這個(gè)IBinder對象寫入data堤撵,實(shí)際寫入的就是前面的參數(shù)——IBinder token
            // 而這個(gè)token是什么,我們暫時(shí)不管羽莺,后面會(huì)給出解釋
            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;
        }
        ……省略余下代碼……
    }

將數(shù)據(jù)都寫入后实昨,就通過mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0)傳輸數(shù)據(jù)并得到響應(yīng)(寫入reply)。

前面已經(jīng)提到了盐固,ActivityManagerProxy是ActivityManagerService的代理荒给,那么調(diào)用mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0)實(shí)際上就是通過Binder建立Launcher所在的進(jìn)程與system_server進(jìn)程(Android Framework層的服務(wù)幾乎都由system_server進(jìn)程管理,因此ActivityManagerService運(yùn)行在system_server進(jìn)程中)的通信刁卜,并把我們寫入data的數(shù)據(jù)通過Binder傳遞給ActivityManagerService志电。

ActivityManagerService得到我們用Parcelable封裝的data后就會(huì)調(diào)用startActivity方法為Launcher啟動(dòng)Activity:

@Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
                                   Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                                   int startFlags, ProfilerInfo profilerInfo, Bundle options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, options,
                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 options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    }

    void enforceNotIsolatedCaller(String caller) {
        if (UserHandle.isIsolated(Binder.getCallingUid())) {
            throw new SecurityException("Isolated process not allowed to call " + caller);
        }
    }

enforceNotIsolatedCaller("startActivity");作安全性檢查,判斷當(dāng)前用戶是否允許啟動(dòng)Activity蛔趴,然后對之前傳入的userId進(jìn)行轉(zhuǎn)換和安全性檢查挑辆。最后調(diào)用mStackSupervisor.startActivityMayWait。這里的mStackSupervisor是ActivityStackSupervisor對象孝情,前面提到過鱼蝉,Task是以堆棧形式組織Activity的集合,而Task又由ActivityStack管理箫荡,ActivityStackSupervisor則是管理ActivityStack的類魁亦。

由于代碼太長,下面只截取部分關(guān)鍵代碼講解:

首先羔挡,通過下面代碼段調(diào)用PackageManagerService解析Intent(我們想要打開的App的用于啟動(dòng)MainActivity的Intent)洁奈,將解析的結(jié)果保存到ActivityInfo類型的對象里:

  // Collect information about the target of the Intent.
    ActivityInfo aInfo =
            resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);

    // Method - resolveActivity
    ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
                                 ProfilerInfo profilerInfo, int userId) {
        // Collect information about the target of the Intent.
        ActivityInfo aInfo;
        try {
            ResolveInfo rInfo =
                    AppGlobals.getPackageManager().resolveIntent(
                            intent, resolvedType,
                            PackageManager.MATCH_DEFAULT_ONLY
                                    | ActivityManagerService.STOCK_PM_FLAGS, userId);
            aInfo = rInfo != null ? rInfo.activityInfo : null;
        } catch (RemoteException e) {
            aInfo = null;
        }

        ……省略,大致是做一些安全性檢查和相關(guān)信息的設(shè)置……
        return aInfo;
    }

然后互斥鎖鎖住ActivityManagerService的實(shí)例mService婉弹,如果解析的ActivityInfo不為空睬魂,且ApplicationInfo有ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE標(biāo)記终吼,意味著調(diào)用者App是屬于heavy-weight process镀赌,如果現(xiàn)在有另一個(gè)heavy-weight process正在運(yùn)行,則需要進(jìn)行一些額外的處理际跪。然后進(jìn)入到startActivityLocked方法商佛。

這里通過注釋我們可以發(fā)現(xiàn)喉钢,若App有ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE標(biāo)記,App就可視為heavy-weight process良姆,該標(biāo)記可以在AndroidManifest.xml中設(shè)置肠虽,它是用于聲明App是否享受系統(tǒng)提供的Activity狀態(tài)保存/恢復(fù)功能的。但是似乎沒有App能成為heavy-weight process玛追,因?yàn)镻ackageParser的parseApplication方法并不會(huì)解析該標(biāo)簽税课。

在startActivityLocked方法中,得到Launcher(Activity)的ActivityRecord(Activity相關(guān)的信息)痊剖,并創(chuàng)建我們要啟動(dòng)的Activity的ActivityRecord韩玩,最終執(zhí)行startActivityUncheckedLocked繼續(xù)啟動(dòng)Activity:


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

    …………

    ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
            intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
            requestCode, componentSpecified, voiceSession != null, this, container, options);

    ……

    err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                                       startFlags, true, options, inTask);

進(jìn)入startActivityUncheckedLocked方法,完成一些簡單的初始化后陆馁,向下執(zhí)行到這段代碼:如果Intent里有Intent.FLAG_ACTIVITY_NEW_DOCUMENT標(biāo)記(在AndroidManifest.xml中聲明)找颓,且即將要打開的Activity的啟動(dòng)模式又被聲明為SingleInstance或SingleTask,那么Intent中攜帶的標(biāo)記和AndroidManifest中聲明的標(biāo)記出現(xiàn)沖突叮贩,而AndroidManifest的優(yōu)先級是高于Intent的击狮,因此將launchFlags的對應(yīng)位置為0。

然后是對launchFlags一系列的置位益老,目的是設(shè)置啟動(dòng)模式彪蓬。

if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
        (launchSingleInstance || launchSingleTask)) {
            // We have a conflict between the Intent and the Activity manifest, manifest wins.
            Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
                    "\"singleInstance\" or \"singleTask\"");
            launchFlags &=
            ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
        } else {
            switch (r.info.documentLaunchMode) {
                case ActivityInfo.DOCUMENT_LAUNCH_NONE:
                    break;
                case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
                    break;
                case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
                    break;
                case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
                    launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
                    break;
            }
        }
    }
    ……

            if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
        launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    }

    // If we are actually going to launch in to a new task, there are some cases where
    // we further want to do multiple task.
    if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        if (launchTaskBehind
                || r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) {
            launchFlags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
        }
    }

    ……

            if (inTask == null) {
        if (sourceRecord == null) {
            // This activity is not being started from another...  in this
            // case we -always- start a new task.
            if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) {
                Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
                        "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
            }
        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
            // The original activity who is starting us is running as a single
            // instance...  this new activity it is starting must go on its
            // own task.
            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
        } else if (launchSingleInstance || launchSingleTask) {
            // The activity being started is a single instance...  it always
            // gets launched into its own task.
            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
        }
    }

    ……

            // 因?yàn)槲覀兪菑腖auncher啟動(dòng)目的Activity,所以sourceRecord不為null捺萌,值為Launcher的ActivityRecord
            if (sourceRecord != null) {
        if (sourceRecord.finishing) {
            // 如果sourceRecord表示的Activity正在結(jié)束/被銷毀寞焙,那么我們不能把該Activity看作啟動(dòng)目的
            // Activity的源Activity,因?yàn)楹驮碅ctivity關(guān)聯(lián)的Task現(xiàn)在可能是空的(沒有Activity)或者
            // 也在結(jié)束/被銷毀的過程中互婿,所以我們不能盲目地把目的Activity放到該Task中捣郊。取而代之的是,
            // 我們會(huì)為它找到一個(gè)可用的Task慈参,但我們要先保存源Activity的Task的信息呛牲,使得我們在創(chuàng)建新
            // 的可用的Task時(shí)能用到里面的一些信息。
            if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                Slog.w(TAG, "startActivity called from finishing " + sourceRecord
                        + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
                newTaskInfo = sourceRecord.info;
                newTaskIntent = sourceRecord.task.intent;
            }
            sourceRecord = null;
            sourceStack = null;
        } else {
            sourceStack = sourceRecord.task.stack;
        }
    } else {
        sourceStack = null;
    }

    ……

            // 為目的Activity創(chuàng)建新的Task
            if (r.resultTo == null && inTask == null && !addingToTask
    && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;
        targetStack = computeStackFocus(r, newTask);
        targetStack.moveToFront("startingNewTask");

        if (reuseTask == null) {
            r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                    newTaskInfo != null ? newTaskInfo : r.info,
                    newTaskIntent != null ? newTaskIntent : intent,
                    voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
                    taskToAffiliate);
            if (DEBUG_TASKS) Slog.v(TAG_TASKS,
                    "Starting new activity " + r + " in new task " + r.task);
        } else {
            r.setTask(reuseTask, taskToAffiliate);
        }
        if (isLockTaskModeViolation(r.task)) {
            Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
            return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }
        if (!movedHome) {
            if ((launchFlags &
            (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
                // Caller wants to appear on home activity, so before starting
                // their own activity we will bring home to the front.
                r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
            }
        }
    }

完成上面一系列的處理后驮配,調(diào)用ActivityStack的startActivityLocked方法繼續(xù)執(zhí)行啟動(dòng)Activity需要的操作娘扩,targetStack是通過這行代碼targetStack = computeStackFocus(r, newTask)為用戶新建的ActivityStack:


        mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
                intent, r.getUriPermissionsLocked(), r.userId);

        if (sourceRecord != null && sourceRecord.isRecentsActivity()) {
            r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
        }
        if (newTask) {
            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
        }
        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
        targetStack.mLastPausedActivity = null;
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        if (!launchTaskBehind) {
            // Don't set focus on an activity that's going to the back.
            mService.setFocusedActivityLocked(r, "startedActivity");
        }
        return ActivityManager.START_SUCCESS;

進(jìn)入到ActivityStack的startActivityLocked方法,首先為目的Activity創(chuàng)建ProcessRecord壮锻,然后用WindowManager進(jìn)行一些切換窗口的操作琐旁,最后調(diào)用mStackSupervisor.resumeTopActivitiesLocked(this, r, options)。

……

        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;
            }
            ……調(diào)用WindowManager切換窗口……
        }

        ……

        if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }

進(jìn)入到resumeTopActivitiesLocked方法猜绣,調(diào)用resumeTopActivityLocked方法將所有ActivityStack(多個(gè)顯示設(shè)備灰殴,每個(gè)設(shè)備對應(yīng)一個(gè)ActivityStack)棧頂?shù)腁ctivity切換到resume狀態(tài)(生命周期的onResume),而resumeTopActivityLocked方法先避免遞歸調(diào)用掰邢,然后調(diào)用ActivityStack的resumeTopActivityInnerLocked方法牺陶。

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
                Bundle targetOptions) {
            if (targetStack == null) {
                targetStack = mFocusedStack;
            }
            // Do targetStack first.
            boolean result = false;
            if (isFrontStack(targetStack)) {
                result = targetStack.resumeTopActivityLocked(target, targetOptions);
            }

            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
                final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                    final ActivityStack stack = stacks.get(stackNdx);
                    if (stack == targetStack) {
                        // Already started above.
                        continue;
                    }
                    if (isFrontStack(stack)) {
                        stack.resumeTopActivityLocked(null);
                    }
                }
            }
            return result;
        }

下面這段代碼主要就是做一些前期的檢查伟阔,避免做多余的工作浪費(fèi)時(shí)間,并且確保目標(biāo)Activity處于正確的“狀態(tài)”掰伸,使得我們后面能把它切換到resume狀態(tài)并顯示皱炉。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {

        // 判斷ActivityManagerService是否已經(jīng)啟動(dòng)完畢
        if (!mService.mBooting && !mService.mBooted) {
            // Not ready yet!
            return false;
        }

        // 獲取parentActivity,如果parentActivity還未處于resume狀態(tài)狮鸭,則不能將stack棧頂?shù)腁ctivity切換為resume狀態(tài)(Activity的嵌套關(guān)系不能弄亂)
        ActivityRecord parent = mActivityContainer.mParentActivity;
        if ((parent != null && parent.state != ActivityState.RESUMED) ||
                !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;
        }

        // 如果有正在初始化的Activity沒有位于ActivityStack的棧頂合搅,且正在執(zhí)行window的啟動(dòng)和顯示,
        // 則要將window相關(guān)的操作取消歧蕉。因?yàn)檫@類Activity的窗口有可能被孤立历筝,那么它們有可能永遠(yuǎn)也不會(huì)進(jìn)入resume狀態(tài)
        cancelInitializingActivities();

        // 取得當(dāng)前ActivityStack棧頂Activity的ActivityRecord
        final ActivityRecord next = topRunningActivityLocked(null);

        // 記住我們怎樣處理pause/resume狀態(tài)切換,并確保無論何時(shí)結(jié)束處理都會(huì)重置狀態(tài)
        final boolean userLeaving = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;

        final TaskRecord prevTask = prev != null ? prev.task : null;
        if (next == null) {
            // next為null表示當(dāng)前ActivityStack沒有要顯示的Activity
            final String reason = "noMoreActivities";
            if (!mFullscreen) {
                // 如果當(dāng)前ActivityStack不是全屏的廊谓,將焦點(diǎn)切換到下一個(gè)擁有Activity的可見ActivityStack中
                final ActivityStack stack = getNextVisibleStackLocked();
                if (adjustFocusToNextVisibleStackLocked(stack, reason)) {
                    return mStackSupervisor.resumeTopActivitiesLocked(stack, prev, null);
                }
            }
            // 如果ActivityStack是全屏的梳猪,卻沒有可以顯示的Activity,那么就顯示桌面(Launcher)
            ActivityOptions.abort(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: No more activities go home");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
                    HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
            return isOnHomeDisplay() &&
                    mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
        }

        next.delayedResume = false;

        // 如果當(dāng)前棧頂Activity處于resume狀態(tài)蒸痹,且就是我們要打開的Activity春弥,則直接結(jié)束
        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                mStackSupervisor.allResumedActivitiesComplete()) {
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            mWindowManager.executeAppTransition();
            mNoAnimActivities.clear();
            ActivityOptions.abort(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Top activity resumed " + next);
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

        // 對prevActivity(Launcher)所在的Task進(jìn)行一些判斷,如果prevTask和nextTask相同叠荠,那么直接將
        // prevTask直接設(shè)為棧頂Task匿沛;如果prevTask不是當(dāng)前ActivityStack棧頂?shù)腡ask,那么它后面的Task
        // 都應(yīng)該放到Launcher的Task后面榛鼎;后面則是有關(guān)是否為桌面的判斷和處理了逃呼。
        final TaskRecord nextTask = next.task;
        if (prevTask != null && prevTask.stack == this &&
                prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
            if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
            if (prevTask == nextTask) {
                prevTask.setFrontOfTask();
            } else if (prevTask != topTask()) {
                // This task is going away but it was supposed to return to the home stack.
                // Now the task above it has to return to the home task instead.
                final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
                mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
            } else if (!isOnHomeDisplay()) {
                return false;
            } else if (!isHomeStack()){
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Launching home next");
                final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
                        HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
                return isOnHomeDisplay() &&
                        mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished");
            }
        }

        // 如果ActivityManagerService處于休眠狀態(tài),而且此時(shí)沒有Activity處于resume狀態(tài)
        // 且棧頂Activity處于pause狀態(tài)者娱,則中斷調(diào)度
        if (mService.isSleepingOrShuttingDown()
                && mLastPausedActivity == next
                && mStackSupervisor.allPausedActivitiesComplete()) {
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            mWindowManager.executeAppTransition();
            mNoAnimActivities.clear();
            ActivityOptions.abort(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Going to sleep and all paused");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

        // Make sure that the user who owns this activity is started.  If not,
        // we will just leave it as is because someone should be bringing
        // another user's activities to the top of the stack.
        if (mService.mStartedUsers.get(next.userId) == null) {
            Slog.w(TAG, "Skipping resume of top activity " + next
                    + ": user " + next.userId + " is stopped");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

        // 確保我們要啟動(dòng)的Activity沒有處于stop隊(duì)列抡笼、休眠隊(duì)列、等待變?yōu)榭梢婈?duì)列中
        mStackSupervisor.mStoppingActivities.remove(next);
        mStackSupervisor.mGoingToSleepActivities.remove(next);
        next.sleeping = false;
        mStackSupervisor.mWaitingVisibleActivities.remove(next);

        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

        // If we are currently pausing an activity, then don't do anything
        // until that is done.
        if (!mStackSupervisor.allPausedActivitiesComplete()) {
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                    "resumeTopActivityLocked: Skip resume: some activity pausing.");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

        ……待續(xù)……
    }

后面做的工作就是:將Launcher切換到pause狀態(tài)黄鳍,用WindowManager將Launcher的窗口隱藏⊥埔觯現(xiàn)在只完成了Activity相關(guān)的預(yù)處理工作,目標(biāo)應(yīng)用的進(jìn)程和主線程還沒有創(chuàng)建框沟,因此后面會(huì)進(jìn)入if的false分支調(diào)用mStackSupervisor.startSpecificActivityLocked方法創(chuàng)建應(yīng)用進(jìn)程藏古;如果目標(biāo)Activity的進(jìn)程和主線程已經(jīng)創(chuàng)建,則進(jìn)入if語句的true分支直接將目標(biāo)Activity切換到resume狀態(tài)忍燥,并顯示目標(biāo)Activity的窗口拧晕。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {

            ……續(xù)上……

            // 步入setLaunchSource方法后可以知道,該方法實(shí)際是通過PowerManager的setWorkSource方法
            // 設(shè)置WakeLock梅垄,使得在執(zhí)行后面的工作時(shí)系統(tǒng)不會(huì)進(jìn)入休眠狀態(tài)
            mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);

            // 現(xiàn)在開始將當(dāng)前Activity切換到pause狀態(tài)厂捞,使得棧頂Activity可以切換到resume狀態(tài)
            boolean dontWaitForPause = (next.info.flags& ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
            // 將后臺(tái)ActivityStack的Activity切換到pause狀態(tài)
            boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
            // 將當(dāng)前ActivityStack中正在顯示Activity切換到pause狀態(tài)
            if (mResumedActivity != null) {
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Pausing " + mResumedActivity);
                pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
            }
            if (pausing) {
                if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
                        "resumeTopActivityLocked: Skip resume: need to start pausing");
                // At this point we want to put the upcoming activity's process
                // at the top of the LRU list, since we know we will be needing it
                // very soon and it would be a waste to let it get killed if it
                // happens to be sitting towards the end.
                if (next.app != null && next.app.thread != null) {
                    mService.updateLruProcessLocked(next.app, true, null);
                }
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return true;
            }

            ……

            ActivityStack lastStack = mStackSupervisor.getLastStack();
            if (next.app != null && next.app.thread != null) {
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next);

                // 目標(biāo)Activity已經(jīng)可見
                mWindowManager.setAppVisibility(next.appToken, true);

                next.startLaunchTickingLocked();

                ActivityRecord lastResumedActivity =
                        lastStack == null ? null :lastStack.mResumedActivity;
                ActivityState lastState = next.state;

                mService.updateCpuStats();

                // 目標(biāo)Activity切換到resume狀態(tài)
                if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)");
                next.state = ActivityState.RESUMED;
                mResumedActivity = next;
                next.task.touchActiveTime();
                mRecentTasks.addLocked(next.task);
                mService.updateLruProcessLocked(next.app, true, null);
                updateLRUListLocked(next);
                mService.updateOomAdjLocked();

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

ActivityManagerService為即將打開的應(yīng)用創(chuàng)建進(jìn)程

進(jìn)入ActivityStackSupervisor類的startSpecificActivityLocked方法,首先通過應(yīng)用的包名和uid取得ProcessRecord,判斷ProcessRecord是否被創(chuàng)建蔫敲,若創(chuàng)建饲嗽,則直接啟動(dòng)Activity炭玫;否則調(diào)用ActivityManagerService的startProcessLocked方法創(chuàng)建應(yīng)用進(jìn)程奈嘿。

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

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

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

進(jìn)入到ActivityManagerService的startProcessLocked方法,首先判斷要?jiǎng)?chuàng)建的進(jìn)程是否為隔離進(jìn)程(isolated)吞加,由于不是隔離進(jìn)程裙犹,則直接進(jìn)入true分支,然后再次獲取ProcessRecord衔憨。如果Intent有FLAG_FROM_BACKGROUND標(biāo)記叶圃,則在后臺(tái)啟動(dòng)badProcess;否則清空進(jìn)程的崩潰次數(shù)践图,并將進(jìn)程移出badProcess集合(如果進(jìn)程存在的話)掺冠。然后調(diào)用newProcessRecordLocked方法創(chuàng)建ProcessRecord,最后再調(diào)用另一個(gè)重載的startProcessLocked方法創(chuàng)建進(jìn)程码党。

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

                if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
                    // If we are in the background, then check to see if this process
                    // is bad.  If so, we will just silently fail.
                    if (mBadProcesses.get(info.processName, info.uid) != null) {
                        if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
                                + "/" + info.processName);
                        return null;
                    }
                } else {
                    // When the user is explicitly starting a process, then clear its
                    // crash count so that we won't make it bad until they see at
                    // least one crash dialog again, and make the process good again
                    // if it had been bad.
                    if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
                            + "/" + info.processName);
                    mProcessCrashTimes.remove(info.processName, info.uid);
                    if (mBadProcesses.get(info.processName, info.uid) != null) {
                        EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                                UserHandle.getUserId(info.uid), info.uid,
                                info.processName);
                        mBadProcesses.remove(info.processName, info.uid);
                        if (app != null) {
                            app.bad = false;
                        }
                    }
                }
            } else {
                // If this is an isolated process, it can't re-use an existing process.
                app = null;
            }

            ……

            String hostingNameStr = hostingName != null
                    ? hostingName.flattenToShortString() : 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");
            }

            // 如果系統(tǒng)還沒啟動(dòng)完畢德崭,則等待系統(tǒng)啟動(dòng)完畢后再啟動(dòng)進(jìn)程
            if (!mProcessesReady
                    && !isAllowedWhileBooting(info)
                    && !allowWhileBooting) {
                if (!mProcessesOnHold.contains(app)) {
                    mProcessesOnHold.add(app);
                }
                if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
                        "System not ready, putting on hold: " + app);
                checkTime(startTime, "startProcess: returning with proc on hold");
                return app;
            }

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

調(diào)用newProcessRecordLocked方法根據(jù)ApplicationInfo創(chuàng)建ProcessRecord,并讓ActivityManagerService管理該P(yáng)rocessRecord揖盘,過程比較簡單就不貼代碼了眉厨,直接看startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs)方法吧。

進(jìn)入startProcessLocked方法兽狭,首先將app的pid初始化憾股,若進(jìn)程已經(jīng)存在(pid不等于0),則先清除超時(shí)信息箕慧,再講pid置為0服球,然后確保app不在mProcessesOnHold列表中。

mProcessesOnHold代表在系統(tǒng)啟動(dòng)完畢前嘗試啟動(dòng)的進(jìn)程颠焦,這部分進(jìn)程會(huì)先在該列表中待著有咨,等到系統(tǒng)啟動(dòng)完畢再啟動(dòng)。

完成一系列的初始化操作后蒸健,調(diào)用Process.start方法創(chuàng)建應(yīng)用進(jìn)程座享,然后以進(jìn)程pid為key,app(ProcessRecord)為value存儲(chǔ)到ActivityManagerService的mPidsSelfLocked中似忧。

Process.start方法創(chuàng)建應(yīng)用進(jìn)程是通過Zygote進(jìn)程完成的渣叛,設(shè)置好參數(shù)和創(chuàng)建選項(xiàng)后通過zygoteState.writer將數(shù)據(jù)交給Zygote進(jìn)程,它會(huì)調(diào)用fork()創(chuàng)建進(jìn)程盯捌。在這里要注意一個(gè)地方淳衙,我們通過if (entryPoint == null) entryPoint = "android.app.ActivityThread"這行代碼設(shè)置了進(jìn)程創(chuàng)建完成后的入口點(diǎn)(Process.start的參數(shù)注釋),因此Zygote進(jìn)程完成了進(jìn)程創(chuàng)建的操作后就會(huì)執(zhí)行ActivityThread的main()方法。

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

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

進(jìn)入到ActivityThread的main方法箫攀,首先進(jìn)行一些初始化(包括參數(shù)設(shè)置肠牲、性能安全監(jiān)控之類的),然后初始化Looper(Looper靴跛、Handler消息機(jī)制)缀雳,創(chuàng)建ActivityThread,存儲(chǔ)線程的Handler梢睛,最后啟動(dòng)Looper監(jiān)聽消息肥印。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市绝葡,隨后出現(xiàn)的幾起案子深碱,更是在濱河造成了極大的恐慌,老刑警劉巖藏畅,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敷硅,死亡現(xiàn)場離奇詭異,居然都是意外死亡愉阎,警方通過查閱死者的電腦和手機(jī)绞蹦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诫硕,“玉大人坦辟,你說我怎么就攤上這事≌掳欤” “怎么了锉走?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長藕届。 經(jīng)常有香客問我挪蹭,道長,這世上最難降的妖魔是什么休偶? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任梁厉,我火速辦了婚禮,結(jié)果婚禮上踏兜,老公的妹妹穿的比我還像新娘词顾。我一直安慰自己,他們只是感情好碱妆,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布肉盹。 她就那樣靜靜地躺著,像睡著了一般疹尾。 火紅的嫁衣襯著肌膚如雪上忍。 梳的紋絲不亂的頭發(fā)上骤肛,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機(jī)與錄音窍蓝,去河邊找鬼腋颠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛吓笙,可吹牛的內(nèi)容都是我干的淑玫。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼观蓄,長吁一口氣:“原來是場噩夢啊……” “哼混移!你這毒婦竟也來了祠墅?” 一聲冷哼從身側(cè)響起侮穿,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎毁嗦,沒想到半個(gè)月后亲茅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡狗准,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年克锣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腔长。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡袭祟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捞附,到底是詐尸還是另有隱情巾乳,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布鸟召,位于F島的核電站胆绊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏欧募。R本人自食惡果不足惜压状,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望跟继。 院中可真熱鬧种冬,春花似錦、人聲如沸舔糖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽剩盒。三九已至谷婆,卻和暖如春慨蛙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纪挎。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工期贫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人异袄。 一個(gè)月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓通砍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親烤蜕。 傳聞我的和親對象是個(gè)殘疾皇子封孙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,499評論 25 707
  • 簡介: 在android系統(tǒng)中,Home界面也就是Launcher的界面讽营,Launcher它本身也是一個(gè)應(yīng)用程序虎忌,...
    Memebox閱讀 2,438評論 4 19
  • 生命中總有些人是匆匆過客,我們在人生的長河中決定不了太多卻也決定不少橱鹏,這來來回回的緣分在時(shí)間的沖刷下變成了泡沫膜蠢,直...
    墨小凝閱讀 344評論 2 4
  • 生命是一條長河,在小溪里歇歇腳再啟航莉兰。
    slowDownEmma閱讀 112評論 0 0
  • 1.有個(gè)女的問一個(gè)男的挑围,“我好看嗎?” 男的說:你現(xiàn)在就像蒙娜麗莎的妹妹 女的說:是嗎糖荒,她妹妹是誰吧颊蕖? 男的說:珍...
    維納斯的丘比特閱讀 217評論 0 1