Android8.0(API26)之Activity启动流程(显示启动)

知识为进步之母,而进步又为富强之源泉。这篇文章主要讲述Android8.0(API26)之Activity启动流程(显示启动)相关的知识,希望能为你提供帮助。
 
【Android8.0(API26)之Activity启动流程(显示启动)】 
我们自己的启动Activity方法

Android8.0(API26)之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方法
1public void execStartActivitiesAsUser(Context who, IBinder contextThread, 2IBinder token, Activity target, Intent[] intents, Bundle options, 3int userId) { 4IApplicationThread whoThread = (IApplicationThread) contextThread; //ActivityThread的ApplictionThread对象 5if (mActivityMonitors != null) { 6synchronized (mSync) { 7final int N = mActivityMonitors.size(); 8for (int i=0; i< N; i++) { 9final ActivityMonitor am = mActivityMonitors.get(i); //List< ActivityMonitor> mActivityMonitors 10ActivityResult result = null; 11if (am.ignoreMatchingSpecificIntents()) { 12result = am.onStartActivity(intents[0]); //这个方法返回的是null 13} 14if (result != null) { 15am.mHits++; 16return; 17} else if (am.match(who, null, intents[0])) {//用于拦截任何已启动的活动 18am.mHits++; 19if (am.isBlocking()) { 20return; 21} 22break; 23} 24} 25} 26} 27try { 28String[] resolvedTypes = new String[intents.length]; 29for (int i=0; i< intents.length; i++) { 30intents[i].migrateExtraStreamToClipData(); 31intents[i].prepareToLeaveProcess(who); 32resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver()); 33} 34int result = ActivityManager.getService() 35.startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes, 36token, options, userId); 37checkStartActivityResult(result, intents[0]); 38} catch (RemoteException e) { 39throw new RuntimeException("Failure from system", e); 40} 41}

第4行代码:private class ApplicationThread extends IApplicationThread.Stub{}是在ActivityThread中ApplictionThread的构造方法、
通过代码分析(有注释)可知这里的重点事:

Android8.0(API26)之Activity启动流程(显示启动)

文章图片

 
我们再来查看ActivityManager.getService()方法返回的对象:
1public static IActivityManager getService() { 2return IActivityManagerSingleton.get(); 3} 4 5private static final Singleton< IActivityManager> IActivityManagerSingleton = 6new Singleton< IActivityManager> () { 7@Override 8protected IActivityManager create() { 9final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); 10final IActivityManager am = IActivityManager.Stub.asInterface(b); 11return 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 6public final int startActivity(IApplicationThread caller, String callingPackage, 7Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, 8int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) { 9return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, 10resultWho, requestCode, startFlags, profilerInfo, bOptions, 11UserHandle.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对象
Android8.0(API26)之Activity启动流程(显示启动)

文章图片
Android8.0(API26)之Activity启动流程(显示启动)

文章图片
1final int startActivityMayWait(IApplicationThread caller, int callingUid, 2String callingPackage, Intent intent, String resolvedType, 3IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, 4IBinder resultTo, String resultWho, int requestCode, int startFlags, 5ProfilerInfo profilerInfo, WaitResult outResult, 6Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId, 7IActivityContainer iContainer, TaskRecord inTask, String reason) { 8// Refuse possible leaked file descriptors 9if (intent != null & & intent.hasFileDescriptors()) { 10throw new IllegalArgumentException("File descriptors passed in Intent"); 11} 12//调用底层的方法 给ActivityMetricsLogger的INVALID_START_TIME赋值 13mSupervisor.mActivityMetricsLogger.notifyActivityLaunching(); 14boolean componentSpecified = intent.getComponent() != null; //显示启动为true 15 16// Save a copy in case ephemeral needs it 17final Intent ephemeralIntent = new Intent(intent); 18// Don\'t modify the client\'s object! 19//为了不改变用户的intent 20intent = new Intent(intent); 21if (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 29intent.setComponent(null /*component*/); 30componentSpecified = false; 31} 32//收集Intent所指向的Activity信息, 当存在多个可供选择的Activity,则直接向用户弹出resolveActivity 33ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId); 34if (rInfo == null) { 35UserInfo userInfo = mSupervisor.getUserInfo(userId); //UserInfo 保存了应用相关信息 名字 图片.... 36if (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. 40UserManager userManager = UserManager.get(mService.mContext); 41boolean profileLockedAndParentUnlockingOrUnlocked = false; 42long token = Binder.clearCallingIdentity(); 43try { 44UserInfo parent = userManager.getProfileParent(userId); 45profileLockedAndParentUnlockingOrUnlocked = (parent != null) 46& & userManager.isUserUnlockingOrUnlocked(parent.id) 47& & !userManager.isUserUnlockingOrUnlocked(userId); 48} finally { 49Binder.restoreCallingIdentity(token); 50} 51if (profileLockedAndParentUnlockingOrUnlocked) { 52rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 53PackageManager.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() 61ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo); 62 63ActivityOptions options = ActivityOptions.fromBundle(bOptions); 64ActivityStackSupervisor.ActivityContainer container = 65(ActivityStackSupervisor.ActivityContainer)iContainer; 66synchronized (mService) { 67if (container != null & & container.mParentActivity != null & & 68container.mParentActivity.state != RESUMED) { 69// Cannot start a child activity if the parent is not resumed. 70return ActivityManager.START_CANCELED; 71} 72final int realCallingPid = Binder.getCallingPid(); 73final int realCallingUid = Binder.getCallingUid(); 74int callingPid; 75if (callingUid > = 0) { 76callingPid = -1; 77} else if (caller == null) { 78callingPid = realCallingPid; 79callingUid = realCallingUid; 80} else { 81callingPid = callingUid = -1; 82} 83 84final ActivityStack stack; 85//取得需要启动的ActivityStack栈 86if (container == null || container.mStack.isOnHomeDisplay()) { 87stack = mSupervisor.mFocusedStack; 88} else { 89stack = container.mStack; 90} 91stack.mConfigWillChange = globalConfig != null 92& & mService.getGlobalConfiguration().diff(globalConfig) != 0; 93if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 94"Starting activity when config will change = " + stack.mConfigWillChange); 95 96final long origId = Binder.clearCallingIdentity(); 97 98if (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//供的状态保存/恢复功能。主要是为了保证用户体验的连续性 105if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) { 106final ProcessRecord heavy = mService.mHeavyWeightProcess; 107if (heavy != null & & (heavy.info.uid != aInfo.applicationInfo.uid 108|| !heavy.processName.equals(aInfo.processName))) { 109int appCallingUid = callingUid; 110if (caller != null) { 111ProcessRecord callerApp = mService.getRecordForAppLocked(caller); 112if (callerApp != null) { 113appCallingUid = callerApp.info.uid; 114} else { 115Slog.w(TAG, "Unable to find app for caller " + caller 116+ " (pid=" + callingPid + ") when starting: " 117+ intent.toString()); 118ActivityOptions.abort(options); 119return ActivityManager.START_PERMISSION_DENIED; 120} 121} 122 123IIntentSender target = mService.getIntentSenderLocked( 124ActivityManager.INTENT_SENDER_ACTIVITY, "android", 125appCallingUid, userId, null, null, 0, new Intent[] { intent }, 126new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT 127| PendingIntent.FLAG_ONE_SHOT, null); 128 129Intent newIntent = new Intent(); 130if (requestCode > = 0) { 131// Caller is requesting a result. 132newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true); 133} 134newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT, 135new IntentSender(target)); 136if (heavy.activities.size() > 0) { 137ActivityRecord hist = heavy.activities.get(0); 138newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, 139hist.packageName); 140newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, 141hist.getTask().taskId); 142} 143newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP, 144aInfo.packageName); 145newIntent.setFlags(intent.getFlags()); 146newIntent.setClassName("android", 147HeavyWeightSwitcherActivity.class.getName()); 148intent = newIntent; 149resolvedType = null; 150caller = null; 151callingUid = Binder.getCallingUid(); 152callingPid = Binder.getCallingPid(); 153componentSpecified = true; 154rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId); 155aInfo = rInfo != null ? rInfo.activityInfo : null; 156if (aInfo != null) { 157aInfo = mService.getActivityInfoForUser(aInfo, userId); 158} 159} 160} 161} 162final ActivityRecord[] outRecord = new ActivityRecord[1]; 163//启动Activity 164int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType, 165aInfo, rInfo, voiceSession, voiceInteractor, 166resultTo, resultWho, requestCode, callingPid, 167callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, 168options, ignoreTargetSecurity, componentSpecified, outRecord, container, 169inTask, reason); 170 171Binder.restoreCallingIdentity(origId); 172//如果配置Configration发生变化,则调用AMS的updateConfigurationLocked进行处理 173if (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//它还没有启动下一个活动。 182mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, 183"updateConfiguration()"); 184stack.mConfigWillChange = false; 185if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 186"Updating to new configuration after starting activity."); 187mService.updateConfigurationLocked(globalConfig, null, false); 188} 189 190if (outResult != null) { 191outResult.result = res; 192if (res == ActivityManager.START_SUCCESS) { 193//将结果放入mWaitingActivityLaunced中保存 194mSupervisor.mWaitingActivityLaunched.add(outResult); 195do { 196try { 197//等待启动结果 198mService.wait(); 199} catch (InterruptedException e) { 200} 201} while (outResult.result != START_TASK_TO_FRONT 202& & !outResult.timeout & & outResult.who == null); 203if (outResult.result == START_TASK_TO_FRONT) { 204res = START_TASK_TO_FRONT; 205} 206} 207if (res == START_TASK_TO_FRONT) { 208final ActivityRecord r = outRecord[0]; 209 210// ActivityRecord may represent a different activity, but it should not be in 211// the resumed state. 212if (r.nowVisible & & r.state == RESUMED) { 213outResult.timeout = false; 214outResult.who = r.realActivity; 215outResult.totalTime = 0; 216outResult.thisTime = 0; 217} else { 218outResult.thisTime = SystemClock.uptimeMillis(); 219mSupervisor.waitActivityVisible(r.realActivity, outResult); 220// Note: the timeout variable is not currently not ever set. 221

    推荐阅读