我們自己的啟動Activity方法
調用Activity對象的方法
@Override public void startActivity(Intent intent) { this.startActivity(intent, null); }
繼續調用Activity對象方法
@Override public void startActivity(Intent intent, @Nullable Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { // Note we want to go through this call for compatibility with // applications that may have overridden the method. startActivityForResult(intent, -1); } }
繼續調用Activity對象方法
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) { startActivityForResult(intent, requestCode, null); }
繼續調用Activity對象方法
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) {//mParent指的是ActivityGroup,可以在一個界面里嵌套多個Activity。隨着版本的升級,在API13以后就廢棄掉了。 options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(//調用了方法Instrumentation$execStartActivity,因為mParent為null。 this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult(//mMainThread是一個ActivityThread對象,該對象初始化在當前Activity的attach方法中。 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); } } }
在startActivityForResult這個方法中 我們發現如果
requestCode > 0會把標志位mStartedActivity改成true(這個關於)
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); }
這個方法是否回調。
在回頭查看啟動的重點:根據上面的注釋我們繼續查看Instrumentation的execStartActivity方法
1 public void execStartActivitiesAsUser(Context who, IBinder contextThread, 2 IBinder token, Activity target, Intent[] intents, Bundle options, 3 int userId) { 4 IApplicationThread whoThread = (IApplicationThread) contextThread;//ActivityThread的ApplictionThread對象 5 if (mActivityMonitors != null) { 6 synchronized (mSync) { 7 final int N = mActivityMonitors.size(); 8 for (int i=0; i<N; i++) { 9 final ActivityMonitor am = mActivityMonitors.get(i);//List<ActivityMonitor> mActivityMonitors 10 ActivityResult result = null; 11 if (am.ignoreMatchingSpecificIntents()) { 12 result = am.onStartActivity(intents[0]);//這個方法返回的是null 13 } 14 if (result != null) { 15 am.mHits++; 16 return; 17 } else if (am.match(who, null, intents[0])) {//用於攔截任何已啟動的活動 18 am.mHits++; 19 if (am.isBlocking()) { 20 return; 21 } 22 break; 23 } 24 } 25 } 26 } 27 try { 28 String[] resolvedTypes = new String[intents.length]; 29 for (int i=0; i<intents.length; i++) { 30 intents[i].migrateExtraStreamToClipData(); 31 intents[i].prepareToLeaveProcess(who); 32 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver()); 33 } 34 int result = ActivityManager.getService() 35 .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes, 36 token, options, userId); 37 checkStartActivityResult(result, intents[0]); 38 } catch (RemoteException e) { 39 throw new RuntimeException("Failure from system", e); 40 } 41 }
第4行代碼:private class ApplicationThread extends IApplicationThread.Stub{}是在ActivityThread中ApplictionThread的構造方法、
通過代碼分析(有注釋)可知這里的重點事:
我們再來查看ActivityManager.getService()方法返回的對象:
1 public static IActivityManager getService() { 2 return IActivityManagerSingleton.get(); 3 } 4 5 private static final Singleton<IActivityManager> IActivityManagerSingleton = 6 new Singleton<IActivityManager>() { 7 @Override 8 protected IActivityManager create() { 9 final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); 10 final IActivityManager am = IActivityManager.Stub.asInterface(b); 11 return am; 12 } 13 };
返回的對象是一個IActivityManager,其中Singleton<T>是創建一個T的單列對象通過get()方法獲取T對象。所以這里獲取的是一個IActivityManager對象
這里的大概意思就是基於(Bidler機制)獲取ActivityManagerServer在應用進程的代理對象IActivityManager(這里需要了解Binder機制,會另外寫bidler機制)
所以這里的Instrumentation中的getMananger.getServer.startActivity 等價於--IActivityManager.startActivity----等價於ActivityManagerServer.startActivity方法。
繼續查看ActivityManagerServer對象的startActivity方法:
1 /** 2 * Instrumentaion 調用的是這個方法 3 * @return 返回值用於判斷Activity是否啟動 4 */ 5 @Override 6 public final int startActivity(IApplicationThread caller, String callingPackage, 7 Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, 8 int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) { 9 return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, 10 resultWho, requestCode, startFlags, profilerInfo, bOptions, 11 UserHandle.getCallingUserId()); 12 }
繼續查看startActivityAsUer方法
@Override public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) { enforceNotIsolatedCaller("startActivity"); //獲取userid userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null); // TODO: 在這里切換到用戶應用程序棧。(Switch to user app stacks here.) return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, null, null, bOptions, false, userId, null, null, "startActivityAsUser"); }
繼續查看mActivityStarter.startActivityMayWait方法,mActivityStarter是ActivityStarter對象

1 final int startActivityMayWait(IApplicationThread caller, int callingUid, 2 String callingPackage, Intent intent, String resolvedType, 3 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, 4 IBinder resultTo, String resultWho, int requestCode, int startFlags, 5 ProfilerInfo profilerInfo, WaitResult outResult, 6 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId, 7 IActivityContainer iContainer, TaskRecord inTask, String reason) { 8 // Refuse possible leaked file descriptors 9 if (intent != null && intent.hasFileDescriptors()) { 10 throw new IllegalArgumentException("File descriptors passed in Intent"); 11 } 12 //調用底層的方法 給ActivityMetricsLogger的INVALID_START_TIME賦值 13 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching(); 14 boolean componentSpecified = intent.getComponent() != null;//顯示啟動為true 15 16 // Save a copy in case ephemeral needs it 17 final Intent ephemeralIntent = new Intent(intent); 18 // Don't modify the client's object! 19 //為了不改變用戶的intent 20 intent = new Intent(intent); 21 if (componentSpecified 22 && intent.getData() != null 23 && Intent.ACTION_VIEW.equals(intent.getAction()) 24 && mService.getPackageManagerInternalLocked() 25 .isInstantAppInstallerComponent(intent.getComponent())) {//判斷是否調用系統功能 26 // intercept intents targeted directly to the ephemeral installer the 27 // ephemeral installer should never be started with a raw URL; instead 28 // adjust the intent so it looks like a "normal" instant app launch 29 intent.setComponent(null /*component*/); 30 componentSpecified = false; 31 } 32 //收集Intent所指向的Activity信息, 當存在多個可供選擇的Activity,則直接向用戶彈出resolveActivity 33 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId); 34 if (rInfo == null) { 35 UserInfo userInfo = mSupervisor.getUserInfo(userId);//UserInfo 保存了應用相關信息 名字 圖片.... 36 if (userInfo != null && userInfo.isManagedProfile()) {//不會執行(估計) 37 // Special case for managed profiles, if attempting to launch non-cryto aware 38 // app in a locked managed profile from an unlocked parent allow it to resolve 39 // as user will be sent via confirm credentials to unlock the profile. 40 UserManager userManager = UserManager.get(mService.mContext); 41 boolean profileLockedAndParentUnlockingOrUnlocked = false; 42 long token = Binder.clearCallingIdentity(); 43 try { 44 UserInfo parent = userManager.getProfileParent(userId); 45 profileLockedAndParentUnlockingOrUnlocked = (parent != null) 46 && userManager.isUserUnlockingOrUnlocked(parent.id) 47 && !userManager.isUserUnlockingOrUnlocked(userId); 48 } finally { 49 Binder.restoreCallingIdentity(token); 50 } 51 if (profileLockedAndParentUnlockingOrUnlocked) { 52 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 53 PackageManager.MATCH_DIRECT_BOOT_AWARE 54 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); 55 } 56 } 57 } 58 // 收集有關目標的信息。(Collect information about the target of the Intent.) 59 //收集目標intent的信息,在resolveActivity方法中與PKMS交互獲得 60 //該過程主要功能:通過resolveActivity來獲取ActivityInfo信息, 找到相應的Activity組件,並保存到intent對象,然后再進入startActivityLocked() 61 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo); 62 63 ActivityOptions options = ActivityOptions.fromBundle(bOptions); 64 ActivityStackSupervisor.ActivityContainer container = 65 (ActivityStackSupervisor.ActivityContainer)iContainer; 66 synchronized (mService) { 67 if (container != null && container.mParentActivity != null && 68 container.mParentActivity.state != RESUMED) { 69 // Cannot start a child activity if the parent is not resumed. 70 return ActivityManager.START_CANCELED; 71 } 72 final int realCallingPid = Binder.getCallingPid(); 73 final int realCallingUid = Binder.getCallingUid(); 74 int callingPid; 75 if (callingUid >= 0) { 76 callingPid = -1; 77 } else if (caller == null) { 78 callingPid = realCallingPid; 79 callingUid = realCallingUid; 80 } else { 81 callingPid = callingUid = -1; 82 } 83 84 final ActivityStack stack; 85 //取得需要啟動的ActivityStack棧 86 if (container == null || container.mStack.isOnHomeDisplay()) { 87 stack = mSupervisor.mFocusedStack; 88 } else { 89 stack = container.mStack; 90 } 91 stack.mConfigWillChange = globalConfig != null 92 && mService.getGlobalConfiguration().diff(globalConfig) != 0; 93 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 94 "Starting activity when config will change = " + stack.mConfigWillChange); 95 96 final long origId = Binder.clearCallingIdentity(); 97 98 if (aInfo != null && 99 (aInfo.applicationInfo.privateFlags 100 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { 101 // This may be a heavy-weight process! Check to see if we already 102 // have another, different heavy-weight process running. 103 //Androidmanifest.xml中的Application標簽可以聲明一個cantSaveState屬性,若設置,其將不享受系統提 104 //供的狀態保存/恢復功能。主要是為了保證用戶體驗的連續性 105 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) { 106 final ProcessRecord heavy = mService.mHeavyWeightProcess; 107 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid 108 || !heavy.processName.equals(aInfo.processName))) { 109 int appCallingUid = callingUid; 110 if (caller != null) { 111 ProcessRecord callerApp = mService.getRecordForAppLocked(caller); 112 if (callerApp != null) { 113 appCallingUid = callerApp.info.uid; 114 } else { 115 Slog.w(TAG, "Unable to find app for caller " + caller 116 + " (pid=" + callingPid + ") when starting: " 117 + intent.toString()); 118 ActivityOptions.abort(options); 119 return ActivityManager.START_PERMISSION_DENIED; 120 } 121 } 122 123 IIntentSender target = mService.getIntentSenderLocked( 124 ActivityManager.INTENT_SENDER_ACTIVITY, "android", 125 appCallingUid, userId, null, null, 0, new Intent[] { intent }, 126 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT 127 | PendingIntent.FLAG_ONE_SHOT, null); 128 129 Intent newIntent = new Intent(); 130 if (requestCode >= 0) { 131 // Caller is requesting a result. 132 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true); 133 } 134 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT, 135 new IntentSender(target)); 136 if (heavy.activities.size() > 0) { 137 ActivityRecord hist = heavy.activities.get(0); 138 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, 139 hist.packageName); 140 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, 141 hist.getTask().taskId); 142 } 143 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP, 144 aInfo.packageName); 145 newIntent.setFlags(intent.getFlags()); 146 newIntent.setClassName("android", 147 HeavyWeightSwitcherActivity.class.getName()); 148 intent = newIntent; 149 resolvedType = null; 150 caller = null; 151 callingUid = Binder.getCallingUid(); 152 callingPid = Binder.getCallingPid(); 153 componentSpecified = true; 154 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId); 155 aInfo = rInfo != null ? rInfo.activityInfo : null; 156 if (aInfo != null) { 157 aInfo = mService.getActivityInfoForUser(aInfo, userId); 158 } 159 } 160 } 161 } 162 final ActivityRecord[] outRecord = new ActivityRecord[1]; 163 //啟動Activity 164 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType, 165 aInfo, rInfo, voiceSession, voiceInteractor, 166 resultTo, resultWho, requestCode, callingPid, 167 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, 168 options, ignoreTargetSecurity, componentSpecified, outRecord, container, 169 inTask, reason); 170 171 Binder.restoreCallingIdentity(origId); 172 //如果配置Configration發生變化,則調用AMS的updateConfigurationLocked進行處理 173 if (stack.mConfigWillChange) { 174 // If the caller also wants to switch to a new configuration, 175 // do so now. This allows a clean switch, as we are waiting 176 // for the current activity to pause (so we will not destroy 177 // it), and have not yet started the next activity. 178 //如果調用方也希望切換到新配置 179 //現在就這樣做。這允許一個干凈的開關,因為我們正在等待 180 //為當前活動暫停(因此我們不會破壞) 181 //它還沒有啟動下一個活動。 182 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, 183 "updateConfiguration()"); 184 stack.mConfigWillChange = false; 185 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 186 "Updating to new configuration after starting activity."); 187 mService.updateConfigurationLocked(globalConfig, null, false); 188 } 189 190 if (outResult != null) { 191 outResult.result = res; 192 if (res == ActivityManager.START_SUCCESS) { 193 //將結果放入mWaitingActivityLaunced中保存 194 mSupervisor.mWaitingActivityLaunched.add(outResult); 195 do { 196 try { 197 //等待啟動結果 198 mService.wait(); 199 } catch (InterruptedException e) { 200 } 201 } while (outResult.result != START_TASK_TO_FRONT 202 && !outResult.timeout && outResult.who == null); 203 if (outResult.result == START_TASK_TO_FRONT) { 204 res = START_TASK_TO_FRONT; 205 } 206 } 207 if (res == START_TASK_TO_FRONT) { 208 final ActivityRecord r = outRecord[0]; 209 210 // ActivityRecord may represent a different activity, but it should not be in 211 // the resumed state. 212 if (r.nowVisible && r.state == RESUMED) { 213 outResult.timeout = false; 214 outResult.who = r.realActivity; 215 outResult.totalTime = 0; 216 outResult.thisTime = 0; 217 } else { 218 outResult.thisTime = SystemClock.uptimeMillis(); 219 mSupervisor.waitActivityVisible(r.realActivity, outResult); 220 // Note: the timeout variable is not currently not ever set. 221 do { 222 try { 223 //等待啟動結果 224 mService.wait(); 225 } catch (InterruptedException e) { 226 } 227 } while (!outResult.timeout && outResult.who == null); 228 } 229 } 230 } 231 232 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]); 233 return res; 234 } 235 }
這個方法內容比較多我們來查看重要的部分
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, outRecord, container, inTask, reason);
繼續查看startLocked方法
int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask, String reason) { if (TextUtils.isEmpty(reason)) { throw new IllegalArgumentException("Need to specify a reason."); } mLastStartReason = reason; mLastStartActivityTimeMs = System.currentTimeMillis(); mLastStartActivityRecord[0] = null; mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord, container, inTask); if (outActivity != null) { // mLastStartActivityRecord[0] is set in the call to startActivity above. outActivity[0] = mLastStartActivityRecord[0]; } return mLastStartActivityResult; }
繼續查看startActivity方法:

/** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */ private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask) { int err = ActivityManager.START_SUCCESS; // Pull the optional Ephemeral Installer-only bundle out of the options early. final Bundle verificationBundle = options != null ? options.popAppVerificationBundle() : null; ProcessRecord callerApp = null; if (caller != null) {//如果caller不為空,從AMS中找到它所屬的ProcessRecord即進程,本文此處為null callerApp = mService.getRecordForAppLocked(caller); if (callerApp != null) { callingPid = callerApp.pid; callingUid = callerApp.info.uid; } else { Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting: " + intent.toString()); err = ActivityManager.START_PERMISSION_DENIED; } } final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0; if (err == ActivityManager.START_SUCCESS) { Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false) + "} from uid " + callingUid); } //sourceRecord用於描述啟動目標Activity的那個Activity ActivityRecord sourceRecord = null; //resultRecord用於描述接收啟動結果的Activity,即onActivityResult將被調用以通知啟動結果 ActivityRecord resultRecord = null; if (resultTo != null) { sourceRecord = mSupervisor.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; } } } //獲取Intent設置的啟動標志 final int launchFlags = intent.getFlags(); //此部分與LaunchMode類似,它用於控制Activity啟動結果的通知 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) { // Transfer the result target from the source activity to the new // one being started, including any failures. if (requestCode >= 0) { ActivityOptions.abort(options); return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT; } resultRecord = sourceRecord.resultTo; if (resultRecord != null && !resultRecord.isInStackLocked()) { resultRecord = null; } resultWho = sourceRecord.resultWho; requestCode = sourceRecord.requestCode; sourceRecord.resultTo = null; if (resultRecord != null) { resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode); } if (sourceRecord.launchedFromUid == callingUid) { // The new activity is being launched from the same uid as the previous // activity in the flow, and asking to forward its result back to the // previous. In this case the activity is serving as a trampoline between // the two, so we also want to update its launchedFromPackage to be the // same as the previous activity. Note that this is safe, since we know // these two packages come from the same uid; the caller could just as // well have supplied that same package name itself. This specifially // deals with the case of an intent picker/chooser being launched in the app // flow to redirect to an activity picked by the user, where we want the final // activity to consider it to have been launched by the previous app activity. callingPackage = sourceRecord.launchedFromPackage; } } if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) { // We couldn't find a class that can handle the given Intent. // That's the end of that! err = ActivityManager.START_INTENT_NOT_RESOLVED; } if (err == ActivityManager.START_SUCCESS && aInfo == null) { // We couldn't find the specific class specified in the Intent. // Also the end of the line. err = ActivityManager.START_CLASS_NOT_FOUND; } if (err == ActivityManager.START_SUCCESS && sourceRecord != null && sourceRecord.getTask().voiceSession != null) { // If this activity is being launched as part of a voice session, we need // to ensure that it is safe to do so. If the upcoming activity will also // be part of the voice session, we can only launch it if it has explicitly // said it supports the VOICE category, or it is a part of the calling app. if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) { try { intent.addCategory(Intent.CATEGORY_VOICE); if (!AppGlobals.getPackageManager().activitySupportsIntent( intent.getComponent(), intent, resolvedType)) { Slog.w(TAG, "Activity being started in current voice task does not support voice: " + intent); err = ActivityManager.START_NOT_VOICE_COMPATIBLE; } } catch (RemoteException e) { Slog.w(TAG, "Failure checking voice capabilities", e); err = ActivityManager.START_NOT_VOICE_COMPATIBLE; } } } if (err == ActivityManager.START_SUCCESS && voiceSession != null) { // If the caller is starting a new voice session, just make sure the target // is actually allowing it to run this way. try { if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(), intent, resolvedType)) { Slog.w(TAG, "Activity being started in new voice task does not support: " + intent); err = ActivityManager.START_NOT_VOICE_COMPATIBLE; } } catch (RemoteException e) { Slog.w(TAG, "Failure checking voice capabilities", e); err = ActivityManager.START_NOT_VOICE_COMPATIBLE; } } final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack(); if (err != START_SUCCESS) { if (resultRecord != null) { resultStack.sendActivityResultLocked( -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null); } ActivityOptions.abort(options); return err; } boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho, requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp, resultRecord, resultStack, options); abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid, callingPid, resolvedType, aInfo.applicationInfo); if (mService.mController != null) { try { // The Intent we give to the watcher has the extra data // stripped off, since it can contain private information. Intent watchIntent = intent.cloneFilter(); abort |= !mService.mController.activityStarting(watchIntent, aInfo.applicationInfo.packageName); } catch (RemoteException e) { mService.mController = null; } } mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage); mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid, options); intent = mInterceptor.mIntent; rInfo = mInterceptor.mRInfo; aInfo = mInterceptor.mAInfo; resolvedType = mInterceptor.mResolvedType; inTask = mInterceptor.mInTask; callingPid = mInterceptor.mCallingPid; callingUid = mInterceptor.mCallingUid; options = mInterceptor.mActivityOptions; if (abort) { if (resultRecord != null) { resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null); } // We pretend to the caller that it was really started, but // they will just get a cancel result. ActivityOptions.abort(options); return START_SUCCESS; } // If permissions need a review before any of the app components can run, we // launch the review activity and pass a pending intent to start the activity // we are to launching now after the review is completed. if (mService.mPermissionReviewRequired && aInfo != null) { if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired( aInfo.packageName, userId)) { IIntentSender target = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, callingUid, userId, null, null, 0, new Intent[]{intent}, new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT, null); final int flags = intent.getFlags(); Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); newIntent.setFlags(flags | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName); newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target)); if (resultRecord != null) { newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true); } intent = newIntent; resolvedType = null; callingUid = realCallingUid; callingPid = realCallingPid; rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId); aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/); if (DEBUG_PERMISSIONS_REVIEW) { Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false) + "} from uid " + callingUid + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) : (container.mActivityDisplay == null ? DEFAULT_DISPLAY : container.mActivityDisplay.mDisplayId))); } } } // If we have an ephemeral app, abort the process of launching the resolved intent. // Instead, launch the ephemeral installer. Once the installer is finished, it // starts either the intent we resolved here [on install error] or the ephemeral // app [on install success]. if (rInfo != null && rInfo.auxiliaryInfo != null) { intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent, callingPackage, verificationBundle, resolvedType, userId); resolvedType = null; callingUid = realCallingUid; callingPid = realCallingPid; aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/); } ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid, callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor, container, options, sourceRecord); if (outActivity != null) { outActivity[0] = r; } if (r.appTimeTracker == null && sourceRecord != null) { // If the caller didn't specify an explicit time tracker, we want to continue // tracking under any it has. r.appTimeTracker = sourceRecord.appTimeTracker; } final ActivityStack stack = mSupervisor.mFocusedStack; if (voiceSession == null && (stack.mResumedActivity == null || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) { if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, realCallingPid, realCallingUid, "Activity start")) { PendingActivityLaunch pal = new PendingActivityLaunch(r, sourceRecord, startFlags, stack, callerApp); mPendingActivityLaunches.add(pal); ActivityOptions.abort(options); return ActivityManager.START_SWITCHES_CANCELED; } } if (mService.mDidAppSwitch) { // This is the second allowed switch since we stopped switches, // so now just generally allow switches. Use case: user presses // home (switches disabled, switch to home, mDidAppSwitch now true); // user taps a home icon (coming from home so allowed, we hit here // and now allow anyone to switch again). mService.mAppSwitchesAllowedTime = 0; } else { mService.mDidAppSwitch = true; } doPendingActivityLaunchesLocked(false); return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask, outActivity); }
這個方法內容比較多會去檢查Activity是否在Mainfest.xml中是否注冊等,假如一切正常,我們接下來查看關鍵部分:
doPendingActivityLaunchesLocked(false); return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask, outActivity);
先查看dopeingActivityLauchesLocked方法
final void doPendingActivityLaunchesLocked(boolean doResume) { while (!mPendingActivityLaunches.isEmpty()) { final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0); final boolean resume = doResume && mPendingActivityLaunches.isEmpty(); try { startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null, null /*outRecords*/); } catch (Exception e) { Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e); pal.sendErrorResult(e.getMessage()); } } }
到這里我們發現
這里都會去執行startActivity方法只是傳的參數不一樣,我們繼續查看startActivity方法
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { int result = START_CANCELED; try { mService.mWindowManager.deferSurfaceLayout(); result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, outActivity); } finally { // If we are not able to proceed, disassociate the activity from the task. Leaving an // activity in an incomplete state can lead to issues, such as performing operations // without a window container. if (!ActivityManager.isStartResultSuccessful(result) && mStartActivity.getTask() != null) { mStartActivity.getTask().removeActivity(mStartActivity); } mService.mWindowManager.continueSurfaceLayout(); } postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord, mTargetStack);//這個與期待應用進程有關。也是調用2次startActivity的原因(可能理解有誤) return result; }
我們繼續查看
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
startActivityUnChecked方法

// Note: This method should only be called from {@link startActivity}. private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor); computeLaunchingTaskFlags(); computeSourceStack(); mIntent.setFlags(mLaunchFlags); ActivityRecord reusedActivity = getReusableIntentActivity(); final int preferredLaunchStackId = (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID; final int preferredLaunchDisplayId = (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY; if (reusedActivity != null) { // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but // still needs to be a lock task mode violation since the task gets cleared out and // the device would otherwise leave the locked task. if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(), (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) { mSupervisor.showLockTaskToast(); Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode"); return START_RETURN_LOCK_TASK_MODE_VIOLATION; } if (mStartActivity.getTask() == null) { mStartActivity.setTask(reusedActivity.getTask()); } if (reusedActivity.getTask().intent == null) { // This task was started because of movement of the activity based on affinity... // Now that we are actually launching it, we can assign the base intent. reusedActivity.getTask().setIntent(mStartActivity); } // This code path leads to delivering a new intent, we want to make sure we schedule it // as the first operation, in case the activity will be resumed as a result of later // operations. if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0 || isDocumentLaunchesIntoExisting(mLaunchFlags) || mLaunchSingleInstance || mLaunchSingleTask) { final TaskRecord task = reusedActivity.getTask(); // In this situation we want to remove all activities from the task up to the one // being started. In most cases this means we are resetting the task to its initial // state. final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity, mLaunchFlags); // The above code can remove {@code reusedActivity} from the task, leading to the // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The // task reference is needed in the call below to // {@link setTargetStackAndMoveToFrontIfNeeded}. if (reusedActivity.getTask() == null) { reusedActivity.setTask(task); } if (top != null) { if (top.frontOfTask) { // Activity aliases may mean we use different intents for the top activity, // so make sure the task now has the identity of the new intent. top.getTask().setIntent(mStartActivity); } ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask()); top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage); } } sendPowerHintForLaunchStartIfNeeded(false /* forceSend */); reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity); final ActivityRecord outResult = outActivity != null && outActivity.length > 0 ? outActivity[0] : null; // When there is a reused activity and the current result is a trampoline activity, // set the reused activity as the result. if (outResult != null && (outResult.finishing || outResult.noDisplay)) { outActivity[0] = reusedActivity; } if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and the client said not to do anything // if that is the case, so this is it! And for paranoia, make sure we have // correctly resumed the top activity. resumeTargetStackIfNeeded(); return START_RETURN_INTENT_TO_CALLER; } setTaskFromIntentActivity(reusedActivity); if (!mAddingToTask && mReuseTask == null) { // We didn't do anything... but it was needed (a.k.a., client don't use that // intent!) And for paranoia, make sure we have correctly resumed the top activity. resumeTargetStackIfNeeded(); if (outActivity != null && outActivity.length > 0) { outActivity[0] = reusedActivity; } return START_TASK_TO_FRONT; } } if (mStartActivity.packageName == null) { final ActivityStack sourceStack = mStartActivity.resultTo != null ? mStartActivity.resultTo.getStack() : null; if (sourceStack != null) { sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo, mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null /* data */); } ActivityOptions.abort(mOptions); return START_CLASS_NOT_FOUND; } // If the activity being launched is the same as the one currently at the top, then // we need to check if it should only be launched once. final ActivityStack topStack = mSupervisor.mFocusedStack; final ActivityRecord topFocused = topStack.topActivity(); final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); final boolean dontStart = top != null && mStartActivity.resultTo == null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId && top.app != null && top.app.thread != null && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop || mLaunchSingleTask); if (dontStart) { ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask()); // For paranoia, make sure we have correctly resumed the top activity. topStack.mLastPausedActivity = null; if (mDoResume) { mSupervisor.resumeFocusedStackTopActivityLocked(); } ActivityOptions.abort(mOptions); if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and the client said not to do // anything if that is the case, so this is it! return START_RETURN_INTENT_TO_CALLER; } top.deliverNewIntentLocked( mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage); // Don't use mStartActivity.task to show the toast. We're not starting a new activity // but reusing 'top'. Fields in mStartActivity may not be fully initialized. mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId, preferredLaunchDisplayId, topStack.mStackId); return START_DELIVERED_TO_TOP; } boolean newTask = false; final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null) ? mSourceRecord.getTask() : null; // Should this be considered a new task? int result = START_SUCCESS; if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { newTask = true; result = setTaskFromReuseOrCreateNewTask( taskToAffiliate, preferredLaunchStackId, topStack); } else if (mSourceRecord != null) { result = setTaskFromSourceRecord(); } else if (mInTask != null) { result = setTaskFromInTask(); } else { // This not being started from an existing activity, and not part of a new task... // just put it in the top task, though these days this case should never happen. setTaskToCurrentTopOrCreateNewTask(); } if (result != START_SUCCESS) { return result; } mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName, mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId); mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent, mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid)); if (mSourceRecord != null) { mStartActivity.getTask().setTaskToReturnTo(mSourceRecord); } if (newTask) { EventLog.writeEvent( EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.getTask().taskId); } ActivityStack.logStartActivity( EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask()); mTargetStack.mLastPausedActivity = null; sendPowerHintForLaunchStartIfNeeded(false /* forceSend */); mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition, mOptions); if (mDoResume) { final ActivityRecord topTaskActivity = mStartActivity.getTask().topRunningActivityLocked(); if (!mTargetStack.isFocusable() || (topTaskActivity != null && topTaskActivity.mTaskOverlay && mStartActivity != topTaskActivity)) { // If the activity is not focusable, we can't resume it, but still would like to // make sure it becomes visible as it starts (this will also trigger entry // animation). An example of this are PIP activities. // Also, we don't want to resume activities in a task that currently has an overlay // as the starting activity just needs to be in the visible paused state until the // over is removed. mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); // Go ahead and tell window manager to execute app transition for this activity // since the app transition will not be triggered through the resume channel. mWindowManager.executeAppTransition(); } else { // If the target stack was not previously focusable (previous top running activity // on that stack was not visible) then any prior calls to move the stack to the // will not update the focused stack. If starting the new activity now allows the // task stack to be focusable, then ensure that we now update the focused stack // accordingly. if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityUnchecked"); } mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); } } else { mTargetStack.addRecentActivityLocked(mStartActivity); } mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack); mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId, preferredLaunchDisplayId, mTargetStack.mStackId); return START_SUCCESS; }
這個方法內容比較多,我們查看
繼續查看resumeFocusedStackTopActivityLocked方法屬於(ActivityStackSupervisor)對象
boolean resumeFocusedStackTopActivityLocked() { return resumeFocusedStackTopActivityLocked(null, null, null); }
調用的是3個參數的重載方法
boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (targetStack != null && isFocusedStack(targetStack)) { return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } final ActivityRecord r = mFocusedStack.topRunningActivityLocked(); if (r == null || r.state != RESUMED) { mFocusedStack.resumeTopActivityUncheckedLocked(null, null); } else if (r.state == RESUMED) { // Kick off any lingering app transitions form the MoveTaskToFront operation. mFocusedStack.executeAppTransition(targetOptions); } return false; }
繼續查看resumeTopAcitivityUncheckLocked方法(ActivityStatk對象)
1 boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { 2 if (mStackSupervisor.inResumeTopActivity) { 3 // Don't even start recursing. 4 return false; 5 } 6 7 boolean result = false; 8 try { 9 // Protect against recursion. 10 mStackSupervisor.inResumeTopActivity = true; 11 result = resumeTopActivityInnerLocked(prev, options); 12 } finally { 13 mStackSupervisor.inResumeTopActivity = false; 14 } 15 // When resuming the top activity, it may be necessary to pause the top activity (for 16 // example, returning to the lock screen. We suppress the normal pause logic in 17 // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the end. 18 // We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here to ensure 19 // any necessary pause logic occurs. 20 mStackSupervisor.checkReadyForSleepLocked(); 21 22 return result; 23 }
繼續查看resumeTopActivityInnerLocked方法

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { if (!mService.mBooting && !mService.mBooted) { // Not ready yet! return false; } // Find the next top-most activity to resume in this stack that is not finishing and is // focusable. If it is not focusable, we will fall into the case below to resume the // top activity in the next focusable task. final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */); final boolean hasRunningActivity = next != null; final ActivityRecord parent = mActivityContainer.mParentActivity; final boolean isParentNotResumed = parent != null && parent.state != ActivityState.RESUMED; if (hasRunningActivity && (isParentNotResumed || !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; } mStackSupervisor.cancelInitializingActivities(); // Remember how we'll process this pause/resume situation, and ensure // that the state is reset however we wind up proceeding. final boolean userLeaving = mStackSupervisor.mUserLeaving; mStackSupervisor.mUserLeaving = false; if (!hasRunningActivity) { // There are no activities left in the stack, let's look somewhere else. return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities"); } next.delayedResume = false; // If the top activity is the resumed one, nothing to do. 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. executeAppTransition(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Top activity resumed " + next); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } final TaskRecord nextTask = next.getTask(); final TaskRecord prevTask = prev != null ? prev.getTask() : null; if (prevTask != null && prevTask.getStack() == 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"); return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(prev, "prevFinished"); } } // If we are sleeping, and there is no resumed activity, and the top // activity is paused, well that is the state we want. if (mService.isSleepingOrShuttingDownLocked() && mLastPausedActivity == next && mStackSupervisor.allPausedActivitiesComplete()) { // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. executeAppTransition(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.mUserController.hasStartedUserState(next.userId)) { Slog.w(TAG, "Skipping resume of top activity " + next + ": user " + next.userId + " is stopped"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false; } // The activity may be waiting for stop, but that is no longer // appropriate for it. mStackSupervisor.mStoppingActivities.remove(next); mStackSupervisor.mGoingToSleepActivities.remove(next); next.sleeping = false; mStackSupervisor.mActivitiesWaitingForVisibleActivity.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; } mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid); boolean lastResumedCanPip = false; final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack(); if (lastFocusedStack != null && lastFocusedStack != this) { // So, why aren't we using prev here??? See the param comment on the method. prev doesn't // represent the last resumed activity. However, the last focus stack does if it isn't null. final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity; lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState( "resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */); } // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity // to be paused, while at the same time resuming the new resume activity only if the // previous activity can't go into Pip since we want to give Pip activities a chance to // enter Pip before resuming the next activity. final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0 && !lastResumedCanPip; boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false); if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity); pausing |= startPausingLocked(userLeaving, false, next, false); } if (pausing && !resumeWhilePausing) { 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; } else if (mResumedActivity == next && next.state == ActivityState.RESUMED && mStackSupervisor.allResumedActivitiesComplete()) { // It is possible for the activity to be resumed when we paused back stacks above if the // next activity doesn't have to wait for pause to complete. // So, nothing else to-do except: // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. executeAppTransition(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } // If the most recent activity was noHistory but was only stopped rather // than stopped+finished because the device went to sleep, we need to make // sure to finish it as we're making a new activity topmost. if (mService.isSleepingLocked() && mLastNoHistoryActivity != null && !mLastNoHistoryActivity.finishing) { if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + mLastNoHistoryActivity + " on new resume"); requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED, null, "resume-no-history", false); mLastNoHistoryActivity = null; } if (prev != null && prev != next) { if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev) && next != null && !next.nowVisible) { mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming top, waiting visible to hide: " + prev); } else { // The next activity is already visible, so hide the previous // activity's windows right now so we can show the new one ASAP. // We only do this if the previous is finishing, which should mean // it is on top of the one being resumed so hiding it quickly // is good. Otherwise, we want to do the normal route of allowing // the resumed activity to be shown so we can decide if the // previous should actually be hidden depending on whether the // new one is found to be full-screen or not. if (prev.finishing) { prev.setVisibility(false); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Not waiting for visible to hide: " + prev + ", waitingVisible=" + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev) + ", nowVisible=" + next.nowVisible); } else { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Previous already visible but still waiting to hide: " + prev + ", waitingVisible=" + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev) + ", nowVisible=" + next.nowVisible); } } } // Launching this app's activity, make sure the app is no longer // considered stopped. try { AppGlobals.getPackageManager().setPackageStoppedState( next.packageName, false, next.userId); /* TODO: Verify if correct userid */ } catch (RemoteException e1) { } catch (IllegalArgumentException e) { Slog.w(TAG, "Failed trying to unstop package " + next.packageName + ": " + e); } // We are starting up the next activity, so tell the window manager // that the previous one will be hidden soon. This way it can know // to ignore it when computing the desired screen orientation. boolean anim = true; if (prev != null) { if (prev.finishing) { if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare close transition: prev=" + prev); if (mNoAnimActivities.contains(prev)) { anim = false; mWindowManager.prepareAppTransition(TRANSIT_NONE, false); } else { mWindowManager.prepareAppTransition(prev.getTask() == next.getTask() ? TRANSIT_ACTIVITY_CLOSE : TRANSIT_TASK_CLOSE, false); } prev.setVisibility(false); } else { if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: prev=" + prev); if (mNoAnimActivities.contains(next)) { anim = false; mWindowManager.prepareAppTransition(TRANSIT_NONE, false); } else { mWindowManager.prepareAppTransition(prev.getTask() == next.getTask() ? TRANSIT_ACTIVITY_OPEN : next.mLaunchTaskBehind ? TRANSIT_TASK_OPEN_BEHIND : TRANSIT_TASK_OPEN, false); } } } else { if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous"); if (mNoAnimActivities.contains(next)) { anim = false; mWindowManager.prepareAppTransition(TRANSIT_NONE, false); } else { mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false); } } Bundle resumeAnimOptions = null; if (anim) { ActivityOptions opts = next.getOptionsForTargetActivityLocked(); if (opts != null) { resumeAnimOptions = opts.toBundle(); } next.applyOptionsLocked(); } else { next.clearOptionsLocked(); } ActivityStack lastStack = mStackSupervisor.getLastStack(); if (next.app != null && next.app.thread != null) { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.stopped + " visible=" + next.visible); // If the previous activity is translucent, force a visibility update of // the next activity, so that it's added to WM's opening app list, and // transition animation can be set up properly. // For example, pressing Home button with a translucent activity in focus. // Launcher is already visible in this case. If we don't add it to opening // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation. final boolean lastActivityTranslucent = lastStack != null && (!lastStack.mFullscreen || (lastStack.mLastPausedActivity != null && !lastStack.mLastPausedActivity.fullscreen)); // This activity is now becoming visible. if (!next.visible || next.stopped || lastActivityTranslucent) { next.setVisibility(true); } // schedule launch ticks to collect information about slow apps. next.startLaunchTickingLocked(); ActivityRecord lastResumedActivity = lastStack == null ? null :lastStack.mResumedActivity; ActivityState lastState = next.state; mService.updateCpuStats(); if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)"); setResumedActivityLocked(next, "resumeTopActivityInnerLocked"); mService.updateLruProcessLocked(next.app, true, null); updateLRUListLocked(next); mService.updateOomAdjLocked(); // Have the window manager re-evaluate the orientation of // the screen based on the new activity order. boolean notUpdated = true; if (mStackSupervisor.isFocusedStack(this)) { final Configuration config = mWindowManager.updateOrientationFromAppTokens( mStackSupervisor.getDisplayOverrideConfiguration(mDisplayId), next.mayFreezeScreenLocked(next.app) ? next.appToken : null, mDisplayId); if (config != null) { next.frozenBeforeDestroy = true; } notUpdated = !mService.updateDisplayOverrideConfigurationLocked(config, next, false /* deferResume */, mDisplayId); } if (notUpdated) { // The configuration update wasn't able to keep the existing // instance of the activity, and instead started a new one. // We should be all done, but let's just make sure our activity // is still at the top and schedule another run if something // weird happened. ActivityRecord nextNext = topRunningActivityLocked(); if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES, "Activity config changed during resume: " + next + ", new next: " + nextNext); if (nextNext != next) { // Do over! mStackSupervisor.scheduleResumeTopActivities(); } if (!next.visible || next.stopped) { next.setVisibility(true); } next.completeResumeLocked(); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } try { // Deliver all pending results. ArrayList<ResultInfo> a = next.results; if (a != null) { final int N = a.size(); if (!next.finishing && N > 0) { if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a); next.app.thread.scheduleSendResult(next.appToken, a); } } if (next.newIntents != null) { next.app.thread.scheduleNewIntent( next.newIntents, next.appToken, false /* andPause */); } // Well the app will no longer be stopped. // Clear app token stopped state in window manager if needed. next.notifyAppResumed(next.stopped); EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId, System.identityHashCode(next), next.getTask().taskId, next.shortComponentName); next.sleeping = false; mService.showUnsupportedZoomDialogIfNeededLocked(next); mService.showAskCompatModeDialogLocked(next); next.app.pendingUiClean = true; next.app.forceProcessStateUpTo(mService.mTopProcessState); next.clearOptionsLocked(); next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState, mService.isNextTransitionForward(), resumeAnimOptions); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next); } catch (Exception e) { // Whoops, need to restart this activity! if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to " + lastState + ": " + next); next.state = lastState; if (lastStack != null) { lastStack.mResumedActivity = lastResumedActivity; } Slog.i(TAG, "Restarting because process died: " + next); if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null && mStackSupervisor.isFrontStackOnDisplay(lastStack)) { next.showStartingWindow(null /* prev */, false /* newTask */, false /* taskSwitch */); } mStackSupervisor.startSpecificActivityLocked(next, true, false); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } // From this point on, if something goes wrong there is no way // to recover the activity. try { next.completeResumeLocked(); } catch (Exception e) { // If any exception gets thrown, toss away this // activity and try the next one. Slog.w(TAG, "Exception thrown during resume of " + next, e); requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null, "resume-exception", true); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } } else { // Whoops, need to restart this activity! if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; } else { if (SHOW_APP_STARTING_PREVIEW) { next.showStartingWindow(null /* prev */, false /* newTask */, false /* taskSwich */); } if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next); } if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next); mStackSupervisor.startSpecificActivityLocked(next, true, true); } if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; }
這個方法比較長,我們查看比較重要的部分
經過startPausingLocked系列處理 會去執行當前Activity的onPause方法。這里不做說明
我們繼續查看ActivityStackSupervisor對象的startSpecificActivityLocked方法
1 void startSpecificActivityLocked(ActivityRecord r, 2 boolean andResume, boolean checkConfig) { 3 // Is this activity's application already running? 4 ProcessRecord app = mService.getProcessRecordLocked(r.processName, 5 r.info.applicationInfo.uid, true); 6 7 r.getStack().setLaunchTime(r); 8 9 if (app != null && app.thread != null) { 10 try { 11 if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 12 || !"android".equals(r.info.packageName)) { 13 // Don't add this if it is a platform component that is marked 14 // to run in multiple processes, because this is actually 15 // part of the framework so doesn't make sense to track as a 16 // separate apk in the process. 17 app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, 18 mService.mProcessStats); 19 } 20 realStartActivityLocked(r, app, andResume, checkConfig); 21 return; 22 } catch (RemoteException e) { 23 Slog.w(TAG, "Exception when starting activity " 24 + r.intent.getComponent().flattenToShortString(), e); 25 } 26 27 // If a dead object exception was thrown -- fall through to 28 // restart the application. 29 } 30 31 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, 32 "activity", r.intent.getComponent(), false, false, true); 33 }
繼續查看20行調用的realStartActivityLocked方法

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { if (!allPausedActivitiesComplete()) { // While there are activities pausing we skipping starting any new activities until // pauses are complete. NOTE: that we also do this for activities that are starting in // the paused state because they will first be resumed then paused on the client side. if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE, "realStartActivityLocked: Skipping start of r=" + r + " some activities pausing..."); return false; } r.startFreezingScreenLocked(app, 0); if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */, true /* isTop */)) { // We only set the visibility to true if the activity is allowed to be visible based on // keyguard state. This avoids setting this into motion in window manager that is later // cancelled due to later calls to ensure visible activities that set visibility back to // false. r.setVisibility(true); } // schedule launch ticks to collect information about slow apps. r.startLaunchTickingLocked(); // Have the window manager re-evaluate the orientation of the screen based on the new // activity order. Note that as a result of this, it can call back into the activity // manager with a new orientation. We don't care about that, because the activity is not // currently running so we are just restarting it anyway. if (checkConfig) { final int displayId = r.getDisplayId(); final Configuration config = mWindowManager.updateOrientationFromAppTokens( getDisplayOverrideConfiguration(displayId), r.mayFreezeScreenLocked(app) ? r.appToken : null, displayId); // Deferring resume here because we're going to launch new activity shortly. // We don't want to perform a redundant launch of the same record while ensuring // configurations and trying to resume top activity of focused stack. mService.updateDisplayOverrideConfigurationLocked(config, r, true /* deferResume */, displayId); } if (mKeyguardController.isKeyguardLocked()) { r.notifyUnknownVisibilityLaunched(); } final int applicationInfoUid = (r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1; if ((r.userId != app.userId) || (r.appInfo.uid != applicationInfoUid)) { Slog.wtf(TAG, "User ID for activity changing for " + r + " appInfo.uid=" + r.appInfo.uid + " info.ai.uid=" + applicationInfoUid + " old=" + r.app + " new=" + app); } r.app = app; app.waitingToKill = null; r.launchCount++; r.lastLaunchTime = SystemClock.uptimeMillis(); if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r); int idx = app.activities.indexOf(r); if (idx < 0) { app.activities.add(r); } mService.updateLruProcessLocked(app, true, null); mService.updateOomAdjLocked(); final TaskRecord task = r.getTask(); if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE || task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) { setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false); } final ActivityStack stack = task.getStack(); try { if (app.thread == null) { throw new RemoteException(); } List<ResultInfo> results = null; List<ReferrerIntent> newIntents = null; if (andResume) { // We don't need to deliver new intents and/or set results if activity is going // to pause immediately after launch. results = r.results; newIntents = r.newIntents; } if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Launching: " + r + " icicle=" + r.icicle + " with results=" + results + " newIntents=" + newIntents + " andResume=" + andResume); EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.userId, System.identityHashCode(r), task.taskId, r.shortComponentName); if (r.isHomeActivity()) { // Home process is the root process of the task. mService.mHomeProcess = task.mActivities.get(0).app; } mService.notifyPackageUse(r.intent.getComponent().getPackageName(), PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY); r.sleeping = false; r.forceNewConfig = false; mService.showUnsupportedZoomDialogIfNeededLocked(r); mService.showAskCompatModeDialogLocked(r); r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo); ProfilerInfo profilerInfo = null; if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) { if (mService.mProfileProc == null || mService.mProfileProc == app) { mService.mProfileProc = app; final String profileFile = mService.mProfileFile; if (profileFile != null) { ParcelFileDescriptor profileFd = mService.mProfileFd; if (profileFd != null) { try { profileFd = profileFd.dup(); } catch (IOException e) { if (profileFd != null) { try { profileFd.close(); } catch (IOException o) { } profileFd = null; } } } profilerInfo = new ProfilerInfo(profileFile, profileFd, mService.mSamplingInterval, mService.mAutoStopProfiler, mService.mStreamingOutput); } } } app.hasShownUi = true; app.pendingUiClean = true; app.forceProcessStateUpTo(mService.mTopProcessState); // Because we could be starting an Activity in the system process this may not go across // a Binder interface which would create a new Configuration. Consequently we have to // always create a new Configuration here. final MergedConfiguration mergedConfiguration = new MergedConfiguration( mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration()); r.setLastReportedConfiguration(mergedConfiguration); app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global and // override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo); if ((app.info.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { // This may be a heavy-weight process! Note that the package // manager will ensure that only activity can run in the main // process of the .apk, which is the only thing that will be // considered heavy-weight. if (app.processName.equals(app.info.packageName)) { if (mService.mHeavyWeightProcess != null && mService.mHeavyWeightProcess != app) { Slog.w(TAG, "Starting new heavy weight process " + app + " when already running " + mService.mHeavyWeightProcess); } mService.mHeavyWeightProcess = app; Message msg = mService.mHandler.obtainMessage( ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG); msg.obj = r; mService.mHandler.sendMessage(msg); } } } catch (RemoteException e) { if (r.launchFailed) { // This is the second time we failed -- finish activity // and give up. Slog.e(TAG, "Second failure launching " + r.intent.getComponent().flattenToShortString() + ", giving up", e); mService.appDiedLocked(app); stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "2nd-crash", false); return false; } // This is the first time we failed -- restart process and // retry. r.launchFailed = true; app.activities.remove(r); throw e; } r.launchFailed = false; if (stack.updateLRUListLocked(r)) { Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list"); } if (andResume) { // As part of the process of launching, ActivityThread also performs // a resume. stack.minimalResumeActivityLocked(r); } else { // This activity is not starting in the resumed state... which should look like we asked // it to pause+stop (but remain visible), and it has done so and reported back the // current icicle and other state. if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r + " (starting in paused state)"); r.state = PAUSED; } // Launch the new version setup screen if needed. We do this -after- // launching the initial activity (that is, home), so that it can have // a chance to initialize itself while in the background, making the // switch back to it faster and look better. if (isFocusedStack(stack)) { mService.startSetupActivityLocked(); } // Update any services we are bound to that might care about whether // their client may have activities. if (r.app != null) { mService.mServices.updateServiceConnectionActivitiesLocked(r.app); } return true; }
這個方法比較長 只看重要部分:
其中app.thread是一個
這里又回歸到bilder機制 是以系統進程為客戶端,我們自己的進行為服務端。
IAPPlictionThread 就相當APP進程中ActivityThread中ApplictionThread的代理類,
這里實際執行的相當於:ApplictionThread的scheduleLaunchActivity方法。
我們繼續查看ApplictionThread中的scheduleLauchActivity方法
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) { updateProcessState(procState, false); ActivityClientRecord r = new ActivityClientRecord(); r.token = token; r.ident = ident; r.intent = intent; r.referrer = referrer; r.voiceInteractor = voiceInteractor; r.activityInfo = info; r.compatInfo = compatInfo; r.state = state; r.persistentState = persistentState; r.pendingResults = pendingResults; r.pendingIntents = pendingNewIntents; r.startsNotResumed = notResumed; r.isForward = isForward; r.profilerInfo = profilerInfo; r.overrideConfig = overrideConfig; updatePendingConfiguration(curConfig); sendMessage(H.LAUNCH_ACTIVITY, r); }
這里就是我們熟悉的Handler機制了,不過這個Handler是系統的H對象(繼續Handler)
我們繼續查看sendMessage方法(在ActivityThread對象中)
這里msg.what==H.LAUNCH_ACTIVITY
1 switch (msg.what) { 2 case LAUNCH_ACTIVITY: { 3 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); 4 final ActivityClientRecord r = (ActivityClientRecord) msg.obj; 5 6 r.packageInfo = getPackageInfoNoCheck( 7 r.activityInfo.applicationInfo, r.compatInfo); 8 handleLaunchActivity(r, null, "LAUNCH_ACTIVITY"); 9 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 10 } break;
這里去執行handleLaunchActivity方法

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); mSomeActivitiesChanged = true; if (r.profilerInfo != null) { mProfiler.setProfiler(r.profilerInfo); mProfiler.startProfiling(); } // Make sure we are running with the most recent config. handleConfigurationChanged(null, null); if (localLOGV) Slog.v( TAG, "Handling launch of " + r); // Initialize before creating the activity WindowManagerGlobal.initialize(); Activity a = performLaunchActivity(r, customIntent); if (a != null) { r.createdConfig = new Configuration(mConfiguration); reportSizeConfigurations(r); Bundle oldState = r.state; handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason); if (!r.activity.mFinished && r.startsNotResumed) { // The activity manager actually wants this one to start out paused, because it // needs to be visible but isn't in the foreground. We accomplish this by going // through the normal startup (because activities expect to go through onResume() // the first time they run, before their window is displayed), and then pausing it. // However, in this case we do -not- need to do the full pause cycle (of freezing // and such) because the activity manager assumes it can just retain the current // state it has. performPauseActivityIfNeeded(r, reason); // We need to keep around the original state, in case we need to be created again. // But we only do this for pre-Honeycomb apps, which always save their state when // pausing, so we can not have them save their state when restarting from a paused // state. For HC and later, we want to (and can) let the state be saved as the // normal part of stopping the activity. if (r.isPreHoneycomb()) { r.state = oldState; } } } else { // If there was an error, for any reason, tell the activity manager to stop us. try { ActivityManager.getService() .finishActivity(r.token, Activity.RESULT_CANCELED, null, Activity.DONT_FINISH_TASK_WITH_ACTIVITY); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } }
通過performLaunchActivity去創建一個Activity
performLaunchActivity方法下面分析,
如果我們創建的a不為null就去執行
也就是我們Activity中的onResume方法
如果a是null
就在向系統發生請求。
停止啟動Activity
我們再回過頭去查看performLaunchActivity方法

1 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { 2 // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); 3 4 ActivityInfo aInfo = r.activityInfo; 5 // 1.創建ActivityClientRecord對象時沒有對他的packageInfo賦值,所以它是null 6 if (r.packageInfo == null) { 7 r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, 8 Context.CONTEXT_INCLUDE_CODE); 9 } 10 //r.packageInfo ----> LoadedApk 11 12 ComponentName component = r.intent.getComponent(); 13 if (component == null) { 14 component = r.intent.resolveActivity( 15 mInitialApplication.getPackageManager()); 16 r.intent.setComponent(component); 17 } 18 19 if (r.activityInfo.targetActivity != null) { 20 component = new ComponentName(r.activityInfo.packageName, 21 r.activityInfo.targetActivity); 22 } 23 24 ContextImpl appContext = createBaseContextForActivity(r); 25 Activity activity = null; 26 try { 27 // 2.非常重要!!這個ClassLoader保存於LoadedApk對象中,它是用來加載我們寫的activity的加載器 28 java.lang.ClassLoader cl = appContext.getClassLoader(); 29 // 3.用加載器來加載activity類,這個會根據不同的intent加載匹配的activity 30 activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent); 31 StrictMode.incrementExpectedActivityCount(activity.getClass()); 32 r.intent.setExtrasClassLoader(cl); 33 r.intent.prepareToEnterProcess(); 34 if (r.state != null) { 35 r.state.setClassLoader(cl); 36 } 37 } catch (Exception e) { 38 // 4.這里的異常也是非常非常重要的!!!后面就根據這個提示找到突破口。。。 39 if (!mInstrumentation.onException(activity, e)) { 40 throw new RuntimeException( 41 "Unable to instantiate activity " + component 42 + ": " + e.toString(), e); 43 } 44 } 45 46 try { 47 Application app = r.packageInfo.makeApplication(false, mInstrumentation); 48 49 if (localLOGV) Slog.v(TAG, "Performing launch of " + r); 50 if (localLOGV) Slog.v( 51 TAG, r + ": app=" + app 52 + ", appName=" + app.getPackageName() 53 + ", pkg=" + r.packageInfo.getPackageName() 54 + ", comp=" + r.intent.getComponent().toShortString() 55 + ", dir=" + r.packageInfo.getAppDir()); 56 57 if (activity != null) { 58 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); 59 Configuration config = new Configuration(mCompatConfiguration); 60 if (r.overrideConfig != null) { 61 config.updateFrom(r.overrideConfig); 62 } 63 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " 64 + r.activityInfo.name + " with config " + config); 65 Window window = null; 66 if (r.mPendingRemoveWindow != null && r.mPreserveWindow) { 67 window = r.mPendingRemoveWindow; 68 r.mPendingRemoveWindow = null; 69 r.mPendingRemoveWindowManager = null; 70 } 71 appContext.setOuterContext(activity); 72 activity.attach(appContext, this, getInstrumentation(), r.token, 73 r.ident, app, r.intent, r.activityInfo, title, r.parent, 74 r.embeddedID, r.lastNonConfigurationInstances, config, 75 r.referrer, r.voiceInteractor, window, r.configCallback); 76 77 if (customIntent != null) { 78 activity.mIntent = customIntent; 79 } 80 r.lastNonConfigurationInstances = null; 81 checkAndBlockForNetworkAccess(); 82 activity.mStartedActivity = false; 83 int theme = r.activityInfo.getThemeResource(); 84 if (theme != 0) { 85 activity.setTheme(theme); 86 } 87 88 activity.mCalled = false; 89 // 從這里就會執行到我們通常看到的activity的生命周期的onCreate里面 90 if (r.isPersistable()) { 91 mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); 92 } else { 93 mInstrumentation.callActivityOnCreate(activity, r.state); 94 } 95 if (!activity.mCalled) { 96 throw new SuperNotCalledException( 97 "Activity " + r.intent.getComponent().toShortString() + 98 " did not call through to super.onCreate()"); 99 } 100 r.activity = activity; 101 r.stopped = true; 102 if (!r.activity.mFinished) { 103 activity.performStart(); 104 r.stopped = false; 105 } 106 if (!r.activity.mFinished) { 107 if (r.isPersistable()) { 108 if (r.state != null || r.persistentState != null) { 109 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, 110 r.persistentState); 111 } 112 } else if (r.state != null) { 113 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); 114 } 115 } 116 if (!r.activity.mFinished) { 117 activity.mCalled = false; 118 if (r.isPersistable()) { 119 mInstrumentation.callActivityOnPostCreate(activity, r.state, 120 r.persistentState); 121 } else { 122 mInstrumentation.callActivityOnPostCreate(activity, r.state); 123 } 124 if (!activity.mCalled) { 125 throw new SuperNotCalledException( 126 "Activity " + r.intent.getComponent().toShortString() + 127 " did not call through to super.onPostCreate()"); 128 } 129 } 130 } 131 r.paused = true; 132 133 mActivities.put(r.token, r); 134 135 } catch (SuperNotCalledException e) { 136 throw e; 137 138 } catch (Exception e) { 139 if (!mInstrumentation.onException(activity, e)) { 140 throw new RuntimeException( 141 "Unable to start activity " + component 142 + ": " + e.toString(), e); 143 } 144 } 145 146 return activity; 147 }
通過反射創建Activity 這里涉及的classLoader的加載機制:http://www.cnblogs.com/kangqi001/p/8318054.html 這里有介紹
再看下
Activity類中的方法
到這里基本就完成了Activity的創建
總結:Activity的啟動流程
1.(Activity)經過Activity的重載方法startActivity方法執行startActivityForResult方法(應用進程)
2.(Instrumentation)在執行execStartActivity方法(應用進程)
3.(ActivityManagerService)執行startActivity方法 --》atrtAcitivityAsUser方法(系統進程)
4.(ActivityStarter)執行startActivityMayWait方法 --》startActivityLocked方法 --》startActivity方法 --》
doPengActivityLaunchesLocked方法 --》startAcitivity方法(與上不是同一個方法)--》startActivityUnchecked方法 (系統進程)
5.(ActivityStackSupervisor)執行resumeFocusedStackkTopActivityLocked方法(系統進程)
6.(ActivityStack)執行resumeTopActivityUncheckedLocked方法 --》resumeTopActivityInnerLocked方法 --》 startPausingLocked(這個方法去執行ActivityStack棧頂Activity的OnPause方法)(系統進程)
7.(ActivityStackSupervisor)執行startSpecificActivityLocked方法 --》realStartActivityLocked方法(系統進程)
8.(ActivityThread$ApplictionThread)scheduleLaunchActivity方法(應用進程)
9.(ActivityThread)執行sendMessage方法 --》 handleLaunchActivity方法--》performLaunchActivity方法(應用進程)
到這里就創建完成了Activity