国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android App啟動流程

2019-11-06 09:40:55
字體:
來源:轉載
供稿:網友

前言

在使用Android手機時,我們總會啟動各種各樣的App以滿足生活的各種需求,你是否想過,我們是怎樣啟動這些APP的?今天我將帶著讀者一起探索在Android系統中,一個App是如何被啟動的。

在開始分析之前,我們先回想下啟動一個App的流程:

Android系統桌面->點擊應用圖標->啟動App

從這個過程來看,只要弄明白:

Android系統桌面是什么點擊應用圖標后Android系統執行了什么操作

就可以解決我們“App如何被啟動”的疑問。

Android系統桌面是什么

如何分析Android系統桌面是什么

在Android系統中,Activity是視圖存在的根本,那么我們可以通過命令adb shell dumpsys activity activities判斷是哪個Activity為我們呈現桌面視圖的。

以我的小米5為例,通過USB連上電腦后,輸入命令adb shell dumpsys activity activities得到結果如下:

可以看到,顯示桌面視圖的Activity是com.miui.home包下的名為Launcher的Activity。

因為虛擬機編譯AOSP實在是太慢了,所以我沒有編譯AOSP得到系統鏡像,然后運行模擬器跑AOSP,再通過Ubuntu的Shell跑命令。國內手機廠商雖然會對Android系統進行定制,但是命名和包名都會和原生盡可能保持一致的。

那么我們在IDE中搜索Launcher,看看這個Activity是什么。結果如下:

這里摘選的是Launcher2的Launcher進行分析,雖然新版本Android已經使用Launcher3作為桌面App了,但是我進入源碼看了看發現核心的邏輯是沒有變化的,所以選取了代碼更短的Launcher2的Launcher進行分析。

點擊應用圖標后Android系統執行了什么操作

既然Launcher是Activity,那就意味著我們點擊桌面的事件可以表達為:

呈現Android桌面視圖(View)->點擊View上某個應用圖標->產生點擊事件->點擊事件被響應->通知Android系統的某個/某些進程->Android系統執行某些操作->啟動App

Launcher如何響應由我們產生的點擊事件

/** * Launches the intent referred by the clicked shortcut. * * @param v The view rePResenting the clicked shortcut. */public void onClick(View v) { // Make sure that rogue clicks don't get through while allapps is launching, or after the // view has detached (it's possible for this to happen if the view is removed mid touch). if (v.getWindowToken() == null) { return; } if (!mWorkspace.isFinishedSwitchingState()) { return; } Object tag = v.getTag(); if (tag instanceof ShortcutInfo) { // Open shortcut final Intent intent = ((ShortcutInfo) tag).intent; int[] pos = new int[2]; v.getLocationOnScreen(pos); intent.setSourceBounds(new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight())); boolean success = startActivitySafely(v, intent, tag); if (success && v instanceof BubbleTextView) { mWaitingForResume = (BubbleTextView) v; mWaitingForResume.setStayPressed(true); } } else if (tag instanceof FolderInfo) { if (v instanceof FolderIcon) { FolderIcon fi = (FolderIcon) v; handleFolderClick(fi); } } else if (v == mAllAppsButton) { if (isAllAppsVisible()) { showWorkspace(true); } else { onClickAllAppsButton(v); } }}boolean startActivitySafely(View v, Intent intent, Object tag) { boolean success = false; try { success = startActivity(v, intent, tag); } catch (ActivityNotFoundException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e); } return success;}

從代碼來看,產生點擊事件后,如果產生點擊事件的View的Tag是ShortcutInfo(即啟動應用的快捷方式),就會取得ShortcutInfo中保存的Intent(這個Intent指向我們要啟動的App),然后執行startActivitySafely(v, intent, tag)方法,而startActivitySafely方法只是對startActivity方法的簡單封裝。

所以,Launcher響應我們產生的點擊事件后,實際上就是啟動一個新的Activity。

我們現在回想下App開發時,每個App都需要有一個“MainActivity”,這個Activity必須在AndroidManifest.xml文件中有以下配置:

<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter>

在配置AndroidManifest.xml文件時,將Activity的Action指定為android.intent.action.MAIN,會使Activity在一個新的Task中啟動(Task是一個Activity棧)。將category指定為android.intent.category.LAUNCHER,表示通過Intent啟動此Activity時,只接受category為LAUNCHER的Intent。

所以,Launcher將會通過App的快捷方式(ShortcutInfo)得到應用的Intent,并通過這個Intent啟動應用的“MainActivity”,從而啟動應用。

所以我們研究的問題就從“App啟動流程”變為“Activity啟動流程”。

Launcher通過Binder通知ActivityManagerService啟動Activity

現在我們就進入Launcher的startActivity方法里面探索“Activity啟動流程”吧:

boolean startActivity(View v, Intent intent, Object tag) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { // Only launch using the new animation if the shortcut has not opted out (this is a // private contract between launcher and may be ignored in the future). boolean useLaunchAnimation = (v != null) && !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION); UserHandle user = (UserHandle) intent.getParcelableExtra(applicationInfo.EXTRA_PROFILE); LauncherApps launcherApps = (LauncherApps) this.getSystemService(Context.LAUNCHER_APPS_SERVICE); if (useLaunchAnimation) { ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); if (user == null || user.equals(android.os.Process.myUserHandle())) { // Could be launching some bookkeeping activity startActivity(intent, opts.toBundle()); } else { launcherApps.startMainActivity(intent.getComponent(), user, intent.getSourceBounds(), opts.toBundle()); } } else { if (user == null || user.equals(android.os.Process.myUserHandle())) { startActivity(intent); } else { launcherApps.startMainActivity(intent.getComponent(), user, intent.getSourceBounds(), null); } } return true; } catch (SecurityException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Launcher does not have the permission to launch " + intent + ". Make sure to create a MAIN intent-filter for the corresponding activity " + "or use the exported attribute for this activity. " + "tag="+ tag + " intent=" + intent, e); } return false;}

在這個方法中,首先,將Intent的Flag設為Intent.FLAG_ACTIVITY_NEW_TASK,使得Android系統將創建一個新的Task來放置即將被打開的新Activity(應用的“MainActivity)。然后獲取一個布爾值以用于后續判斷是否顯示啟動App的動畫。

然后獲取Intent中是否傳輸了Parcelable格式的用戶句柄,并通過Context.LAUNCHER_APPS_SERVICE獲取用于在多用戶情境下啟動App的系統服務。

不管是否顯示啟動App的動畫,最終都會執行startActivity(intent)launcherApps.startMainActivity方法以啟動應用的“MainActivity”。而launcherApps.startMainActivity只在用戶句柄不為空且用戶句柄不等于當前進程句柄時(其他用戶的句柄)調用。

為什么用戶句柄會影響Activity的啟動方式

這一點和Android的多用戶安全機制有關。

假設我們有用戶A和用戶B在使用同一臺手機,用戶A是無法訪問到用戶B的文件或者和用戶B的App通信的。所以假如我們現在是用戶A,但我們想啟動用戶B的App,是無法直接實現的,因為用戶A沒有權限訪問到用戶B的數據,即使我們在代碼中強行把user id設為用戶B的user id,交給內核執行時也會拋出SecurityException。因此我們需要取得用戶A的句柄(和用戶A相關的數據),將我們想啟動的用戶B的App的Intent、用戶A的句柄交給內核,讓擁有權限的Android系統服務(內核態進程)去訪問用戶B的數據并執行相關的操作。

假如是單用戶情境,就會相對簡單了。因為此時只有一個用戶,而該用戶始終有權限直接訪問自己的數據。

startActivity(intent)如何啟動Activity

進入Activity類后層層深入就可以看到最終調用的是startActivityForResult方法:

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } cancelInputsAndStartExitTransition(options); // TODO Consider clearing/flushing other event sources and events for child windows. } else { if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this, intent, requestCode); } }}

從代碼上看,如果Launcher有mParent Activity,就會執行mParent.startActivityFromChild;如果沒有,就會執行mInstrumentation.execStartActivity。進入mParent.startActivityFromChild方法會看到最終也是執行了mInstrumentation.execStartActivity。執行完成后,會取得一個ActivityResult對象,用于給調用者Activity傳遞一些數據,最后在Activity切換時顯示Transition動畫。

這里有一點需要指出的是:這里的ParentActivity指的是類似TabActivity、ActivityGroup關系的嵌套Activity。之所以要強調parent和child,是要避免混亂的Activity嵌套關系。

我們進入Instrumentation類看看execStartActivity方法吧:

public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { IApplicationThread whoThread = (IApplicationThread) contextThread; Uri referrer = target != null ? target.onProvideReferrer() : null; if (referrer != null) { intent.putExtra(Intent.EXTRA_REFERRER, referrer); } if (mActivityMonitors != null) { synchronized (mSync) { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; } break; } } } } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(); int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null;}

首先,我們通過參數IBinder contextThread取得一個IApplicationThread類型的對象whoThread,而contextThread是由mMainThread.getApplicationThread()取得的ApplicationThread對象,此時mMainThread指的就是Launcher應用的主線程,所以whoThread指代的自然是Launcher的ApplicationThread。

因為Activity的onProvideReferrer()方法默認返回null,除非該方法被重寫,而我們使用的Launcher并沒有重寫該方法,所以不用管referrer。

然后判斷是否有ActivityMonitor,如果有,則即將要打開的Activity是否和ActivityMonitor中保存的IntentFilter匹配,如果匹配則增加ActivityMonitor的計數。大致是用于監控符合匹配規則的Activity的數量的。

最后調用ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);啟動Activity,并檢查啟動是否成功。換句話說,最終負責啟動Activity的是ActivityManager,前面得到的ApplicationThread也是在這里使用的。

那么ActivityManager、ApplicationThread、ActivityThread都是什么呢?

ActivityManagerService通過Binder將Launcher切換到pause狀態

首先,調用ActivityManagerNative.getDefault()方法實際調用的是asInterface(IBinder obj)方法,也就意味著我們使用的其實是ActivityManagerProxy,而ActivityManagerProxy則是ActivityManagerService的代理,詳見下面的代碼:

static public IActivityManager getDefault() { return gDefault.get(); }private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { IBinder b = ServiceManager.getService("activity"); if (false) { Log.v("ActivityManager", "default service binder = " + b); } IActivityManager am = asInterface(b); if (false) { Log.v("ActivityManager", "default service = " + am); } return am; }};static public IActivityManager asInterface(IBinder obj) { if (obj == null) { return null; } IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor); if (in != null) { return in; } return new ActivityManagerProxy(obj);}

那么進入ActivityManagerProxy:

class ActivityManagerProxy implements IActivityManager{ public ActivityManagerProxy(IBinder remote) { mRemote = remote; } public IBinder asBinder() { return mRemote; } public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException { // 創建兩個Parcel對象,data用于傳輸啟動Activity需要的數據,reply用于獲取 // 啟動Activity操作執行后系統返回的響應 Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); // caller 就是Launcher提供的ApplicationThread(也就是前面提到的whoThread) data.writeStrongBinder(caller != null ? caller.asBinder() : null); // 記錄啟動新Activity的應用的包名,也就是Launcher的包名 data.writeString(callingPackage); intent.writeToParcel(data, 0); data.writeString(resolvedType); // 將resultTo這個IBinder對象寫入data,實際寫入的就是前面的參數——IBinder token // 而這個token是什么,我們暫時不管,后面會給出解釋 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; }……省略余下代碼……}

將數據都寫入后,就通過mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0)傳輸數據并得到響應(寫入reply)。

前面已經提到了,ActivityManagerProxy是ActivityManagerService的代理,那么調用mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0)實際上就是通過Binder建立Launcher所在的進程與system_server進程(Android Framework層的服務幾乎都由system_server進程管理,因此ActivityManagerService運行在system_server進程中)的通信,并把我們寫入data的數據通過Binder傳遞給ActivityManagerService。

ActivityManagerService得到我們用Parcelable封裝的data后就會調用startActivity方法為Launcher啟動Activity:

@Overridepublic 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());}@Overridepublic final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) { enforceNotIsolatedCaller("startActivity"); userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null); // TODO: Switch to user app stacks here. return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, null, null, options, false, userId, null, null);}void enforceNotIsolatedCaller(String caller) { if (UserHandle.isIsolated(Binder.getCallingUid())) { throw new SecurityException("Isolated process not allowed to call " + caller); }}

enforceNotIsolatedCaller("startActivity");作安全性檢查,判斷當前用戶是否允許啟動Activity,然后對之前傳入的userId進行轉換和安全性檢查。最后調用mStackSupervisor.startActivityMayWait。這里的mStackSupervisor是ActivityStackSupervisor對象,前面提到過,Task是以堆棧形式組織Activity的集合,而Task又由ActivityStack管理,ActivityStackSupervisor則是管理ActivityStack的類。

由于代碼太長,下面只截取部分關鍵代碼講解:

首先,通過下面代碼段調用PackageManagerService解析Intent(我們想要打開的App的用于啟動MainActivity的Intent),將解析的結果保存到ActivityInfo類型的對象里:

// Collect information about the target of the Intent. ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);// Method - resolveActivity ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags, ProfilerInfo profilerInfo, int userId) { // Collect information about the target of the Intent. ActivityInfo aInfo; try { ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent( intent, resolvedType, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS, userId); aInfo = rInfo != null ? rInfo.activityInfo : null; } catch (RemoteException e) { aInfo = null; }……省略,大致是做一些安全性檢查和相關信息的設置…… return aInfo; }

然后互斥鎖鎖住ActivityManagerService的實例mService,如果解析的ActivityInfo不為空,且ApplicationInfo有ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE標記,意味著調用者App是屬于heavy-weight process,如果現在有另一個heavy-weight process正在運行,則需要進行一些額外的處理。然后進入到startActivityLocked方法。

這里通過注釋我們可以發現,若App有ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE標記,App就可視為heavy-weight process,該標記可以在AndroidManifest.xml中設置,它是用于聲明App是否享受系統提供的Activity狀態保存/恢復功能的。但是似乎沒有App能成為heavy-weight process,因為PackageParser的parseApplication方法并不會解析該標簽。

startActivityLocked方法中,得到Launcher(Activity)的ActivityRecord(Activity相關的信息),并創建我們要啟動的Activity的ActivityRecord,最終執行startActivityUncheckedLocked繼續啟動Activity:

ActivityRecord sourceRecord = null; ActivityRecord resultRecord = null; if (resultTo != null) { sourceRecord = isInAnyStackLocked(resultTo); if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Will send result to " + resultTo + " " + sourceRecord); if (sourceRecord != null) { if (requestCode >= 0 && !sourceRecord.finishing) { resultRecord = sourceRecord; } } }…………ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified, voicesession != null, this, container, options);……err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask);

進入startActivityUncheckedLocked方法,完成一些簡單的初始化后,向下執行到這段代碼:如果Intent里有Intent.FLAG_ACTIVITY_NEW_DOCUMENT標記(在AndroidManifest.xml中聲明),且即將要打開的Activity的啟動模式又被聲明為SingleInstance或SingleTask,那么Intent中攜帶的標記和AndroidManifest中聲明的標記出現沖突,而AndroidManifest的優先級是高于Intent的,因此將launchFlags的對應位置為0。

然后是對launchFlags一系列的置位,目的是設置啟動模式。

if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && (launchSingleInstance || launchSingleTask)) { // We have a conflict between the Intent and the Activity manifest, manifest wins. Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " + "/"singleInstance/" or /"singleTask/""); launchFlags &= ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); } else { switch (r.info.documentLaunchMode) { case ActivityInfo.DOCUMENT_LAUNCH_NONE: break; case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING: launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT; break; case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS: launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT; break; case ActivityInfo.DOCUMENT_LAUNCH_NEVER: launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK; break; } }}……if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) { launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;}// If we are actually going to launch in to a new task, there are some cases where// we further want to do multiple task.if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { if (launchTaskBehind || r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) { launchFlags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK; }}……if (inTask == null) { if (sourceRecord == null) { // This activity is not being started from another... in this // case we -always- start a new task. if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) { Slog.w(TAG, "startActivity called from non-Activity context; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent); launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; } } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { // The original activity who is starting us is running as a single // instance... this new activity it is starting must go on its // own task. launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; } else if (launchSingleInstance || launchSingleTask) { // The activity being started is a single instance... it always // gets launched into its own task. launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; }}……// 因為我們是從Launcher啟動目的Activity,所以sourceRecord不為null,值為Launcher的ActivityRecordif (sourceRecord != null) { if (sourceRecord.finishing) { // 如果sourceRecord表示的Activity正在結束/被銷毀,那么我們不能把該Activity看作啟動目的 // Activity的源Activity,因為和源Activity關聯的Task現在可能是空的(沒有Activity)或者 // 也在結束/被銷毀的過程中,所以我們不能盲目地把目的Activity放到該Task中。取而代之的是, // 我們會為它找到一個可用的Task,但我們要先保存源Activity的Task的信息,使得我們在創建新 // 的可用的Task時能用到里面的一些信息。 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { Slog.w(TAG, "startActivity called from finishing " + sourceRecord + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent); launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; newTaskInfo = sourceRecord.info; newTaskIntent = sourceRecord.task.intent; } sourceRecord = null; sourceStack = null; } else { sourceStack = sourceRecord.task.stack; }} else { sourceStack = null;}……// 為目的Activity創建新的Taskif (r.resultTo == null && inTask == null && !addingToTask && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { newTask = true; targetStack = computeStackFocus(r, newTask); targetStack.moveToFront("startingNewTask"); if (reuseTask == null) { r.setTask(targetStack.createTaskRecord(getNextTaskId(), newTaskInfo != null ? newTaskInfo : r.info, newTaskIntent != null ? newTaskIntent : intent, voiceSession, voiceInteractor, !launchTaskBehind /* toTop */), taskToAffiliate); if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r + " in new task " + r.task); } else { r.setTask(reuseTask, taskToAffiliate); } if (isLockTaskModeViolation(r.task)) { Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r); return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION; } if (!movedHome) { if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) { // Caller wants to appear on home activity, so before starting // their own activity we will bring home to the front. r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } }}

完成上面一系列的處理后,調用ActivityStack的startActivityLocked方法繼續執行啟動Activity需要的操作,targetStack是通過這行代碼targetStack = computeStackFocus(r, newTask)為用戶新建的ActivityStack:

mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, intent, r.getUriPermissionsLocked(), r.userId);if (sourceRecord != null && sourceRecord.isRecentsActivity()) { r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);}if (newTask) { EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);}ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);targetStack.mLastPausedActivity = null;targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);if (!launchTaskBehind) { // Don't set focus on an activity that's going to the back. mService.setFocusedActivityLocked(r, "startedActivity");}return ActivityManager.START_SUCCESS;

進入到ActivityStack的startActivityLocked方法,首先為目的Activity創建ProcessRecord,然后用WindowManager進行一些切換窗口的操作,最后調用mStackSupervisor.resumeTopActivitiesLocked(this, r, options)

……if (!isHomeStack() || numActivities() > 0) { // We want to show the starting preview window if we are // switching to a new task, or the next activity's process is // not currently running. boolean showStartingIcon = newTask; ProcessRecord proc = r.app; if (proc == null) { proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid); } if (proc == null || proc.thread == null) { showStartingIcon = true; } ……調用WindowManager切換窗口……}……if (doResume) { mStackSupervisor.resumeTopActivitiesLocked(this, r, options);}

進入到resumeTopActivitiesLocked方法,調用resumeTopActivityLocked方法將所有ActivityStack(多個顯示設備,每個設備對應一個ActivityStack)棧頂的Activity切換到resume狀態(生命周期的onResume),而resumeTopActivityLocked方法先避免遞歸調用,然后調用ActivityStack的resumeTopActivityInnerLocked方法。

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions) { if (targetStack == null) { targetStack = mFocusedStack; } // Do targetStack first. boolean result = false; if (isFrontStack(targetStack)) { result = targetStack.resumeTopActivityLocked(target, targetOptions); } for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); if (stack == targetStack) { // Already started above. continue; } if (isFrontStack(stack)) { stack.resumeTopActivityLocked(null); } } } return result;}

下面這段代碼主要就是做一些前期的檢查,避免做多余的工作浪費時間,并且確保目標Activity處于正確的“狀態”,使得我們后面能把它切換到resume狀態并顯示。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) { // 判斷ActivityManagerService是否已經啟動完畢 if (!mService.mBooting && !mService.mBooted) { // Not ready yet! return false; } // 獲取parentActivity,如果parentActivity還未處于resume狀態,則不能將stack棧頂的Activity切換為resume狀態(Activity的嵌套關系不能弄亂) ActivityRecord parent = mActivityContainer.mParentActivity; if ((parent != null && parent.state != ActivityState.RESUMED) || !mActivityContainer.isAttachedLocked()) { // Do not resume this stack if its parent is not resumed. // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st. return false; } // 如果有正在初始化的Activity沒有位于ActivityStack的棧頂,且正在執行window的啟動和顯示, // 則要將window相關的操作取消。因為這類Activity的窗口有可能被孤立,那么它們有可能永遠也不會進入resume狀態 cancelInitializingActivities(); // 取得當前ActivityStack棧頂Activity的ActivityRecord final ActivityRecord next = topRunningActivityLocked(null); // 記住我們怎樣處理pause/resume狀態切換,并確保無論何時結束處理都會重置狀態 final boolean userLeaving = mStackSupervisor.mUserLeaving; mStackSupervisor.mUserLeaving = false; final TaskRecord prevTask = prev != null ? prev.task : null; if (next == null) { // next為null表示當前ActivityStack沒有要顯示的Activity final String reason = "noMoreActivities"; if (!mFullscreen) { // 如果當前ActivityStack不是全屏的,將焦點切換到下一個擁有Activity的可見ActivityStack中 final ActivityStack stack = getNextVisibleStackLocked(); if (adjustFocusToNextVisibleStackLocked(stack, reason)) { return mStackSupervisor.resumeTopActivitiesLocked(stack, prev, null); } } // 如果ActivityStack是全屏的,卻沒有可以顯示的Activity,那么就顯示桌面(Launcher) ActivityOptions.abort(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: No more activities go home"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo(); return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason); } next.delayedResume = false; // 如果當前棧頂Activity處于resume狀態,且就是我們要打開的Activity,則直接結束 if (mResumedActivity == next && next.state == ActivityState.RESUMED && mStackSupervisor.allResumedActivitiesComplete()) { // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. mWindowManager.executeAPPTransition(); mNoAnimActivities.clear(); ActivityOptions.abort(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Top activity resumed " + next); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } // 對prevActivity(Launcher)所在的Task進行一些判斷,如果prevTask和nextTask相同,那么直接將 // prevTask直接設為棧頂Task;如果prevTask不是當前ActivityStack棧頂的Task,那么它后面的Task // 都應該放到Launcher的Task后面;后面則是有關是否為桌面的判斷和處理了。 final TaskRecord nextTask = next.task; if (prevTask != null && prevTask.stack == this && prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) { if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); if (prevTask == nextTask) { prevTask.setFrontOfTask(); } else if (prevTask != topTask()) { // This task is going away but it was supposed to return to the home stack. // Now the task above it has to return to the home task instead. final int taskNdx = mTaskHistory.indexOf(prevTask) + 1; mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE); } else if (!isOnHomeDisplay()) { return false; } else if (!isHomeStack()){ if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Launching home next"); final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo(); return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished"); } } // 如果ActivityManagerService處于休眠狀態,而且此時沒有Activity處于resume狀態 // 且棧頂Activity處于pause狀態,則中斷調度 if (mService.isSleepingOrShuttingDown() && mLastPausedActivity == next && mStackSupervisor.allPausedActivitiesComplete()) { // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. mWindowManager.executeAppTransition(); mNoAnimActivities.clear(); ActivityOptions.abort(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Going to sleep and all paused"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } // Make sure that the user who owns this activity is started. If not, // we will just leave it as is because someone should be bringing // another user's activities to the top of the stack. if (mService.mStartedUsers.get(next.userId) == null) { Slog.w(TAG, "Skipping resume of top activity " + next + ": user " + next.userId + " is stopped"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } // 確保我們要啟動的Activity沒有處于stop隊列、休眠隊列、等待變為可見隊列中 mStackSupervisor.mStoppingActivities.remove(next); mStackSupervisor.mGoingToSleepActivities.remove(next); next.sleeping = false; mStackSupervisor.mWaitingVisibleActivities.remove(next); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next); // If we are currently pausing an activity, then don't do anything // until that is done. if (!mStackSupervisor.allPausedActivitiesComplete()) { if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE, "resumeTopActivityLocked: Skip resume: some activity pausing."); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; }……待續……}

后面做的工作就是:將Launcher切換到pause狀態,用WindowManager將Launcher的窗口隱藏。現在只完成了Activity相關的預處理工作,目標應用的進程和主線程還沒有創建,因此后面會進入if的false分支調用mStackSupervisor.startSpecificActivityLocked方法創建應用進程;如果目標Activity的進程和主線程已經創建,則進入if語句的true分支直接將目標Activity切換到resume狀態,并顯示目標Activity的窗口。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {……續上…… // 步入setLaunchSource方法后可以知道,該方法實際是通過PowerManager的setWorkSource方法 // 設置WakeLock,使得在執行后面的工作時系統不會進入休眠狀態 mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid); // 現在開始將當前Activity切換到pause狀態,使得棧頂Activity可以切換到resume狀態 boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0; // 將后臺ActivityStack的Activity切換到pause狀態 boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause); // 將當前ActivityStack中正在顯示Activity切換到pause狀態 if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity); pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause); } if (pausing) { if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES, "resumeTopActivityLocked: Skip resume: need to start pausing"); // At this point we want to put the upcoming activity's process // at the top of the LRU list, since we know we will be needing it // very soon and it would be a waste to let it get killed if it // happens to be sitting towards the end. if (next.app != null && next.app.thread != null) { mService.updateLruProcessLocked(next.app, true, null); } if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; }…… ActivityStack lastStack = mStackSupervisor.getLastStack(); if (next.app != null && next.app.thread != null) { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next); // 目標Activity已經可見 mWindowManager.setAppVisibility(next.appToken, true); next.startLaunchTickingLocked(); ActivityRecord lastResumedActivity = lastStack == null ? null :lastStack.mResumedActivity; ActivityState lastState = next.state; mService.updateCpuStats(); // 目標Activity切換到resume狀態 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)"); next.state = ActivityState.RESUMED; mResumedActivity = next; next.task.touchActiveTime(); mRecentTasks.addLocked(next.task); mService.updateLruProcessLocked(next.app, true, null); updateLRUListLocked(next); mService.updateOomAdjLocked();…… mStackSupervisor.startSpecificActivityLocked(next, true, true); }……}

ActivityManagerService為即將打開的應用創建進程

進入ActivityStackSupervisor類的startSpecificActivityLocked方法,首先通過應用的包名和uid取得ProcessRecord,判斷ProcessRecord是否被創建,若創建,則直接啟動Activity;否則調用ActivityManagerService的startProcessLocked方法創建應用進程。

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);}

進入到ActivityManagerService的startProcessLocked方法,首先判斷要創建的進程是否為隔離進程(isolated),由于不是隔離進程,則直接進入true分支,然后再次獲取ProcessRecord。如果Intent有FLAG_FROM_BACKGROUND標記,則在后臺啟動badProcess;否則清空進程的崩潰次數,并將進程移出badProcess集合(如果進程存在的話)。然后調用newProcessRecordLocked方法創建ProcessRecord,最后再調用另一個重載的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) { long startTime = SystemClock.elapsedRealtime(); ProcessRecord app; if (!isolated) { app = getProcessRecordLocked(processName, info.uid, keepIfLarge); checkTime(startTime, "startProcess: after getProcessRecord"); if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) { // If we are in the background, then check to see if this process // is bad. If so, we will just silently fail. if (mBadProcesses.get(info.processName, info.uid) != null) { if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid + "/" + info.processName); return null; } } else { // When the user is explicitly starting a process, then clear its // crash count so that we won't make it bad until they see at // least one crash dialog again, and make the process good again // if it had been bad. if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid + "/" + info.processName); mProcessCrashTimes.remove(info.processName, info.uid); if (mBadProcesses.get(info.processName, info.uid) != null) { EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, UserHandle.getUserId(info.uid), info.uid, info.processName); mBadProcesses.remove(info.processName, info.uid); if (app != null) { app.bad = false; } } } } else { // If this is an isolated process, it can't re-use an existing process. app = null; }…… String hostingNameStr = hostingName != null ? hostingName.flattenToShortString() : null; if (app == null) { checkTime(startTime, "startProcess: creating new process record"); app = newProcessRecordLocked(info, processName, isolated, isolatedUid); if (app == null) { Slog.w(TAG, "Failed making new process record for " + processName + "/" + info.uid + " isolated=" + isolated); return null; } app.crashHandler = crashHandler; checkTime(startTime, "startProcess: done creating new process record"); } else { // If this is a new package in the process, add the package to the list app.addPackage(info.packageName, info.versionCode, mProcessStats); checkTime(startTime, "startProcess: added package to existing proc"); } // 如果系統還沒啟動完畢,則等待系統啟動完畢后再啟動進程 if (!mProcessesReady && !isAllowedWhileBooting(info) && !allowWhileBooting) { if (!mProcessesOnHold.contains(app)) { mProcessesOnHold.add(app); } if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "System not ready, putting on hold: " + app); checkTime(startTime, "startProcess: returning with proc on hold"); return app; } checkTime(startTime, "startProcess: stepping in to startProcess"); startProcessLocked( app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs); checkTime(startTime, "startProcess: done starting proc!"); return (app.pid != 0) ? app : null;}

調用newProcessRecordLocked方法根據ApplicationInfo創建ProcessRecord,并讓ActivityManagerService管理該ProcessRecord,過程比較簡單就不貼代碼了,直接看startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs)方法吧。

進入startProcessLocked方法,首先將app的pid初始化,若進程已經存在(pid不等于0),則先清除超時信息,再講pid置為0,然后確保app不在mProcessesOnHold列表中。

mProcessesOnHold代表在系統啟動完畢前嘗試啟動的進程,這部分進程會先在該列表中待著,等到系統啟動完畢再啟動。

完成一系列的初始化操作后,調用Process.start方法創建應用進程,然后以進程pid為key,app(ProcessRecord)為value存儲到ActivityManagerService的mPidsSelfLocked中。

Process.start方法創建應用進程是通過Zygote進程完成的,設置好參數和創建選項后通過zygoteState.writer將數據交給Zygote進程,它會調用fork()創建進程。在這里要注意一個地方,我們通過if (entryPoint == null) entryPoint = "android.app.ActivityThread"這行代碼設置了進程創建完成后的入口點(Process.start的參數注釋),因此Zygote進程完成了進程創建的操作后就會執行ActivityThread的main()方法。

private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { long startTime = SystemClock.elapsedRealtime(); if (app.pid > 0 && app.pid != MY_PID) { checkTime(startTime, "startProcess: removing from pids map"); synchronized (mPidsSelfLocked) { mPidsSelfLocked.remove(app.pid); mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); } checkTime(startTime, "startProcess: done removing from pids map"); app.setPid(0); } if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES, "startProcessLocked removing on hold: " + app); mProcessesOnHold.remove(app);…… // Start the process. It will either succeed and return a result containing // the PID of the new process, or else throw a RuntimeException. boolean isActivityProcess = (entryPoint == null); if (entryPoint == null) entryPoint = "android.app.ActivityThread"; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " + app.processName); checkTime(startTime, "startProcess: asking zygote to start proc"); Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, app.info.dataDir, entryPointArgs);……}

進入到ActivityThread的main方法,首先進行一些初始化(包括參數設置、性能安全監控之類的),然后初始化Looper(Looper、Handler消息機制),創建ActivityThread,存儲線程的Handler,最后啟動Looper監聽消息。

ActivityThread通過Binder將ApplicationThread對象傳遞給ActivityManagerService,并完成啟動Activity的后續工作

到這里ActivityThread的初始化就完成了,但是回想一下前面的工作,我們現在將Launcher切換到了pause狀態,但由于目標應用進程和線程還沒有創建,所以我們還沒有把目標應用的MainActivity切換到resume狀態。所以就意味著,我們還需要進行應用進程和ActivityManagerService所在的system_server進程的通信,告訴ActivityManagerService我們已經創建好了進程和線程,接下來把MainActivity狀態切換到resume中,就能打開應用了。

這一步工作在哪里完成的呢?

thread.attach(false)

final IActivityManager mgr = ActivityManagerNative.getDefault();看到這行代碼有沒有熟悉的感覺?前面我們就通過ActivityManagerNative.getDefault()取得ActivityManagerService的代理對象,完成了啟動MainActivity的前期工作。這里再次取得代理對象,并調用了ActivityManagerService的attachApplication方法。

public static void main(String[] args) {…… Process.setArgV0("<pre-initialized>"); 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");}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) { // Ignore }…… } else {…… }……}

進入到ActivityManagerService的attachApplication方法,前面我們已經存儲過目標應用的pid-ProcessRecord鍵值對了,因此這里的app不為null。然后向下執行,激活ProcessRecord并將ProcessRecord綁定到應用進程。然后通過Binder(thread.bindApplication)將各種應用相關信息傳遞給應用進程,進行應用進程一些必要的設置。最后調用mStackSupervisor.attachApplicationLocked(app)方法將ApplicationThread對象傳遞給ActivityManagerService方便后續應用進程與ActivityManagerService的通信(如:將MainActivity切換到resume狀態),并完成啟動應用的所有工作。

@Overridepublic 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) { // Find the application record that is being attached... either via // the pid if we are running in multiple processes, or just pull the // next app record if we are emulating process with anonymous threads. ProcessRecord app; if (pid != MY_PID && pid >= 0) { synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); } } else { app = null; } // 此時app不為null,跳過 if (app == null) {…… } // 清除ProcessRecord中的信息,以確保沒有不相關進程的信息 if (app.thread != null) { handleAppDiedLocked(app, true, true); } // Tell the process all about itself. if (DEBUG_ALL) Slog.v( TAG, "Binding process pid " + pid + " to record " + app); // 注冊DeathRecipient,確保應用意外關閉時系統進程能收到通知 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);…… // 調用ActivityThread的bindApplication方法 try {…… thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profilerInfo, app.instrumentationArguments, app.instrumentationWatcher, app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked()); updateLruProcessLocked(app, false, null); app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); } catch (Exception e) {…… }…… // See if the top visible activity is waiting to run in this process... if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { Slog.wtf(TAG, "Exception thrown launching activities in " + app, e); badApp = true; } } // Find any services that should be running in this process... if (!badApp) {…… } // Check if a next-broadcast receiver is in this process... if (!badApp && isPendingBroadcastProcessLocked(pid)) {…… } // Check whether the next backup agent is in this process... if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) {…… }…… return true;}

ActivityManagerService通知ActivityThread啟動Activity

回到ActivityThread,先看bindApplication方法,就是將上面傳的數據存儲在AppBindData中,然后通過Message、Handler發送出去,我們再看看Handler是怎么處理H.BIND_APPLICATION類型的Message的。

public final void bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, ProfilerInfo profilerInfo, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {…… AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.instrumentationUiAutomationConnection = instrumentationUiConnection; data.debugMode = debugMode; data.enableOpenGlTrace = enableOpenGlTrace; data.restrictedBackupMode = isRestrictedBackupMode; data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; sendMessage(H.BIND_APPLICATION, data);}

這里我就直接截出代碼段了,最終調用了handleBindApplication方法。

case BIND_APPLICATION: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication"); AppBindData data = (AppBindData)msg.obj; handleBindApplication(data); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;

進入到handleBindApplication方法,首先進行一些初始化操作,然后取出data中存儲的進程名,為應用進程設置進程名。然后創建應用的Context,也就是應用的運行上下文,通過Context我們可以訪問到應用相關的各種資源文件(圖片、布局文件等等)。然后創建進程的Instrumentation對象、Application對象,裝載Provider,最終調用mInstrumentation.callApplicationOnCreate(app)方法,也就是調用我們開發App時,Application類(或子類)的onCreate()方法。

至此應用進程相關的初始化和相關的設置就完成了,接下來只要切換MainActivity的狀態就大功告成了。

private void handleBindApplication(AppBindData data) {…… // send up app name; do this *before* waiting for debugger Process.setArgV0(data.processName); android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId());……設置進程運行信息…… final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);……繼續進程的初始化…… if (data.instrumentationName != null) { …… } else { mInstrumentation = new Instrumentation(); }…… try { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; // don't bring up providers in restricted mode; they may depend on the // app's custom Application class if (!data.restrictedBackupMode) { List<ProviderInfo> providers = data.providers; if (providers != null) { installContentProviders(app, providers); // For process that contains content providers, we want to // ensure that the JIT is enabled "at some point". mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); } }…… try { mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!mInstrumentation.onException(app, e)) { throw new RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), e); } } } finally { StrictMode.setThreadPolicy(savedPolicy); }}

進入到ActivityStackSupervisor類的attachApplicationLocked方法,該方法遍歷mActivityDisplays列表得到當前所有ActivityStack,然后取得前臺ActivityStack棧頂的ActivityRecord,不為空則啟動該對該ActivityRecord調用realStartActivityLocked方法。

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) { Slog.w(TAG, "Exception in new application when starting activity " + hr.intent.getComponent().flattenToShortString(), e); throw e; } } } } } if (!didSomething) { ensureActivitiesVisibleLocked(null, 0); } return didSomething;}

ActivityThread調度執行Activity生命周期方法,完成Activity的啟動

進入到realStartActivityLocked方法,進行一些前期處理后調用ActivityThread的scheduleLaunchActivity方法,將創建ActivityClientRecord存儲我們傳入的各種應用相關的數據,通過Handler機制發送。當Handler接收到LAUNCH_ACTIVITY類型的消息時,執行handleLaunchActivity方法。

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);@Overridepublic 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);}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;

進入到handleLaunchActivity方法,首先進行參數設置,然后調用performLaunchActivity方法得到目標應用的MainActivity并使其分別調用onCreate、onStart方法,然后調用handleResumeActivity方法讓MainActivity進入resume狀態,完成啟動。

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {…… Activity a = performLaunchActivity(r, customIntent); if (a != null) { r.createdConfig = new Configuration(mConfiguration); Bundle oldState = r.state; handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed);…… } else {…… }}private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { // 初始化設置…… // 通過反射獲得MainActivity 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 {…… if (activity != null) { // 為MainActivity創建運行的上下文環境Context,并與Activity綁定 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);…… // 回調MainActivity生命周期的onCreate方法 if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); }…… // 回調MainActivity生命周期的onStart方法 if (!r.activity.mFinished) { activity.performStart(); r.stopped = false; }…… } 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;}final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); mSomeActivitiesChanged = true; // TODO Push resumeArgs into the activity for consideration ActivityClientRecord r = performResumeActivity(token, clearHide);……}

總結

用文字總結App啟動流程可以分為以下步驟:

Launcher通過Binder建立Launcher所在進程與system_server進程(ActivityManagerService所在進程)的通信,通知ActivityManagerService即將要啟動一個ActivityActivityManagerService通過Binder讓Launcher進入pause狀態Launcher進入pause狀態后,通過Binder告知ActivityManagerService,隨后ActivityManagerService創建一個進程(將要打開的應用進程)并啟動ActivityThread(應用的UI線程)ActivityThread通過Binder將ApplicationThread類型的Binder對象傳遞給ActivityManagerService,方便ActivityManagerService后續與其的通信準備工作完成后,ActivityManagerService通知ActivityThread啟動ActivityActivityThread調度執行Activity的生命周期方法,完成啟動Activity的工作

相關函數調用的時序圖:


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 天津市| 芜湖县| 长垣县| 虎林市| 石柱| 旌德县| 青川县| 韶山市| 阳山县| 江都市| 镇原县| 泌阳县| 阿克| 休宁县| 叙永县| 从江县| 南投县| 阜平县| 泰来县| 汤原县| 海淀区| 潼关县| 衡东县| 营口市| 嘉义县| 辉县市| 两当县| 广水市| 东宁县| 衡阳县| 香格里拉县| 高台县| 灵宝市| 台北市| 石城县| 白玉县| 宿松县| 新平| 兴化市| 奎屯市| 丰都县|