轉(zhuǎn)自 http://cheelok.com/aosp/54/
啟動(dòng)一個(gè)App的流程:
Android系統(tǒng)桌面->點(diǎn)擊應(yīng)用圖標(biāo)->啟動(dòng)App
從這個(gè)過程來看奈泪,只要弄明白:
- Android系統(tǒng)桌面是什么
- 點(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)聽消息肥印。