在Android系統(tǒng)中,有兩種操作會引發(fā)Activity的啟動:
??第一種:用戶點擊應用程序圖標時,Launcher會為我們啟動應用程序的主Activity;
??第二種:應用程序的默認Activity啟動起來后,它又可以在內部通過調用startActvity接口啟動新的Activity;
依此類推,每一個Activity都可以在內部啟動新的Activity。通過這種連鎖反應,按需啟動Activity,從而完成應用程序的功能。
本文主要講點擊應用圖標,啟動應用程序的過程。
在手機屏幕中點擊應用程序圖標的情景就會引發(fā)Android應用程序中的默認Activity的啟動,從而把應用程序啟動起來。這種啟動方式的特點:會啟動一個新的進程來加載相應的Activity。
這里,我們來研究下Android應用程序的啟動過程,即App的啟動流程。我們這里就不說lancher2包中的Launcher了,好像已經過時了,我們直接查看lancher3包中的Launcher。
1、從手機屏幕點擊應用圖標開始
我們來看下點擊應用圖標會發(fā)生什么事?
public final class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
View.OnTouchListener {
通過分析源碼我們可以知道,我們得Launcher就是一個Activity,而且還是先了幾個點擊事件的接口,我們去看一下Launcher里面的onClick方法。
/**
*
* @param v 表示點擊的應用程序的圖標
*/
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;
}
if (v instanceof Workspace) {
if (mWorkspace.isInOverviewMode()) {
showWorkspace(true);
}
return;
}
if (v instanceof CellLayout) {
if (mWorkspace.isInOverviewMode()) {
showWorkspace(mWorkspace.indexOfChild(v), true);
}
}
Object tag = v.getTag(); //獲取圖標的應用標識
if (tag instanceof ShortcutInfo) {
onClickAppShortcut(v);
} else if (tag instanceof FolderInfo) {
if (v instanceof FolderIcon) {
onClickFolderIcon(v);
}
} else if (v == mAllAppsButton) {
onClickAllAppsButton(v);
} else if (tag instanceof AppInfo) { //說明是應用程序
startAppShortcutOrInfoActivity(v);
} else if (tag instanceof LauncherAppWidgetInfo) {
if (v instanceof PendingAppWidgetHostView) {
onClickPendingWidget((PendingAppWidgetHostView) v);
}
}
}
當點擊Launcher上面的應用圖標的時候,就會觸發(fā)onClick方法的執(zhí)行,然后根據(jù)傳入?yún)?shù)(View v)的v.getTag()方法得到被點擊應用圖標的tag,然后判斷tag的類型,我們從代碼邏輯上可以看出AppInfo是我們的應用程序的類型。所以直接調用了Launcher的startAppShortcutOrInfoActivity(v)方法。
2、然后我們看Launcher的startAppShortcutOrInfoActivity(v)方法
@Thunk void startAppShortcutOrInfoActivity(View v) {
Object tag = v.getTag();
final ShortcutInfo shortcut;
final Intent intent;
if (tag instanceof ShortcutInfo) {
shortcut = (ShortcutInfo) tag;
intent = shortcut.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()));
} else if (tag instanceof AppInfo) {
shortcut = null;
intent = ((AppInfo) tag).intent; //獲取v中的意圖,有了意圖我們就可以啟動Activity了
} else {
throw new IllegalArgumentException("Input must be a Shortcut or AppInfo");
}
boolean success = startActivitySafely(v, intent, tag); //這里就是啟動入口
mStats.recordLaunch(v, intent, shortcut);
if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
mWaitingForResume.setStayPressed(true);
}
}
從上面的代碼我們可以看出,launcher3和launcher2中的啟動有一點不一樣,就是launcher3中有了AppInfo這個類,launcher2中是沒有的,這也更方便了我們的程序啟動。最后還是同樣調用了Launcher中的startActivitySafely(v, intent, tag);方法。
3、然后我們看Launcher的startActivitySafely(v, intent, tag)方法
public boolean startActivitySafely(View v, Intent intent, Object tag) {
boolean success = false;
if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
return false;
}
try {
success = startActivity(v, intent, tag); //調用Launcher的 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;
}
3、然后我們看Launcher的 startActivity(v, intent, tag);
private boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //并且傳入?yún)?shù)intent,對Intent添加flag,F(xiàn)LAG_ACTIVITY_NEW_TASK
...........
代碼較多省略了許多
startActivity(intent, optsBundle); //最后就調用了Activity的startActivity(Intent intent, @Nullable Bundle)方法 options)
...........
return false;
}
這里的intent包含的信息為:action = "android.intent.action.Main",category="android.intent.category.LAUNCHER", cmp="shy.luo.activity/.MainActivity",表示它要啟動的Activity為shy.luo.activity.MainActivity。
Intent.FLAG_ACTIVITY_NEW_TASK表示要在一個新的Task中啟動這個Activity,注意,Task是Android系統(tǒng)中的概念,它不同于進程Process的概念。
簡單地說,一個Task是一系列Activity的集合,這個集合是以堆棧的形式來組織的,遵循后進先出的原則。
稍微擴展一下:
(1)我們知道,一個應用程序可以有多個Activity,每個Activity是同級別的。那么在啟動程序時,最先啟動哪個Activity呢?
(2)有些程序可能需要顯示在程 序列表里,有些不需要。怎么定義呢?
android.intent.action.MAIN決定應用程序最先啟動的Activity ;
android.intent.category.LAUNCHER決定應用程序是否顯示在程序列表里。
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Main和LAUNCHER同時設定才有意義,如果有多個同級的Activity都有過濾器,則只有最前面的Activity的 <action android:name="android.intent.action.MAIN" /> 有 效,啟動該程序時,執(zhí)行的是該Activity。且在程序列表中有多個圖標,這些Activity都在程序列表中顯示,該Application有多個入 口,執(zhí)行不同的Activity,但是整個程序的主入口(整個程序最先運行的那個activity)只有最先定義的那個Activity。
如果一個應用沒有Launcher則該apk仍能安裝到設備上,但是在主程序圖中看不到。如果給那個Activity定了Launcher,且同時設定了Main,則這個Activity就可出現(xiàn)在程序圖中;如果沒有Main,則不知啟動哪Activity,故也不會有圖標出現(xiàn)。
4、然后我們看Activity中的startActivity(intent, bundle)
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1); //這個方法其實也是調用了上面的startActivityForResult(intent, -1, null);
}
}
從源碼可以看出Activity.startActivity方法又調用了Activity.startActivityForResult方法。
5、Activity中的startActivityForResult(Intent intent, int requestCode,Bundle options)
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity( //然后就走到了Instrumentation中的execStartActivity()
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
mInstrumentation是Activity類的成員變量,它的類型是Intrumentation,它用來監(jiān)控應用程序和系統(tǒng)的交互。
mMainThread也是Activity類的成員變量,它的類型是ActivityThread,它代表的是應用程序的主線程。這里通過mMainThread.getApplicationThread獲得它里面的ApplicationThread成員變量,它是一個Binder對象,ActivityManagerService會使用它來和ActivityThread來進行進程間通信,這里我們需注意的是,這里的mMainThread代表的是Launcher應用程序運行的進程。
mToken也是Activity類的成員變量,它是一個Binder對象的遠程接口。
6、Instrumentation.execStartActivity() 里面的參數(shù)有點多
{@hide}
public ActivityResult execStartActivity( //返回的是一個ActivityResult
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(who);
int result = ActivityManagerNative.getDefault() //啟動Activity
.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;
}
從上面的代碼可以看出,啟動Activity真正的實現(xiàn)由ActivityManagerNative.getDefault().startActivity方法執(zhí)行。
這里的ActivityManagerNative.getDefault() 它返回的是一個ActivityManagerService的一個代理類ActivityManagerProxy。
此時啟動Activity這一操作交給了ActivityManagerNative.getDefault()的startActivity()方法.ActivityManagerNative是一個抽象類,繼承了Binder,同時它又實現(xiàn)了IActivityManager接口,其實現(xiàn)類是ActivityManagerService(AMS).
ActivityManagerNative.getDefault()方法返回IActivityManager類型對象,其實現(xiàn)類是ActivityManagerProxy,其構造函數(shù)接受一個IBinder類型,其實就是ActivityManagerService對象,此時你應該發(fā)現(xiàn)ActivityManagerNative,IActivityManager以及ActivityManagerProxy三者之間的聯(lián)系如下:

通過上圖,我們看到這三者就是一個典型的代理模式:ActivityManagerProxy就是ActivityManagerService的遠程代理,那么此時ActivityManagerNative的作用也就很明顯:返回AMS的遠程代理對象,這樣Launcher應用就能和AMS服務通信了.
7. ActivityManagerService的代理類 ActivityManagerProxy.startActivity()
ActivityManagerProxy是ActivityManagerNative中的一個內部類。
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
由于ActivityManagerProxy是一個代理類,上面是通過IPC的Binder聯(lián)系到ActivityManagerService,最后會調用ActivityManagerService的startActivity方法。
我們用一張圖來簡單的描述上述整個流程:

8. ActivityManagerService.startActivity()和startActivityAsUser()
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
//調用了ActivityManagerService的startActivityAsUser()
}
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
//這里的mActivityStarter的類型是ActivityStarter。
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null);
}
9. ActivityStarter.startActivityMayWait()和ActivityStackSupervisor.resolveActivity()
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
//省略了很多代碼
.................................
// 調用ActivityStackSupervisor.resolveActivity()
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
.................................
final ActivityRecord[] outRecord = new ActivityRecord[1];
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask);
.................................
return res;
}
}
ActivityInfo resolveActivity(Intent intent, ResolveInfo rInfo, int startFlags,
ProfilerInfo profilerInfo) {
final ActivityInfo aInfo = rInfo != null ? rInfo.activityInfo : null;
if (aInfo != null)
intent.setComponent(new ComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
if (!aInfo.processName.equals("system")) {
if ((startFlags & ActivityManager.START_FLAG_DEBUG) != 0) {
mService.setDebugApp(aInfo.processName, true, false);
}
if ((startFlags & ActivityManager.START_FLAG_NATIVE_DEBUGGING) != 0) {
mService.setNativeDebuggingAppLocked(aInfo.applicationInfo, aInfo.processName);
}
if ((startFlags & ActivityManager.START_FLAG_TRACK_ALLOCATION) != 0) {
mService.setTrackAllocationApp(aInfo.applicationInfo, aInfo.processName);
}
if (profilerInfo != null) {
mService.setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo);
}
}
}
return aInfo;
}
ActivityStackSupervisor的resolveActivity方法主要是獲得對參數(shù)intent的內容進行解析,得到MainActivity的相關信息,保存在aInfo變量中。解析之后,得到的aInfo.applicationInfo.packageName的值為應用的包名,aInfo.name的值為MainActivity的完整名稱,被定為
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
的Activity,這是在這個實例的配置文件AndroidManifest.xml里面配置的。然后又調用了ActivityStarter的startActivityLocked方法。
10. ActivityStarter.startActivityLocked()
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage,
int realCallingPid, int realCallingUid, int startFlags, Bundle options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
ActivityContainer container, TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
.........................
}
}
...........................................
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;
}
}
}
final int launchFlags = intent.getFlags();
if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
// Transfer the result target from the source activity to the new
// one being started, including any failures.
if (requestCode >= 0) {
ActivityOptions.abort(options);
return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
..................................
}
}
if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
.................
}
if (err == ActivityManager.START_SUCCESS && aInfo == null) {
................
}
if (err == ActivityManager.START_SUCCESS
.................
}
...........................................
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, this, container, options);
....................................
doPendingActivityLaunchesLocked(false);
....................................
從傳進來的參數(shù)caller得到調用者的進程信息,并保存在callerApp變量中,這里就是Launcher應用程序的進程信息了。 前面說過,參數(shù)resultTo是Launcher這個Activity里面的一個Binder對象,通過它可以獲得Launcher這個Activity的相關信息,保存在sourceRecord變量中。再接下來,創(chuàng)建即將要啟動的Activity的相關信息,并保存在r變量中:
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, this, container, options);
然后調用 ActivityStarter. doPendingActivityLaunchesLocked(false);方法。
11. ActivityStarter.doPendingActivityLaunchesLocked(false)
final void doPendingActivityLaunchesLocked(boolean doResume) {
while (!mPendingActivityLaunches.isEmpty()) {
final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
try {
final int result = startActivityUnchecked(
pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
postStartActivityUncheckedProcessing(
pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
mTargetStack);
} catch (Exception e) {
Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
pal.sendErrorResult(e.getMessage());
}
}
}
12. ActivityStarter.startActivityUnchecked()
這個方法主要是創(chuàng)建Acitivity棧,根據(jù)Activity的啟動模式,由于是點擊圖標進來的,一開始也設置了標志位Intent.FLAG_ACTIVITY_NEW_TASK,所以會新創(chuàng)建一個Activity棧。如果之前已經有棧,且不是singleinstance,就不會再創(chuàng)建新的棧,會將待啟動的Activity添加到原來的棧中。最后將會調到ActivityStack的resumeTopActivityUncheckedLocked()中。
13、ActivityStack.resumeTopActivityUncheckedLocked()
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
mService.updateSleepIfNeededLocked();
}
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
return result;
}
14、ActivityStack.resumeTopActivityInnerLocked()
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
---------------------------
省略多余的代碼,太長了
mStackSupervisor.startSpecificActivityLocked(next, true, true);
---------------------------
}
(1)這個方法還會調用通過ActivityManagerService通過Binder進程間通信機制通知Launcher進入Paused狀態(tài);如果是通過其他Activity啟動的。會將其他Activity進入Paused狀態(tài)。由于這里是Launcher發(fā)起的startActivity,所以Launcher進入Paused狀態(tài)。
(2)調用了ActivityStackSupervisor.startSpecificActivityLocked方法。
15、ActivityStackSupervisor.startSpecificActivityLocked()
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
//該應用的進程已經存在
if (app != null && app.thread != null) {
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);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
}
//該應用的進程尚未創(chuàng)建,調用AMS的startProcessLocked()
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
注意,這里由于是第一次啟動應用程序的Activity,取回來的app為null。在Activity應用程序中的AndroidManifest.xml配置文件中,我們沒有指定Application標簽的process屬性,系統(tǒng)就會默認使用package的名稱。
每一個應用程序都有自己的uid,因此,這里uid + process的組合就可以為每一個應用程序創(chuàng)建一個ProcessRecord。所以下面if (app != null && app.thread != null)條件不成立,那么條件里面realStartActivityLocked 方法就不會執(zhí)行,而是執(zhí)行ActivityManagerService.startProcessLocked函數(shù)進行下一步操作。
15、ActivityManagerService.startProcessLocked()
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) {
.............................
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
...................
String hostingNameStr = hostingName != null
? hostingName.flattenToShortString() : null;
if (app == null) {
checkTime(startTime, "startProcess: creating new process record");
// 創(chuàng)建一個新的ProcessRecord
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 {
............................
}
...............................
startProcessLocked(
app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
........
return (app.pid != 0) ? app : null;
}
首先調用getProcessRecordLocked,但是返回的app為null,所以下面這一句就會執(zhí)行。
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
newProcessRecordLocked方法會調用addProcessNameLocked方法,addProcessNameLocked方法中會執(zhí)行mProcessNames.put(proc.processName, proc.uid, proc);這時候mProcessNames這個全局變量就有數(shù)據(jù)了,再調用getProcessRecordLocked,返回的就不是null了。
接著,ActivityManagerService.startProcessLocked方法會執(zhí)行另一個無返回值的startProcessLocked方法。
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
.............................
try {
checkTime(startTime, "startProcess: getting gids from package manager");
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName, app.userId);
MountServiceInternal mountServiceInternal = LocalServices.getService(
MountServiceInternal.class);
mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,
app.info.packageName);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
.....................................
//記住這里新進程導入的是android.app.ActivityThread類
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);
.......................
這里主要是調用Process.start接口來創(chuàng)建一個新的進程,新的進程會導入android.app.ActivityThread類,并且執(zhí)行它的main函數(shù),這就是為什么我們前面說每一個應用程序都有一個ActivityThread實例來對應的原因.
到現(xiàn)在我們同樣用一張圖來描述這過程:

16、走進Zygote 調用Process.start接口來創(chuàng)建一個新的進程
/*
* {@hide}
*/
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
start方法又調用了startViaZygote方法,該方法會通過zygote機制開啟一個新的進程。由于我們導入的類名是android.app.ActivityThread,開啟一個ActivityThread進程,這也是為什么一個應用程序只有一個ActivityThread,然后會執(zhí)行他的main方法。
17、執(zhí)行ActivityThread.main()函數(shù)和ActivityThread.attach(false)函數(shù)
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter()); //在libcore中設置事件日志記錄的報告程序
// Make sure TrustedCertificateStore looks in the right place for CA certificates
//確??尚抛C書在正確的位置查找CA證書
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
//將當前線程初始化為Looper,將其標記為應用程序的主Loopper對象,應用程序的主線程是由Androi環(huán)境創(chuàng)建的,因此您永遠不需要自己調用此函數(shù)。
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
我們在這個方法里創(chuàng)建ActivityThread,并且構建主線程的消息循環(huán)系統(tǒng)。
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
// Watch for getting close to heap limit.
BinderInternal.addGcWatcher(new Runnable() {
@Override public void run() {
if (!mSomeActivitiesChanged) {
return;
}
Runtime runtime = Runtime.getRuntime();
long dalvikMax = runtime.maxMemory();
long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
if (dalvikUsed > ((3*dalvikMax)/4)) {
if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
+ " total=" + (runtime.totalMemory()/1024)
+ " used=" + (dalvikUsed/1024));
mSomeActivitiesChanged = false;
try {
mgr.releaseSomeActivities(mAppThread);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
});
} else {
// Don't set application object here -- if the system crashes,
// we can't display an alert, we just want to die die die.
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());
try {
mInstrumentation = new Instrumentation();
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
// add dropbox logging to libcore
DropBox.setReporter(new DropBoxReporter());
ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
@Override
public void onConfigurationChanged(Configuration newConfig) {
synchronized (mResourcesManager) {
// We need to apply this change to the resources
// immediately, because upon returning the view
// hierarchy will be informed about it.
if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
mResourcesManager.getConfiguration().getLocales());
// This actually changed the resources! Tell
// everyone about it.
if (mPendingConfiguration == null ||
mPendingConfiguration.isOtherSeqNewer(newConfig)) {
mPendingConfiguration = newConfig;
sendMessage(H.CONFIGURATION_CHANGED, newConfig);
}
}
}
}
@Override
public void onLowMemory() {
}
@Override
public void onTrimMemory(int level) {
}
});
}
ActivityThread的內部類ApplicationThread是一個Binder,獲得系統(tǒng)的ActivityManagerService, 調用它的attachApplication(mAppThread)并把ApplicationThread的對象mAppThread(是一個binder對象)傳給ActivityManagerService,AMS拿到了這個Binder對象后做了3件事。
18、ActivityManagerService.attachApplication()和ActivityManagerService.attachApplicationLocked()
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
................................
final String processName = app.processName;
try {
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
startProcessLocked(app, "link fail", processName);
return false;
}
EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);
app.makeActive(thread, mProcessStats);
app.curAdj = app.setAdj = -100;
app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.forcingToForeground = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
..............
boolean badApp = false;
boolean didSomething = false;
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) { //在這里有調用了ActivityStackSupervisor.attachApplicationLocked()
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
..............................
return true;
}
19、ActivityStackSupervisor.attachApplicationLocked(app)
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
ActivityRecord hr = stack.topRunningActivityLocked();
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
return didSomething;
}
調用ActivityStackSupervisor.realStartActivityLocked執(zhí)行真正的Activity啟動操作。這里要啟動的Activity通過調用ActivityStackSupervisor.topRunningActivityLocked(null)從堆棧頂端取回來,這時候在堆棧頂端的Activity就是MainActivity了。
20、ActivityStackSupervisor.topRunningActivityLocked()
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
.....................
app.forceProcessStateUpTo(mService.mTopProcessState);
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
..........................
return true;
}
app.thread是一個代理對象,代理的就是ApplicationThread,ApplicationThread是ActivityThread的一個內部類.所以邏輯轉向了ApplicationThread的scheduleLaunchActivity方法。
20、ApplicationThreadProxy.scheduleLaunchActivity
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r); //發(fā)送啟動acitvity的消息
}
函數(shù)首先創(chuàng)建一個ActivityClientRecord實例,并且初始化它的成員變量,然后發(fā)送一個啟動Activity的消息交給Handler處理,這個Handler有著一個很簡潔的名字:H,然后看一下H對消息的處理,H定義ActivityThrad類中。
21.在ActivityThread類中的內部類H(是一個Handler)中接收消息
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
----------------------------------
可以看出這個消息的處理交給了ActivityThread的handleLaunchActivity方法來處理。
22.ActivityThread.handleLaunchActivity()
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// Initialize before creating the activity
WindowManagerGlobal.initialize();
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
if (!r.activity.mFinished && r.startsNotResumed) {
performPauseActivityIfNeeded(r, reason);
if (r.isPreHoneycomb()) {
r.state = oldState;
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
從上面的源碼可以看出,performLaunchActivity最終完成了Activity對象的創(chuàng)建和啟動過程,并且Activity通過handleResumeActivity方法來調用被啟動Activity的onResume這一生命周期方法。而onCreate這個這個生命周期方法在performLaunchActivity方法中被回調。
23、ActivityThread.performLaunchActivity
performLaunchActivity()主要做了以下幾個事:
(1)從ActivityClientRecord中獲取待啟動的Activity的組件信息。
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
(2)通過Instrumenttation的newActivity方法使用類加載器創(chuàng)建Activity對象
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
(3)通過LoadeApk的makeApplication方法來嘗試創(chuàng)建Application對象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
initializeJavaContextClassLoader();
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
if (!mActivityThread.mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
// Rewrite the R 'constants' for all library apks.
SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
.getAssignedPackageIdentifiers();
final int N = packageIdentifiers.size();
for (int i = 0; i < N; i++) {
final int id = packageIdentifiers.keyAt(i);
if (id == 0x01 || id == 0x7f) {
continue;
}
rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
}
return app;
}
(4)創(chuàng)建ContextImpl對象并通過Activity的attach方法來完成一些重要數(shù)據(jù)的初始化
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor);
ContextImpl是一個很重要的數(shù)據(jù)結構,它是Context的具體實現(xiàn),Context中的大部分邏輯都是由ContextImpl來完成的。ContextImpl是通過Activity的attach方法來和Activity建立連接的,處理之外,在attach方法中Activity還會完成Window的創(chuàng)建并建立自己和Window的關聯(lián),這樣當Window接受到外部輸入事件后就可以將時間傳遞給Activity。
(5)調用Activity的onCreate
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) { //如果是重新啟動
mInstrumentation.callActivityOnPostCreate(activity, r.state,r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
最后回調Activity的onCreate方法。這也意味著應用已經啟動起來了。
到現(xiàn)在,我們已經完全走完應用冷啟動的流程,上面的過程看起來繁瑣,但是結合時序圖來看應該是比較清晰的.拋開細節(jié)不看,那么上述的整個流程可以用下圖概括:

最后為了方便系統(tǒng)理解整個流程,附上一張相對完整的時序圖:
