注:下列源碼均基於9.0,可經過下列方式下載本文相關源碼到本地:html
- git clone aosp.tuna.tsinghua.edu.cn/platform/pa…
- git clone aosp.tuna.tsinghua.edu.cn/platform/fr…
參考博客:如何下載和閱讀Android源碼java
本篇文章將根據源碼解剖Android的Activity的啓動流程,需注意的是下列的分析均基於Android9.0, 9.0版本相較於以前幾個版本作了許多改動和重構,可是總體的流程是變化不大。根據啓動Activity時機的不一樣,可分爲根Activity的啓動流程和普通Activity啓動流程,根Activity啓動流程又能夠稱爲應用程序啓動流程,即在桌面上點擊一個應用圖標到進入到應用第一個Activity的流程。而普通Activity的啓動流程就是在一個應用裏開啓另一個Activity的流程。因爲兩種啓動流程是有重疊的,而根Activity的啓動流程更加複雜,因此接下來咱們重點分析根Activity的啓動流程,而普通Activity的啓動流程在涉及的地方會稍微提一下。因爲考慮到篇幅較長,這裏將分爲兩篇來介紹。android
這篇將分析啓動流程中的應用進程的建立:git
上面咱們提到根Activity的啓動流程其實就是桌面上點擊一個應用圖標進入到應用的第一個Activity的流程,其實桌面也能夠當作一個程序,即Launcher。當系統開機後,Launcher也隨之被啓動,而後將已經安裝的應用程序圖標顯示到桌面上,因此當咱們點擊一個應用圖標其實就是至關於點擊活動中的一個button,其相應事件就是Launcher進程請求AMS來啓動該應用程序。web
請求的入口就是Launcher的startActivitySafe方法,以下:session
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java併發
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
...
// 根Activity會在新的任務棧中啓動
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
...
if (isShortcut) {
// Shortcuts need some special checks due to legacy reasons.
startShortcutIntentSafely(intent, optsBundle, item);
} else if (user == null || user.equals(Process.myUserHandle())) {
// 調用startActivity
startActivity(intent, optsBundle);
} else {
LauncherAppsCompat.getInstance(this).startActivityForProfile(
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
}
...
return true;
} catch (ActivityNotFoundException|SecurityException e) {
...
}
return false;
}
複製代碼
能夠發現該方法爲根Activity設置了flag,即根Activity會在新的任務棧中啓動。而後會調用咱們熟悉的startActivity方法,而在Launcher並無這個方法,因此咱們天然想到了應該是父類的方法,而後讓咱們來看看Launcher繼承了哪些類?app
public class Launcher extends BaseDraggingActivity implements LauncherExterns, LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate{
}
public abstract class BaseDraggingActivity extends BaseActivity implements WallpaperColorInfo.OnChangeListener {
}
public abstract class BaseActivity extends Activity implements UserEventDelegate{
}
複製代碼
其實一直追蹤下去,你就會發現其實Launcher調用的startActivity其實就是Activity中的startActivity。從這裏也能夠證實Launcher其實也是個Activity。因此在Launcher啓動一個app,和咱們平時在startActivity基本是同樣的(基本同樣,不表明徹底同樣,經過後文分析你就會明白!),因而咱們來看看咱們熟悉的Activity中的startActivity的源碼是如何的:socket
源碼:frameworks/base/core/java/android/app/Activity.javaide
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
//第二個參數爲-1表示Launcher不須要知道根Activity的啓動結果
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);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
//mParent表示當前Activity的父類,當根活動還沒建立則mParent==null
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
...
}
...
}
複製代碼
從上面代碼能夠發現startActivity的最終實現是startActivityForResult,startActivity()第二個參數爲-1表示Launcher不須要知道根Activity的啓動結果,而後在startActivityForResult中因爲此時根Activity尚未建立,故mParent=null,因此咱們只須要關注mParent=null的狀況。在這種狀況中會調用Instrumentation的execStartActivity。這時候也許你就會問這個Instrumentation是什麼?爲何要交給她弄呢?其實Instrumentation這個類很重要,重要體如今對Activity生命週期的調用根本離不開她。每一個Activity都持有Instrumentation對象的一個引用,可是整個進程只會存在一個Instrumentation對象。迴歸正題,讓咱們瞧瞧Instrumentation的execStartActivity這個方法。
frameworks/base/core/java/android/app/Instrumentation.java
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
...
try {
...
//獲取AMS的代理對象
int result = ActivityManager.getService()
.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;
}
複製代碼
在這個方法會調用ActivityManager的getService方法來獲得AMS的代理對象,而後調用這個代理對象的
startActivity方法,那麼這個代理對象是誰呢?讓咱們一探究竟
@UnsupportedAppUsage
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
@UnsupportedAppUsage
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
//獲得activity的service引用,即IBinder類型的AMS引用
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//轉換成IActivityManager對象
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
複製代碼
能夠發如今Singleton中的create方法中因爲b是AMS引用做爲服務端處於SystemServer進程中,與當前Launcher進程做爲客戶端與服務端不在同一個進程,因此am返回的是IActivityManager.Stub的代理對象,此時若是要實現客戶端與服務端進程間的通訊,只須要在AMS繼承了IActivityManager.Stub類並實現了相應的方法,而經過下面的代碼能夠發現AMS恰好是繼承了IActivityManager.Stub類的,這樣Launcher進程做爲客戶端就擁有了服務端AMS的代理對象,而後就能夠調用AMS的方法來實現具體功能了,就這樣Launcher的工做就交給AMS實現了。
public class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
}
複製代碼
經過上面的分析,咱們已經知道如今任務已經交給了AMS,入口是AMS的startActivity。
首先來看看在AMS中的startActivity方法:
源碼:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@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());
}
@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) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
true /*validateIncomingUser*/);
}
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, boolean validateIncomingUser) {
//判斷調用者的進程是否隔離
enforceNotIsolatedCaller("startActivity");
//檢查調用者權限
userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
// TODO: Switch to user app stacks here.
return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();
}
複製代碼
startActivity方法通過多個方法調用會去執行startActivityAsUser方法,在startActivityAsUser方法最後會返回mActivityStartController的一長串鏈式調用方法,若是AlertDialog的話,應該不難看出這鏈式方法確定都是返回一個類型的對象的,咱們只須要看看obtainStarter的返回類型就能夠知道這個對象是什麼類型了。
frameworks/base/services/core/java/com/android/server/am/ActivityStartController.java
ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason);
}
複製代碼
能夠發現這個obtainStarter返回的是ActivityStarter類型的,因此鏈式方法就是對ActivityStarter對象設置了要啓動的活動的相關信息,最後再調用ActivityStarter對象execute方法。因此咱們下一步所須要看的就是這個execute方法。
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
int execute() {
try {
// TODO(b/64750076): Look into passing request directly to these methods to allow
// for transactional diffs and preprocessing.
if (mRequest.mayWait) {
return startActivityMayWait(mRequest.caller, mRequest.callingUid,
mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup,
mRequest.originatingPendingIntent);
} else {
return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
mRequest.outActivity, mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup,
mRequest.originatingPendingIntent);
}
} finally {
onExecutionComplete();
}
}
複製代碼
由於在startActivityAsUser的鏈式方法中咱們調用了setMayWait這個方法,因此這裏的mRequest.mayWait爲true,故會繼續調用startActivityMayWait方法。
ActivityStarter#startActivityMayWait
private 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, SafeActivityOptions options, boolean ignoreTargetSecurity, int userId, TaskRecord inTask, String reason, boolean allowPendingRemoteAnimationRegistryLookup, PendingIntentRecord originatingPendingIntent) {
.....
//根據intent在系統中找到合適的應用的activity,若是有多個activity可選擇,
//則會彈出ResolverActivity讓用戶選擇合適的應用。
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent);
....
}
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, SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, TaskRecord inTask, String reason, boolean allowPendingRemoteAnimationRegistryLookup) {
...
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
inTask, allowPendingRemoteAnimationRegistryLookup);
...
return getExternalResult(mLastStartActivityResult);
}
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, SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
...
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true /* doResume */, checkedOptions, inTask, outActivity);
}
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) {
...
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
...
postStartActivityProcessing(r, result, mTargetStack);
return result;
}
複製代碼
startActivityMayWait方法通過調用屢次的startActivity方法後會調用到startActivityUnchecked這個方法,那這個方法是幹啥的呢?這個方法會根據啓動標誌位和Activity啓動模式來決定如何啓動一個Activity以及是否要調用deliverNewIntent方法通知Activity有一個Intent試圖從新啓動它。好比咱們在一開始將活動設置了FLAG_ACTIVITY_NEW_TASK後將建立一個任務棧,其它的就自行看代碼。
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
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
//建立新的TaskRecord
result = setTaskFromReuseOrCreateNewTask(
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,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
...
}
複製代碼
而後不管以何種模式啓動最終都會調用ActivityStackSupervisor.resumeFocusedStackTopActivityLocked方法。
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
....
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
....
}
複製代碼
因而又調用了ActivityStack的resumeTopActivityUncheckedLocked
frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
}
...
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
複製代碼
emmmm.....,看到這估計都懵逼了,幾個類跳來跳去也不知道幹了些什麼,不慌,讓咱們堅持看下ActivityStackSupervisor.startSpecificActivityLocked,由於這個方法很重要。這個方法將是普通Activity和根Activity啓動流程的分岔路口。
ActivityStackSupervisor#startSpecificActivityLocked
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
//獲取即將要啓動的Activity的所在的應用程序進程
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
//若是應用進程已經存在
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.longVersionCode,
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.
}
//應用進程還未建立,則經過AMS調用startProcessLocked向Zygote進程發送請求
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
複製代碼
閱讀上面的代碼咱們能夠知道在方法中首先獲取到了即將要啓動的Activity所在的應用進程,假如是普通的Activity的啓動流程的活,這個進程確定是存在的,因此將執行realStartActivityLocked的方法。可是咱們如今討論的是根Activity的啓動流程,因爲應用都還未啓動,意味着根Activity所在的應用進程還未建立,而mService其實就是AMS,因此這裏將調用AMS的startProcessLocked。因而咱們又回到了最初的起點AMS。
ActivityManagerService.java
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, boolean keepIfLarge) {
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
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) {
...
final boolean success = startProcessLocked(app, hostingType, hostingNameStr, abiOverride);
...
}
@GuardedBy("this")
private final boolean startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride) {
return startProcessLocked(app, hostingType, hostingNameStr,
false /* disableHiddenApiChecks */, abiOverride);
}
private final boolean startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
...
int uid = app.uid; //建立應用進程的用戶ID
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
checkTime(startTime, "startProcess: getting gids from package manager");
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName,
MATCH_DEBUG_TRIAGED_MISSING, app.userId);
StorageManagerInternal storageManagerInternal = LocalServices.getService(
StorageManagerInternal.class);
mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
app.info.packageName);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
/* * 對用戶組進行建立和賦值 */
if (ArrayUtils.isEmpty(permGids)) {
gids = new int[3];
} else {
gids = new int[permGids.length + 3];
System.arraycopy(permGids, 0, gids, 3, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
// Replace any invalid GIDs
if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2];
if (gids[1] == UserHandle.ERR_GID) gids[1] = gids[2];
}
...
//這個參數後文會提到
final String entryPoint = "android.app.ActivityThread";
return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
startTime);
}
private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal, String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime) {
....
//重點關注
final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
requiredAbi, instructionSet, invokeWith, app.startTime);
...
}
private ProcessStartResult startProcess(String hostingType, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal, String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime) {
....
if (hostingType.equals("webview_service")) {
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
} else {
//經過Process.start方法來爲應用建立進程
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
}
checkTime(startTime, "startProcess: returned from zygote!");
return startResult;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
複製代碼
是否是又驚呆了,好吧,我也驚呆了!反正就是經過調用多個startProcessLocked方法後最終將調用startProcess方法,不過須要重點看一下上面的第四個startProcessLocked,在該方法中有個entryPoint參數爲 "android.app.ActivityThread",這個參數將在後文講到建立應用進程後啓動ActivityThread會用到。而後在startProcess方法裏將調用Process.start來發送應用建立進程的請求。這樣AMS就將發送請求的事交給了Process
frameworks/base/core/java/android/os/Process.java
public static final ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int runtimeFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith,
/*useBlastulaPool=*/ true, zygoteArgs);
}
public final Process.ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int runtimeFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, boolean useBlastulaPool, String[] zygoteArgs) {
try {
//重點關注
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith,
/*startChildZygote=*/false,
useBlastulaPool, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
複製代碼
從上面能夠發現,Process中的start方法的實現是startViaZygote方法,因此咱們重點觀察下這個方法。
private Process.ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int runtimeFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, boolean startChildZygote, boolean useBlastulaPool, String[] extraArgs) throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<String>();
// --runtime-args, --setuid=, --setgid=,
//建立字符串列表argsForZygote,並將啓動應用進程的啓動參數保存在這個列表中
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
argsForZygote.add("--runtime-flags=" + runtimeFlags);
if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
argsForZygote.add("--mount-external-default");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
argsForZygote.add("--mount-external-read");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
argsForZygote.add("--mount-external-write");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
...
synchronized(mLock) {
//重點關注
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
useBlastulaPool,
argsForZygote);
}
}
複製代碼
在startViaZygote中會建立字符串列表argsForZygote來保存將要建立的應用進程的啓動參數,而後最後會調用zygoteSendArgsAndGetResult方法,而在這個方法中第一個參數會調用openZygoteSocketIfNeeded方法,第三個參數就是啓動參數列表。因此咱們先看看openZygoteSocketIfNeeded這個方法的實現。
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");
//64位進程中的
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
//調用ZygoteState的connect函數與mZygoteSocketAddress創建鏈接,
//這裏mZygoteSocketAddress的值爲「zygote」
primaryZygoteState =
ZygoteState.connect(mZygoteSocketAddress, mBlastulaPoolSocketAddress);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
maybeSetApiBlacklistExemptions(primaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
}
if (primaryZygoteState.matches(abi)) {
//Socket進行鏈接成功並匹配abi後會返回ZygoteState類型對象
return primaryZygoteState;
}
// 32位Zygote進程中
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState =
ZygoteState.connect(mZygoteSecondarySocketAddress,
mBlastulaPoolSecondarySocketAddress);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}
maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
}
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}
複製代碼
openZygoteSocketIfNeeded這個方法從方法名就能夠推測出這個方法的做用,大概就是與Zygote創建Socket鏈接。而從代碼中也證明了這一點,在代碼中會根據Zygote進程的位數來創建相應的Socket鏈接,而後返回ZygoteState類型的對象。既然與Zygote創建好Socket鏈接後,接下來固然是發送請求啦!因此讓咱們來看看zygoteSendArgsAndGetResult這個方法中是如何發送請求的!
//將傳入的應用進程的啓動參數argsForZygote寫入到ZygoteState
@GuardedBy("mLock")
private static Process.ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, boolean useBlastulaPool, ArrayList<String> args) throws ZygoteStartFailedEx {
String msgStr = Integer.toString(args.size()) + "\n"
+ String.join("\n", args) + "\n";
// Should there be a timeout on this?
Process.ProcessStartResult result = new Process.ProcessStartResult();
// TODO (chriswailes): Move branch body into separate function.
if (useBlastulaPool && Zygote.BLASTULA_POOL_ENABLED && isValidBlastulaCommand(args)) {
LocalSocket blastulaSessionSocket = null;
try {
blastulaSessionSocket = zygoteState.getBlastulaSessionSocket();
final BufferedWriter blastulaWriter =
new BufferedWriter(
new OutputStreamWriter(blastulaSessionSocket.getOutputStream()),
Zygote.SOCKET_BUFFER_SIZE);
final DataInputStream blastulaReader =
new DataInputStream(blastulaSessionSocket.getInputStream());
blastulaWriter.write(msgStr);
blastulaWriter.flush();
result.pid = blastulaReader.readInt();
// Blastulas can't be used to spawn processes that need wrappers.
result.usingWrapper = false;
if (result.pid < 0) {
throw new ZygoteStartFailedEx("Blastula specialization failed");
}
return result;
} catch (IOException ex) {
// If there was an IOException using the blastula pool we will log the error and
// attempt to start the process through the Zygote.
Log.e(LOG_TAG, "IO Exception while communicating with blastula pool - "
+ ex.toString());
} finally {
try {
blastulaSessionSocket.close();
} catch (IOException ex) {
Log.e(LOG_TAG, "Failed to close blastula session socket: " + ex.getMessage());
}
}
}
try {
final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
zygoteWriter.write(msgStr);
zygoteWriter.flush();
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
result.pid = zygoteInputStream.readInt();
result.usingWrapper = zygoteInputStream.readBoolean();
} catch (IOException ex) {
zygoteState.close();
Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
+ ex.toString());
throw new ZygoteStartFailedEx(ex);
}
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
}
複製代碼
由於在openZygoteSocketIfNeeded中咱們已經與Zygote進程創建了Socket鏈接,因此在這個方法中將傳入的應用進程的啓動參數argsForZygote寫入到ZygoteState。這樣AMS就完成了向Zygote進程發送建立應用進程的請求的任務。
從上面咱們知道,AMS已經與Zygote進程創建Socket鏈接併發送了建立應用進程的請求,那麼Zygote進程是在哪裏收到請求,收到請求後又是怎麼處理的呢?這裏能夠停下來先看看劉望舒的Android系統啓動流程(二)解析Zygote進程啓動過程,寫的很不錯。不過因爲咱們分析的源碼基於8.0,可能會稍微不一樣,但整體上來大體流程是同樣的。經過閱讀後咱們知道Zygote進程是在ZygoteInit的main方法中接受請求的。因此如今的入口就是ZygoteInit的main方法。
從時序圖與上面的分析咱們知道如今Zygote進程接受請求是在main方法,就讓咱們來看看這個main方法
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
@UnsupportedAppUsage
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
Runnable caller;
try {
...
//建立名爲zygote的Socket
zygoteServer.createZygoteSocket(socketName);
....
//因爲在init.rc中設置了start-system-server參數,所以
//這裏將啓動SystemServer,可見SystemServer由Zygote建立的第一個進程
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
caller = Zygote.initBlastulaPool();
if (caller == null) {
Log.i(TAG, "Accepting command socket connections");
//等待AMS的請求
caller = zygoteServer.runSelectLoop(abiList);
}
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
zygoteServer.closeServerSocket();
}
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run();
}
}
複製代碼
經過main方法,咱們能夠知道在這個main方法首先要建立一個Server端的Socket,這個name爲」zygote」的Socket用來等待ActivityManagerService來請求Zygote來建立新的應用程序進程,在上面AMS請求的分析中咱們也知道客戶端將根據這個name來與Zygote的Socket創建鏈接。接下去會啓動SystemServer進程,這個進程會啓動各類系統服務,好比與Activity啓動息息相關的AMS。最後會調用ZygoteServer.runSelectLoop(abiList)來使建立的Socket進入無限循環,等待AMS請求。讓咱們來看看這個runSelectLoop
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
Runnable runSelectLoop(String abiList) {
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
peers.add(null);
while (true) {
while (--pollIndex >= 0) {
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
//監聽Socket鏈接,充當服務端Socket
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < blastulaPoolEventFDIndex) {
try {
//不斷處理客戶端的AMS的請求,而後交給processOneCommand
ZygoteConnection connection = peers.get(pollIndex);
final Runnable command = connection.processOneCommand(this);
}
....
}
}
}
}
複製代碼
能夠發現這個方法是死循環表示不停的監聽着Socket鏈接。acceptCommandPeer方法就是監聽是否收到了請求,若是收到了請求就交給processOneCommand來實現
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
ZygoteArguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
//獲取應用程序進程的啓動參數
args = Zygote.readArgumentList(mSocketReader);
// TODO (chriswailes): Remove this and add an assert.
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
throw new IllegalStateException("IOException on command socket", ex);
}
....
parsedArgs = new ZygoteArguments(args);
....
//fork當前進程建立一個子進程
pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
try {
//pid爲0則表明這個進程爲子進程,即新建立的應用程序進程
if (pid == 0) {
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
// In the parent. A pid < 0 indicates a failure and will be handled in
// handleParentProc.
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
handleParentProc(pid, descriptors, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
複製代碼
在這個方法中將對請求進行處理,首先獲取到將要啓動的應用進程的啓動參數,而後調用forkAndSpecialize來建立應用進程。
frameworks/base/core/java/com/android/internal/os/Zygote.java
public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, int targetSdkVersion) {
ZygoteHooks.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir);
// Enable tracing as soon as possible for the child process.
if (pid == 0) {
Zygote.disableExecuteOnly(targetSdkVersion);
Trace.setTracingEnabled(true, runtimeFlags);
// Note that this event ends at the end of handleChildProc,
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
}
ZygoteHooks.postForkCommon();
return pid;
}
複製代碼
在forkAndSpecialize中,最終將建立應用進程的任務交給nativeForkAndSpecialize,而這個方法能夠看出來應該是本地方法,因此具體如何建立的咱們就不深究了,在這裏咱們這須要知道nativeForkAndSpecialize最終是經過fork當前線程來建立一個子線程,而fork後會有返回值給pid:
因而到這裏子線程也就是應用進程就被孵化出來了。你覺得這樣就結束了?其實還早呢!別忘了咱們的最終使命是根Activity的啓動,而如今只是有了根Activity所須要的應用進程,革命還沒有成功,仍須要努力!
從上面咱們知道應用進程已經被建立,那建立後呢?這就須要咱們回頭看上面的processOneCommand方法,細心的你確定會發現再孵化出應用進程後,仍是有返回值的。
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
Runnable processOneCommand(ZygoteServer zygoteServer) {
....
//fork當前進程建立一個子進程
pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
try {
//pid爲0則表明這個進程爲子進程,即新建立的應用程序進程
if (pid == 0) {
....
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
...
}
}
....
}
複製代碼
在上面咱們分析了當pid=0的時候,則表明了當前進程已是子進程了,即應用進程。因此下一步將執行handleChildProc方法。
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, boolean isZygote) {
.....
if (!isZygote) {
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
....
}
}
複製代碼
而handleChildProc最終又會調用ZygoteInit.zygoteInit方法。以下
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
//爲當前的VM設置未捕獲異常器
RuntimeInit.commonInit();
//Binder驅動初始化,該方法完成後,可經過Binder進行進程通訊
ZygoteInit.nativeZygoteInit();
//主要調用SystemServer的main方法
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
複製代碼
在這個方法裏會建立當前進程的Binder線程池,便於後續與其它進程通訊,而後調用了RuntimeInit的applicationInit方法,以下:
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
...
final Arguments args = new Arguments(argv);
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
複製代碼
這個方法最終會調用findStaticMain方法,不過需注意的是方法的第一個參數args.startClass其實就是咱們上文AMS將請求任務轉移給Process中在最後強調的那個參數:android.app.ActivityThread。而後咱們看看findStaticMain的實現
protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);//1
} catch (ClassNotFoundException ex) {
....
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });//2
} catch (NoSuchMethodException ex) {
...
} catch (SecurityException ex) {
...
}
return new MethodAndArgsCaller(m, argv);
}
複製代碼
在這個方法中首先在註釋1經過反射獲取到android.app.ActivityThread類,而後在註釋2獲取到ActivityThread的main方法,最後經過main方法來構造MethodAndArgsCaller。而這個MethodAndArgsCaller是什麼呢?以下:
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
複製代碼
追蹤下去,MethodAndArgsCaller實際上是RuntimeInit的一個內部類而且繼承了Runnable,而後在run方法中會經過反射調用了mMethod方法,此時mMethod是ActivityThread的main方法,即run方法中將會執行ActivityThread的main方法,在這裏你可能會有疑問了,那這個run方法何時執行呢?讓咱們來看看最開始的ZygoteInit的main方法。
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
@UnsupportedAppUsage
public static void main(String argv[]) {
Runnable caller;
try {
....
caller = Zygote.initBlastulaPool();
if (caller == null) {
Log.i(TAG, "Accepting command socket connections");
//等待AMS的請求
caller = zygoteServer.runSelectLoop(abiList);
}
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
zygoteServer.closeServerSocket();
}
if (caller != null) {
caller.run();
}
}
複製代碼
有沒有恍然大悟呢?從分析Zygote進程接受請求並孵化應用進程的一開始,咱們就是分析zygoteServer.runSelectLoop(abiList)這個方法,而分析到最後findStaticMain方法將返回MethodAndArgsCaller對象(繼承Runnable),因此這時候在ZygoteInit的main方法caller會等於這個MethodAndArgsCaller對象,顯然caller不等於null,故最後會執行caller.run方法,即執行ActivityThread的main方法。因而應用進程成功啓動ActivityThread。
分析到這,咱們已經愈來愈接近萬里長征的終點了!不過仍是得歇歇,養足精力,才能走到終點。下篇博客Android之9.0Activity啓動流程(二)將分析Activity啓動流程的剩下部分。即:
參考博客: