在Android系統中,啓動四大組件中的任何一個均可以啓動應用程序。但絕大部分時候咱們是經過點擊Launcher圖標啓動應用程序。本文依據Android6.0源碼,從點擊Launcher圖標,直至解析到MainActivity#OnCreate()被調用。java
Launcher也是個應用程序,不過是個特殊的應用。俗稱「桌面」。經過PackageManagerService查詢全部已安裝的應用程序,並保存相應的圖標、應用名稱、包名和第一個要啓動的類名等。android
源碼位置:frameworks/base/core/Java/android/app/LauncherActivity.java數組
LauncherActivity#onListItemClick()服務器
public abstract class LauncherActivity extends ListActivity { @Override protected void onListItemClick(ListView l, View v, int position, long id) { Intent intent = intentForPosition(position); startActivity(intent); } }
能夠看到LauncherActivity
繼承自ListActivity
,而ListActivity
繼承自Activity
。在LauncherActivity#onListItemClick()
方法中首先經過intentForPosition()
獲取了一個Intent
,而後調用startActivity(intent)
啓動一個Activity
。因爲ListActivity
並無重寫Activity#startActivity()
方法,因此這裏會直接調用Activity#startActivity()
。在此以前先看下intentForPosition()
是怎樣構造Intent
。app
protected Intent intentForPosition(int position) { ActivityAdapter adapter = (ActivityAdapter) mAdapter; return adapter.intentForPosition(position); } private class ActivityAdapter extends BaseAdapter implements Filterable { public Intent intentForPosition(int position) { if (mActivitiesList == null) { return null; } Intent intent = new Intent(mIntent); ListItem item = mActivitiesList.get(position); intent.setClassName(item.packageName, item.className); if (item.extras != null) { intent.putExtras(item.extras); } return intent; } }
Intent
中只是指定了即將啓動的Activity
。socket
源碼位置:frameworks/base/core/java/android/app/Activity.javaasync
Activity#startActivity()ide
public void startActivity(Intent intent) { this.startActivity(intent, null); } public void startActivity(Intent intent, @Nullable Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { startActivityForResult(intent, -1); } } /** @param requestCode If >= 0, this code will be returned inonActivityResult() when the activity exits. */ public void startActivityForResult(Intent intent, int requestCode) { startActivityForResult(intent, requestCode, null); } public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); ... } }
在調用的過程當中能夠觀察到,不管調用StartActivity()
仍是startActivityForResult()
,最終調用的都是startActivityForResult()
。並且註釋說明只有requestCode >= 0
時onActivityResult()
纔會被調用。通過一系列的調用,最終調用了Instrumentation#execStartActivity()
。跟進。oop
源碼位置:frameworks/base/core/java/android/app/Instrumentation.javapost
Instrumentation#execStartActivity()
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { ... int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); ... }
這裏ActivityManagerNative.getDefault()
涉及到Binder進程間通訊機制。下面進行一個簡短的介紹,這不是本文的重點。瞭解過同窗的能夠略過下面這段Binder簡析,不想了解的也能夠直接理解爲返回的是ActivityManagerService
(如下簡稱AMS)。實際調用的是AMS#startActivity()
ActivityManagerNative.getDefault()
static public IActivityManager getDefault() { return gDefault.get(); } private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { IBinder b = ServiceManager.getService("activity"); IActivityManager am = asInterface(b); return am; } }; static public IActivityManager asInterface(IBinder obj) { if (obj == null) { return null; } IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor); if (in != null) { return in; } return new ActivityManagerProxy(obj); }
本例中AMS
做爲服務器端,ActivityManagerNative
做爲客戶端。在getDefault()
方法中經過調用asInterface()
方法中的new ActivityManagerProxy(obj)
返回了IActivityManager
的子類對象AMS
。從哪裏能夠看出來呢?這個就比較難找了,不過細心點仍是能夠發現寫蛛絲馬跡。重點在於IBinder b = ServiceManager.getService("activity")
,這裏的參數是「activity」。在上篇博文SystemServer啓動流程源碼解析中,分析SystemServer#startBootstrapServices()
方法啓動AMS以後調用mActivityManagerService.setSystemProcess()
,跟進。
源碼位置:frameworks/base/services/java/com/android/server/SystemServer.java
SystemServer#startBootstrapServices()
private void startBootstrapServices() { Installer installer = mSystemServiceManager.startService(Installer.class); // Activity manager runs the show. mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); // Set up the Application instance for the system process and get started. mActivityManagerService.setSystemProcess(); } public void setSystemProcess() { ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true); }
靜態常量Context.ACTIVITY_SERVICE = "activity"
。到這裏就對上了。先addService("activity")
,而後getService("activity")
。其實在add和get的時候,又是一次經過Binder進行進程間通訊的過程。此次和本文關係不大,這裏再也不拓展。下面回到AMS#startActivity()
前方高能,可能會致使身體感到嚴重不適。請作好心理準備!
源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
ActivityManagerService#startActivity()
@Override public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) { return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, options, UserHandle.getCallingUserId()); } @Override public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) { // 驗證CallingUid是否合法 enforceNotIsolatedCaller("startActivity"); // 檢查限權 userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null); return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, null, null, options, false, userId, null, null); }
簡單驗證後開始調用StackSupervisor#startActivityMayWait()
,跟進。
源碼位置:frameworks/base/services/core/java/com/android/server/am/StackSupervisor.java
StackSupervisor#startActivityMayWait()、StackSupervisor#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, WaitResult outResult, Configuration config, Bundle options, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, TaskRecord inTask) { ... // 解析intent信息 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId); // 驗證pid uid(省略) ... int res = startActivityLocked(caller, intent, resolvedType, aInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, null, container, inTask); return res; } ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags, ProfilerInfo profilerInfo, int userId) { // Collect information about the target of the Intent. ActivityInfo aInfo; try { ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent( intent, resolvedType, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS, userId); aInfo = rInfo != null ? rInfo.activityInfo : null; } catch (RemoteException e) { aInfo = null; } if (aInfo != null) { intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); ... } return aInfo; }
在調用resolveActivity()
以後會讀取配置文件中包名和要啓動Activity
完整的路徑名,並分別賦值給aInfo.applicationInfo.packageName和aInfo.name。跟進。
StackSupervisor#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) { ProcessRecord callerApp = null; if (caller != null) { callerApp = mService.getRecordForAppLocked(caller); if (callerApp != null) { callingPid = callerApp.pid; callingUid = callerApp.info.uid; } else { err = ActivityManager.START_PERMISSION_DENIED; } } ... ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, this, container, options); // 檢查intent中的flag信息 ... // 檢查限權 ... ... err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask); return err; }
這個方法近300行代碼,咱們只看關鍵的部分就行了。首先獲取調用者的pid、uid等信息,而後保存在callerApp
中。目標Activity
的信息保存在 r 中。跟進。
StackSupervisor#startActivityUncheckedLocked()
final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, Bundle options, TaskRecord inTask) { ... int launchFlags = intent.getFlags(); // 對intent的flag各類判斷 ... ActivityRecord notTop = (launchFlags & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null; ... ActivityStack sourceStack; if (sourceRecord != null) { if (sourceRecord.finishing) { if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { Slog.w(TAG, "startActivity called from finishing " + sourceRecord + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent); launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; newTaskInfo = sourceRecord.info; newTaskIntent = sourceRecord.task.intent; } sourceRecord = null; sourceStack = null; } else { sourceStack = sourceRecord.task.stack; } } else { sourceStack = null; } ... if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0) || launchSingleInstance || launchSingleTask) { if (inTask == null && r.resultTo == null) { // See if there is a task to bring to the front. If this is // a SINGLE_INSTANCE activity, there can be one and only one // instance of it in the history, and it is always in its own // unique task, so we do a special search. ActivityRecord intentActivity = !launchSingleInstance ? findTaskLocked(r) : findActivityLocked(intent, r.info); ... } ... // Should this be considered a new task? if (r.resultTo == null && inTask == null && !addingToTask && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { newTask = true; targetStack = computeStackFocus(r, newTask); targetStack.moveToFront("startingNewTask"); if (reuseTask == null) { // 設任務棧 r.setTask(targetStack.createTaskRecord(getNextTaskId(), newTaskInfo != null ? newTaskInfo : r.info, newTaskIntent != null ? newTaskIntent : intent, voiceSession, voiceInteractor, !launchTaskBehind /* toTop */), taskToAffiliate); } ... } ... targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options); return ActivityManager.START_SUCCESS; }
這個方法600+行,並且好多邏輯判斷,看的幾近崩潰。不過還好,關鍵的代碼已經被過濾出來了~首先肯定幾個變量。前面都沒有設置過intent
的flag
,因此launchFlags = 0x00000000
,可是在執行launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK
以後。launchFlags = Intent.FLAG_ACTIVITY_NEW_TASK
。notTop = null
。因爲沒有要接收返回信息的Activity
,因此r.resultTo == null
。因爲沒有設置Activity
的啓動模式爲SingleInstance
,因此launchSingleInstance = false
,即會執行findTaskLocked(r)
。這個方法的做用是查找歷史全部stack
中有沒有目標Activity
,很顯然返回值爲null
,因此下面很大一段判斷邏輯都不會執行。大約200行,爽~。既然沒有相應的任務棧,確定要建立的。在上文中建立任務棧對應的方法爲targetStack.createTaskRecord()
。最後執行ActivityStack#startActivityLocked()
,跟進。
源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
ActivityStack#startActivityLocked()
final void startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume, boolean keepCurTransition, Bundle options) { ... // newTask = true if(!newTask){ ... } task = r.task; // 將ActivityRecord置於棧頂 task.addActivityToTop(r); // 將任務棧置於前臺 task.setFrontOfTask(); ... if (doResume) { mStackSupervisor.resumeTopActivitiesLocked(this, r, options); } }
跟進。
源碼位置:frameworks/base/services/core/java/com/android/server/am/StackSupervisor.java
StackSupervisor#resumeTopActivitiesLocked()
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions) { if (targetStack == null) { targetStack = mFocusedStack; } // Do targetStack first. boolean result = false; if (isFrontStack(targetStack)) { result = targetStack.resumeTopActivityLocked(target, targetOptions); } for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); if (stack == targetStack) { // Already started above. continue; } if (isFrontStack(stack)) { stack.resumeTopActivityLocked(null); } } } return result; }
這個方法的做用是將Launcher
應用程序所在的任務棧執行resumeTopActivityLocked()
方法。跟進。
源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
ActivityStack#resumeTopActivityLocked()
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle 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; }
跟進。
ActivityStack#resumeTopActivityInnerLocked()
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) { ... // If the top activity is the resumed one, nothing to do. if (mResumedActivity == next && next.state == ActivityState.RESUMED && mStackSupervisor.allResumedActivitiesComplete()) { ... return false; } ... if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity); pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause); } ... mStackSupervisor.startSpecificActivityLocked(next, true, true); ... }
這個方法的主要做用是將mResumedActivity
暫停(Launcher
任務棧的TopActivity
),即進入onPause
狀態。以後啓動指定的AttivityRecored
,即target AttivityRecored
。
源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
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)) { // Don't add this if it is a platform component that is marked // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats); } realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e); } // If a dead object exception was thrown -- fall through to // restart the application. } mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }
因爲沒有在指定Application
的process
屬性,因此這裏的app = null
。
詳見ActivityStackSupervisor#getProcessRecordLocked()
。
final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) { if (uid == Process.SYSTEM_UID) { // The system gets to run in any process. If there are multiple // processes with the same uid, just pick the first (this // should never happen). SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(processName); if (procs == null) return null; ... } ... }
跟進。
源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
ActivityManagerService#startProcessLocked()
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 */); }
跟進。
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) { // isolated = false if (!isolated) { // 沒有指定application的process,因此app = null app = getProcessRecordLocked(processName, info.uid, keepIfLarge); ... } ... if (app == null) { checkTime(startTime, "startProcess: creating new process record"); // 建立ProcessRecord app = newProcessRecordLocked(info, processName, isolated, isolatedUid); ... checkTime(startTime, "startProcess: done creating new process record"); } } ... checkTime(startTime, "startProcess: stepping in to startProcess"); // hostingNameStr="activity" 後面仨參數都是null startProcessLocked( app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs); checkTime(startTime, "startProcess: done starting proc!");
終於看見Process
的身影了,親人吶!!!
ActivityManagerService#startProcessLocked()
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { ... try { int uid = app.uid; int[] gids = null; int mountExternal = Zygote.MOUNT_EXTERNAL_NONE; // isolated = false 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, app.userId); MountServiceInternal mountServiceInternal = LocalServices.getService( MountServiceInternal.class); mountExternal = mountServiceInternal.getExternalStorageMountMode(uid, app.info.packageName); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } /* * Add shared application and profile GIDs so applications can share some * resources like shared libraries and access user-wide resources */ if (ArrayUtils.isEmpty(permGids)) { gids = new int[2]; } else { gids = new int[permGids.length + 2]; System.arraycopy(permGids, 0, gids, 2, permGids.length); } gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid)); gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid)); } ... String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi; if (requiredAbi == null) { requiredAbi = Build.SUPPORTED_ABIS[0]; } String instructionSet = null; if (app.info.primaryCpuAbi != null) { instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi); } app.gids = gids; app.requiredAbi = requiredAbi; app.instructionSet = instructionSet; 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); checkTime(startTime, "startProcess: returned from zygote!"); ... } ... }
這個方法過重要了,因此展現的代碼稍微多一些。首先肯定幾個參數值。hostingType = activity
、後面的三個參數abiOverride
、entryPoint
和entryPointArgs
均等於null
、app.isolated = false
。首先建立了gids[]
這個參數,而後在前兩項插入AppGid
和UserGid
,而後構造了requiredAbi
、instructionSet
等參數,以後調用Process#start()
來建立新進程。Process#start()
。如今是凌晨兩點,若是你像我同樣已經寫了5個小時,必定會發現這方法名字是多麼的讓人陶醉~
抽只煙冷靜下~
跟進。
源碼位置:frameworks/base/core/java/android/os/Process.java
Process#start()
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); } }
這是隻是調用startViaZygote()
進一步處理。跟進。
Process#startViaZygote()
private static ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String[] extraArgs) throws ZygoteStartFailedEx { synchronized(Process.class) { ArrayList<String> argsForZygote = new ArrayList<String>(); // --runtime-args, --setuid=, --setgid=, // and --setgroups= must go first argsForZygote.add("--runtime-args"); argsForZygote.add("--setuid=" + uid); argsForZygote.add("--setgid=" + gid); ... // --setgroups is a comma-separated list if (gids != null && gids.length > 0) { StringBuilder sb = new StringBuilder(); sb.append("--setgroups="); int sz = gids.length; for (int i = 0; i < sz; i++) { if (i != 0) { sb.append(','); } sb.append(gids[i]); } argsForZygote.add(sb.toString()); } if (niceName != null) { argsForZygote.add("--nice-name=" + niceName); } if (seInfo != null) { argsForZygote.add("--seinfo=" + seInfo); } if (instructionSet != null) { argsForZygote.add("--instruction-set=" + instructionSet); } if (appDataDir != null) { argsForZygote.add("--app-data-dir=" + appDataDir); } argsForZygote.add(processClass); if (extraArgs != null) { for (String arg : extraArgs) { argsForZygote.add(arg); } } return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } }
能夠看到,這裏前面一大段都在構造參數argsForZygote
,uid
啦、gid
啦、-nice-name
啦,這裏須要注意processClass = android.app.ActivityThread
,後文會用到。參數構造完成以後,接下來看下openZygoteSocketIfNeeded()
這個方法。
Process#openZygoteSocketIfNeeded()
/** * Tries to open socket to Zygote process if not already open. If * already open, does nothing. May block and retry. */ private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { if (primaryZygoteState == null || primaryZygoteState.isClosed()) { try { primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe); } } if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } // The primary zygote didn't match. Try the secondary. if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { try { secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe); } } if (secondaryZygoteState.matches(abi)) { return secondaryZygoteState; } throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); }
罕見的我把註釋寫上了,由於註釋說的比我清楚~接下來跟進zygoteSendArgsAndGetResult()
方法。
Process#zygoteSendArgsAndGetResult()
/** * Sends an argument list to the zygote process, which starts a new child * and returns the child's pid. Please note: the present implementation * replaces newlines in the argument list with spaces. * * @throws ZygoteStartFailedEx if process start failed for any reason */ private static ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, ArrayList<String> args) throws ZygoteStartFailedEx { try { /** * See com.android.internal.os.ZygoteInit.readArgumentList() * Presently the wire format to the zygote process is: * a) a count of arguments (argc, in essence) * b) a number of newline-separated argument strings equal to count * * After the zygote process reads these it will write the pid of * the child or -1 on failure, followed by boolean to * indicate whether a wrapper process was used. */ final BufferedWriter writer = zygoteState.writer; final DataInputStream inputStream = zygoteState.inputStream; writer.write(Integer.toString(args.size())); writer.newLine(); int sz = args.size(); for (int i = 0; i < sz; i++) { String arg = args.get(i); if (arg.indexOf('\n') >= 0) { throw new ZygoteStartFailedEx( "embedded newlines not allowed"); } writer.write(arg); writer.newLine(); } writer.flush(); // Should there be a timeout on this? ProcessStartResult result = new ProcessStartResult(); result.pid = inputStream.readInt(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } result.usingWrapper = inputStream.readBoolean(); return result; } catch (IOException ex) { zygoteState.close(); throw new ZygoteStartFailedEx(ex); } }
註釋也說的很清楚,給Zygote
發送一個argument list
。通知Zygote
進程啓動一個子進程。再接下來就該和Zygote
進程打交道了。
太晚了,關鍵明天還要上班。明天再細緻分析這部分,古耐~
在另外一篇博文 Android Zygote啓動流程源碼解析中說到:在Zygote#main()
中先註冊了一個serverSocket
,在啓動了SystemServer
進程以後,一直監聽這個serverSocket
,準備啓動新的應用進程。大概過程以下:
源碼位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
ZygoteInit#main()
public static void main(String argv[]) { // 註冊socket registerZygoteSocket(socketName); ... if (startSystemServer) { // 啓動SystemServer進程 startSystemServer(abiList, socketName); } // 監聽socket,啓動新的應用進程。--後文會講 runSelectLoop(abiList); closeServerSocket(); ... }
跟進runSelectLoop(abiList)
。
ZygoteInit#runSelectLoop()
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller { while (true) { int index; ... if (index < 0) { throw new RuntimeException("Error in select()"); } else if (index == 0) { ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDescriptor()); } else { boolean done; done = peers.get(index).runOnce(); if (done) { peers.remove(index); fds.remove(index); } } } } private static ZygoteConnection acceptCommandPeer(String abiList) { try { return new ZygoteConnection(sServerSocket.accept(), abiList); } catch (IOException ex) { ... } }
這個方法的主要做用是經過acceptCommandPeer()
方法接收客戶端發送的Socket
消息。以後執行ZygoteConnection#runOnce()
方法。跟進。
源碼位置:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
ZygoteConnection#runOnce()
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { ... checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize"); pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet, parsedArgs.appDataDir); checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize"); ... if (pid == 0) { // in child IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); // should never get here, the child is expected to either // throw ZygoteInit.MethodAndArgsCaller or exec(). return true; } else { ... } ... }
省略的一大段代碼都在構造參數,以後根據參數調用Zygote.forkAndSpecialize()
方法fork
出應用程序進程,到這裏,應用進程已經被建立了。由於是子進程pid = 0
,因此以後會調用handleChildProc()
方法進一步處理。跟進。
ZygoteConnection#handleChildProc()
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { closeSocket(); ZygoteInit.closeServerSocket(); ... ZygoteInit.invokeStaticMain(cloader, className, mainArgs); ... }
上述代碼先關閉從Zygote
進程繼承來的ServerSocket
,而後調用ZygoteInit.invokeStaticMain()
。接下來的流程和啓動System進程流程差很少,這裏快速的過一遍。不熟悉這部分的同窗能夠參考這篇博客。
源碼位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
ZygoteInit#invokeStaticMain()
static void invokeStaticMain(ClassLoader loader, String className, String[] argv) throws ZygoteInit.MethodAndArgsCaller { Class<?> cl; try { cl = loader.loadClass(className); } catch (ClassNotFoundException ex) { throw new RuntimeException( "Missing class when invoking static main " + className, ex); } Method m; m = cl.getMethod("main", new Class[] { String[].class }); int modifiers = m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { throw new RuntimeException( "Main method is not public and static on " + className); } throw new ZygoteInit.MethodAndArgsCaller(m, argv); }
意料之中的裝載類文件、意料之中的反射、意料之中的驗證修飾符、意料之中的拋出個異常,甚至意料之中的在Zygote#main()
中捕獲。看過Zygote啓動流程源碼解析的讀着確定和我有同樣的感受。接下來就該捕獲異常,而後反射ActivityThread
的靜態方法main()
。直接貼代碼了,so boring…
ZygoteInit#main()
public static void main(String argv[]) { try { ... runSelectLoop(abiList); } catch (MethodAndArgsCaller caller) { caller.run(); } // ZygoteInit&MethodAndArgsCaller#run() public void run() { try { mMethod.invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { ... } }
這裏反射調用的是ActivityThread#main()
方法。跟進。
源碼位置:frameworks/base/core/java/com/android/app/ActivityThread.java
ActivityThread#main()
public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start(); ... Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
咱們知道ActivityThread
就是所謂的主線程,其實ActivityThread
並非一個主線程。只是一個擁有mainLooper
的入口方法。
概述中說:在Android系統中,啓動四大組件中的任何一個均可以啓動應用程序。啓動四大組件的均可以啓動應用程序,但實際上入口方法只有
ActivityThread#main()
一個(未驗證)。
在作了一些初始化的工做後,調用了ActivityThread#attach(false)
。跟進。
final ApplicationThread mAppThread = new ApplicationThread(); private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) { ... final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } ... } ... }
前文AMS中的Binder機制
中分析過:ActivityManagerNative.getDefault()
,返回的是AMS
。其中跟進。
源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
ActivityManagerService#attachApplication()
public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread, callingPid); Binder.restoreCallingIdentity(origId); } }
這裏只是調用兩個參數的attachApplicationLocked()
方法處理。跟進。
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) { ... if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { Slog.wtf(TAG, "Exception thrown launching activities in " + app, e); badApp = true; } } ... }
跟進。
源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
ActivityStackSupervisor#attachApplicationLocked()
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 (!isFrontStack(stack)) { continue; } ActivityRecord hr = stack.topRunningActivityLocked(null); 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) { ... } } } } } ... return didSomething; }
首先遍歷全部stack
,以後找到目前被置於前臺的stack
。以後經過topRunningActivityLocked()
獲取最上面的Activity
。最後調用realStartActivityLocked()
方法來真正的啓動目標Activity
。跟進
源碼位置:frameworks/base/services/java/com/android/server/am/ActivityStack.java
ActivityStack#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, new Configuration(mService.mConfiguration), r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo); } ...
這裏經過Binder
,會調用ApplicationThread#scheduleLaunchActivity()
。跟進。
源碼位置:frameworks/base/core/java/android/app/ActivityThread.java
ActivityThread&ApplicationThread#scheduleLaunchActivity()
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; ... sendMessage(H.LAUNCH_ACTIVITY, r); }
構造一個ActivityClientRecord
對象以後,調用sendMessage(H.LAUNCH_ACTIVITY, r)
。跟進。
private void sendMessage(int what, Object obj) { sendMessage(what, obj, 0, 0, false); } private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) { if (DEBUG_MESSAGES) Slog.v( TAG, "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj); Message msg = Message.obtain(); msg.what = what; msg.obj = obj; msg.arg1 = arg1; msg.arg2 = arg2; if (async) { msg.setAsynchronous(true); } mH.sendMessage(msg); }
根據參數組裝了一個Message
對象,以後經過mH.sendMessage(msg)
發送出去。看下mH
是個什麼鬼。跟進。
ActivityThread、ActivityThread&H
public final class ActivityThread { ... final H mH = new H(); ... private class H extends Handler { public static final int LAUNCH_ACTIVITY = 100; public static final int PAUSE_ACTIVITY = 101; ... public void handleMessage(Message msg) { 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); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; ... } } } }
原來mH
不過是Handler的子類罷了。接着在handleMessage()
中解析出Message
對象,而後調用handleLaunchActivity()
進一步處理。跟進。
ActivityThread#handleLaunchActivity()
private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { ...... // 加載activity,而後調用onCreate,onStart方法 Activity a = performLaunchActivity(r, customIntent); if (a != null) { // 調用onResume方法 handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed); ... } ... }
這是個蠻重要的方法。Activity啓動流程源碼解析裏有詳細講解,這裏暫時略過。
跟進。
ActivityThread#performLaunchActivity()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); 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); } 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); } } try { Application app = r.packageInfo.makeApplication(false, mInstrumentation); if (localLOGV) Slog.v(TAG, "Performing launch of " + r); if (localLOGV) Slog.v( TAG, r + ": app=" + app + ", appName=" + app.getPackageName() + ", pkg=" + r.packageInfo.getPackageName() + ", comp=" + r.intent.getComponent().toShortString() + ", dir=" + r.packageInfo.getAppDir()); if (activity != null) { 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); if (customIntent != null) { activity.mIntent = customIntent; } r.lastNonConfigurationInstances = null; activity.mStartedActivity = false; int theme = r.activityInfo.getThemeResource(); if (theme != 0) { activity.setTheme(theme); } activity.mCalled = false; if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } if (!activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onCreate()"); } r.activity = activity; r.stopped = true; if (!r.activity.mFinished) { activity.performStart(); r.stopped = false; } if (!r.activity.mFinished) { if (r.isPersistable()) { if (r.state != null || r.persistentState != null) { mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, r.persistentState); } } else if (r.state != null) { mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); } } 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()"); } } } r.paused = true; mActivities.put(r.token, r); } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to start activity " + component + ": " + e.toString(), e); } } return activity; }
由於這個方法比較重要,因此代碼完整的貼出來了。能夠看到,首先收集要啓動的Activity
信息。而後經過ClassLoader
加載目標Activiy
類。再而後建立Application
,最後調用Activity#onCreate()
。內容有些多,咱們一步步的看。先從建立Application
提及。r.packageInfo
是LoadedApk
對象,因此會調用LoadedApk#makeApplication()
。
源碼位置:frameworks/base/core/java/android/app/LoadedApk.java
LoadedApk#makeApplication()
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { if (mApplication != null) { return mApplication; } Application app = null; ... try { ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); } catch (Exception e) { ... } ... if (instrumentation != null) { try { instrumentation.callApplicationOnCreate(app); } catch (Exception e) { ... } } } return app; }
方法名稱已經很明顯了。跟進。
源碼位置:frameworks/base/core/java/android/app/Instrumentation.java
Instrumentation#newApplication()
public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return newApplication(cl.loadClass(className), context); } static public Application newApplication(Class<?> clazz, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { Application app = (Application)clazz.newInstance(); app.attach(context); return app; }
簡單粗暴,經過反射建立一個Application
實例。如今實例有了,但onCreate()
方法尚未被調用。跟進Instrumentation#callApplicationOnCreate()
public void callApplicationOnCreate(Application app) { app.onCreate(); }
這都無法解析了,,直接調用Application#onCreate()
。如今已經有了Application
,但Activity
只是被ClassLoader
裝載了,onCreate()
尚未調起來。回到ActivityThread#performLaunchActivity()
... 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); mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); ...
跟進。
源碼位置:frameworks/base/core/java/android/app/callActivityOnCreate.java
Instrumentation#callActivityOnCreate()
public void callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState) { prePerformCreate(activity); activity.performCreate(icicle, persistentState); postPerformCreate(activity); } // Activity#performCreate() final void performCreate(Bundle icicle) { onCreate(icicle); mActivityTransitionState.readState(icicle); performCreateCommon(); }
在Activity#performCreate()
這裏調用了OnCreate()
方法。終於把咱們的應用程序啓動起來了~