前言
由上文可知凤壁,在啟動(dòng)了應(yīng)用程序的進(jìn)程后,接下來(lái)跪另,就該啟動(dòng)應(yīng)用程序本身了拧抖,你已經(jīng)知道AMS(Activity Manager Service)是專(zhuān)門(mén)管理Activity的服務(wù),而啟動(dòng)應(yīng)用程序免绿,本質(zhì)上來(lái)說(shuō)唧席,就是啟動(dòng)應(yīng)用程序的第一個(gè)Activity,這個(gè)Activity被稱(chēng)為根Activity嘲驾,所以AMS在本文中依然是主角淌哟。
本文將分為三個(gè)部分介紹,Launcher
請(qǐng)求AMS辽故,AMS到ApplicationThread
的調(diào)用和ActivityThread
啟動(dòng) Activity徒仓。
Launcher
請(qǐng)求AMS過(guò)程
Launcher
是一個(gè)進(jìn)程,他在android系統(tǒng)啟動(dòng)后會(huì)發(fā)揮作用——將應(yīng)用程序的快捷圖標(biāo)放到桌面誊垢,就是我們手機(jī)里面的app圖標(biāo)蓬衡,這些圖標(biāo)就是每一個(gè)應(yīng)用程序的入口,也是根Activity的入口彤枢,所以狰晚,要想啟動(dòng)app,就需要管理圖標(biāo)的Launcher
去請(qǐng)求管理Activity的AMS
時(shí)序圖如下(mermaid畫(huà)圖更好看哈哈哈)
當(dāng)點(diǎn)擊桌面圖標(biāo)時(shí)缴啡,會(huì)啟動(dòng)Launcher``的startActivitySafely
方法壁晒,如下
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
...
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
...
try {
if (Utilities.ATLEAST_MARSHMALLOW
...
} else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity
startActivity(intent, optsBundle);//10
} else {
...
return false;
}
在第3行代碼處將Flag設(shè)置為FLAG_ACTIVITY_NEW_TASK
,表示啟動(dòng)一個(gè)新的任務(wù)棧业栅,如果你了解Activity的四種啟動(dòng)模式的話(huà)秒咐,應(yīng)該不會(huì)陌生他的作用捡鱼,簡(jiǎn)單說(shuō)蝉衣,就是每個(gè)應(yīng)用程序都有一個(gè)這樣的棧彪腔,當(dāng)打開(kāi)里面的新的Activity的時(shí)候柠贤,就壓入這么一個(gè)Activity,當(dāng)回退的時(shí)候雷滋,就彈出不撑,不過(guò)規(guī)則沒(méi)那么簡(jiǎn)單,有四種模式晤斩,有興趣可以自己搜搜看焕檬。
第10行代碼啟動(dòng)了Activity,而這個(gè)方法在Activity.java
中實(shí)現(xiàn)澳泵。
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
startActivity
沒(méi)有什么內(nèi)容实愚,就是調(diào)用了startActivityForResult
,第二個(gè)參數(shù)名為requestCode
兔辅,這里是-1腊敲,表示Launcher
不需要知道Activity的啟動(dòng)結(jié)果。
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
...
這里進(jìn)入startActivityForResult
后维苔,由于根Activity沒(méi)有啟動(dòng)碰辅,也就是mParent==null
,將會(huì)讓Instrumentation
執(zhí)行execStartActivity
方法蕉鸳,Instrumentation
的作用是監(jiān)控應(yīng)用程序與系統(tǒng)的交互。
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.getService()//9
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target, requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
在第9行處忍法,調(diào)用ActivityManager
的getService
方法潮尝,獲取到AMS的代理對(duì)象,然后調(diào)用該對(duì)象的startActivity
方法饿序,注意這里我們已經(jīng)獲得了AMS勉失。
然后我們看getService
做了什么
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
就調(diào)用了一個(gè)IActivityManagerSingleton
的get()方法
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);//6
return am;
}
};
這是一個(gè)單例,在第6行中創(chuàng)建了IActivityManager
并返回原探,這段代碼比較陌生乱凿,使用的是AIDL,不過(guò)我們不必深究了咽弦。
小結(jié)1
總而言之徒蟆,這一節(jié)中所有的工作都是為了獲得AMS,將代碼邏輯放到AMS中型型,中間經(jīng)歷了多個(gè)startAcitvity
段审,都是為了判定或者架構(gòu)需要,非衬炙猓瑣碎寺枉,我認(rèn)為了解即可
AMS到Application Thread的調(diào)用過(guò)程
現(xiàn)在我們已經(jīng)來(lái)到了熟悉的AMS抑淫,看看他是如何工作的吧
承接上一節(jié)Launcher
請(qǐng)求AMS過(guò)程的最后一步,首先調(diào)用startActivity
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
可以看到姥闪,這里返回的是startActivityAsUser
方法始苇,就開(kāi)始了我們這一節(jié)的內(nèi)容。
注意到startActivityAsUser
比起startActivity
多了最后一個(gè)參數(shù)筐喳,UserHandle.getCallingUserId
催式,這個(gè)是AMS用來(lái)確定調(diào)用這的權(quán)限的
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null,
"startActivityAsUser");
}
第5行出就是在檢查調(diào)用者權(quán)限,如果沒(méi)有沒(méi)有權(quán)限就會(huì)拋出SecurityException
異常疏唾。
然后就是調(diào)用startActivityMayWait
方法蓄氧,這個(gè)方法在ActivityStarter
中,比起startActivityAsUser
槐脏,又多了幾個(gè)參數(shù)喉童,其中最后一個(gè)參數(shù)"startActivityAsUser"表示啟動(dòng)的理由,是從這個(gè)方法中調(diào)用的顿天。
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult,
Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask, String reason) {
// Refuse possible leaked file descriptors
...
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask, reason);
...
return res;
ActivityStarter
是一個(gè)加載Activity的控制類(lèi)堂氯,回去搜集很多的Intent或者Flags用來(lái)生成Activity,這段代碼的10行調(diào)用了startActivityLocked
方法(我真的想吐槽牌废,調(diào)來(lái)調(diào)去的咽白,很容易暈)
int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask, String reason) {
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
mLastStartReason = reason;
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord[0] = null;
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,//17
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
container, inTask);
if (outActivity != null) {
// mLastStartActivityRecord[0] is set in the call to startActivity above.
outActivity[0] = mLastStartActivityRecord[0];
}
return mLastStartActivityResult;
}
沒(méi)什么好看的,注意到17行處又調(diào)用了startActivity
方法鸟缕,方法如下
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
// Pull the optional Ephemeral Installer-only bundle out of the options early.
final Bundle verificationBundle
= options != null ? options.popAppVerificationBundle() : null;
ProcessRecord callerApp = null;
if (caller != null) { //14
callerApp = mService.getRecordForAppLocked(caller);//15
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
err = ActivityManager.START_PERMISSION_DENIED;
}
}
...
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, container, options, sourceRecord);
if (outActivity != null) {
outActivity[0] = r; //32
}
...
doPendingActivityLaunchesLocked(false);
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
第14行處判定caller是否為null晶框,這個(gè)caller是從前面?zhèn)鬟^(guò)來(lái)的,一直都是第一個(gè)參數(shù)懂从,代表的是Launcher
所在的應(yīng)用程序的進(jìn)程的ApplicationThread
對(duì)象授段,如果為null,那么執(zhí)行15行處的getRecordForAppLocked
方法番甩,得到一個(gè)代替Launcher
進(jìn)程的callerApp對(duì)象侵贵。
ActivityRecord
表示記錄一個(gè)Activity信息的對(duì)象,就像入學(xué)一樣缘薛,在新生報(bào)到前窍育,學(xué)校就應(yīng)該準(zhǔn)備好檔案,寢室宴胧,班級(jí)等等工作漱抓。
在27行處就新建了這個(gè)對(duì)象,然后在32行處將其放在outActivity
數(shù)組的第一個(gè)恕齐,我想你應(yīng)該猜到了辽旋,那這個(gè)數(shù)組的其他位置是什么呢?當(dāng)然是除了根Activity之外的其他Activity的記錄信息了。
最后的36行补胚,還是返回了startActivity
方法
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
int result = START_CANCELED;
try {
mService.mWindowManager.deferSurfaceLayout();
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
...
postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord,
mTargetStack);
return result;
}
這個(gè)方法沒(méi)什么好看的码耐,就是調(diào)用了一個(gè)startActivityUnchecked
方法
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
...
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask//6
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
result = setTaskFromReuseOrCreateNewTask( //9
taskToAffiliate, preferredLaunchStackId, topStack);
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
} else {
setTaskToCurrentTopOrCreateNewTask();
}
...
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
...
} else {
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,//30
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
}
startActivityUnchecked
方法主要處理與棧相關(guān)的邏輯,還記得嗎溶其?每一個(gè)應(yīng)用程序都有一個(gè)任務(wù)棧骚腥,Activity
的四種啟動(dòng)模式就在這里,在一開(kāi)始的類(lèi)startActivitySafely
中瓶逃,我們將Intent的Flag設(shè)置為FLAG_ACTIVITY_NEW_TASK
束铭,這樣子,就滿(mǎn)足了第6行代碼處的if判斷厢绝,在第9行處契沫,就會(huì)創(chuàng)建新的TaskRecord
。
現(xiàn)在所有東西準(zhǔn)備齊全昔汉,在第30行處調(diào)用resumeFocusedStackTopActivityLocked
方法懈万,我們?nèi)タ纯窗?/p>
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();//6
if (r == null || r.state != RESUMED) {//7
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.state == RESUMED) {
// Kick off any lingering app transitions form the MoveTaskToFront operation.
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
在第6行處調(diào)用的topRunningActivityLocked
方法可以獲取要啟動(dòng)的Acitvity所在棧的棧頂的不是處于停止?fàn)顟B(tài)的ActivityRecord
(修飾詞很多,慢慢讀)靶病,第7行会通,如果為null,或者要啟動(dòng)的Acitvity狀態(tài)不是RESUMED娄周,就會(huì)調(diào)用resumeTopActivityUncheckedLocked
方法涕侈,當(dāng)然,對(duì)于即將啟動(dòng)的Activity煤辨,滿(mǎn)足上述條件裳涛,進(jìn)入resumeTopActivityUncheckedLocked
方法。
oolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
mStackSupervisor.checkReadyForSleepLocked();
return result;
沒(méi)有什么東西众辨,進(jìn)入resumeTopActivityInnerLocked
方法
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
mStackSupervisor.startSpecificActivityLocked(next, true, true);
...
}
代碼很多端三,但是我們不關(guān)心,只看調(diào)用的startSpecificActivityLocked
方法
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,//4
r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
if (app != null && app.thread != null) {//9
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);//16
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
在第4行處泻轰,獲得即將啟動(dòng)的Activity所在的應(yīng)用程序進(jìn)程技肩,也就是我們?cè)谏掀恼轮械闹鹘乔夜欤诘?行處判斷如果這個(gè)進(jìn)程已經(jīng)運(yùn)行了浮声,就會(huì)調(diào)用了16行處的realStartActivityLocked
方法。
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
...
return true;
在這里的app.thread就是ActivityThread
的內(nèi)部類(lèi)旋奢,app表示傳入這個(gè)應(yīng)用程序的進(jìn)程泳挥。
所以這段代碼的意思就是,在應(yīng)用程序的進(jìn)程中至朗,也就是ActivityThread中屉符,啟動(dòng)Activity。
小結(jié)2
上面代碼的核心,就是要把邏輯從AMS中移動(dòng)到應(yīng)用程序的進(jìn)程當(dāng)中矗钟,然后準(zhǔn)備在應(yīng)用程序的進(jìn)程中啟動(dòng)Activity唆香。
ActivityThread啟動(dòng)Acitvity的過(guò)程
歷經(jīng)千山萬(wàn)水,我們總算是要啟動(dòng)Activity了(我好餓啊……)吨艇,下次再繼續(xù)嘻嘻