本文主要是介绍安卓startActivity的流程 基于API-28的源码解析(上),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
启动流程:
- 点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;
- system_server进程接收到请求后,向zygote进程发送创建进程的请求;
- Zygote进程fork出新的子进程,即App进程;
- App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
- system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;
- App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;
- 主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。
- 到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面。
本文详细startActivity的整个启动流程,
- 流程[1.1 ~1.3]: 运行在调用者所在进程,比如从桌面启动Activity,则调用者所在进程为launcher进程,launcher进程利用AMS作为Binder Client,进入system_server进程(AMS相应的Server端)。
- 流程[1.4 ~1.17]:运行在system_server系统进程,整个过程最为复杂、核心的过程,下面其中部分步骤:
- 流程[1.18 ~1.19+]:运行在目标进程,通过Handler消息机制,该进程中的Binder线程向主线程发送H.LAUNCH_ACTIVITY,最终会通过反射创建目标Activity,然后进入onCreate()生命周期。
以API28为基础分析startActivity的源码
[1.1] >> Activity.startActivity()
@Overridepublic void startActivity(Intent intent, @Nullable Bundle options) {if (options != null) {>> see [1.2] <<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);}}
[1.2] >> Activity.startActivityForResult()
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {if (mParent == null) {options = transferSpringboardActivityOptions(options);>> see [1.3] <<Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options);...}...}
execStartActivity()方法的参数:
- mAppThread: 数据类型为ApplicationThread,通过mMainThread.getApplicationThread()方法获取。
- mToken: 数据类型为IBinder.
[1.3] >> Instrumentation.execStartActivity()
public ActivityResult execStartActivity(...) {IApplicationThread whoThread = (IApplicationThread) contextThread;...try {intent.migrateExtraStreamToClipData();intent.prepareToLeaveProcess(who);>> see [1.4] <<int result = ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); checkStartActivityResult(result, intent);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null;}
- ActivityManager.getService返回的是ActivityManagerService对象
[1.4] >> ActivityManager.getService()
public static IActivityManager getService() {return IActivityManagerSingleton.get();}private static final Singleton<IActivityManager> IActivityManagerSingleton =new Singleton<IActivityManager>() {@Overrideprotected IActivityManager create() {final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);final IActivityManager am = IActivityManager.Stub.asInterface(b);return am;}};
- 通过ServiceManger.getService()获取"ACITIVITY_SERVICE"的IBinder类型的AMS的引用
- Stub是AIDL(Android Interface Definition Language)生成的一个Binder类,将一个 IBinder 转换为 IMyAidl,如果不在一个进程就创建一个代理
- asInterdace()方法的作用是:将服务端的Binder对象转换为客户端所需要的AIDL接口类型。如果客户端和服务端同进程则返回Binder引用的Service对象,否则返回Binder引用的BinderProxy对象,这个BinderProxy是存活在另一个进程中的Service在当前进程的代理。
[1.5] >> ActivityManagerService.startActivity()
@Overridepublic final int startActivity(...) {return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,resultWho, requestCode, startFlags, profilerInfo, bOptions,UserHandle.getCallingUserId());}public final int startActivityAsUser(...) {enforceNotIsolatedCaller("startActivity");userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");// TODO: Switch to user app stacks here.>> see [1.6] <<return mActivityStartController.obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(bOptions).setMayWait(userId).execute();}ActivityStarter obtainStarter(Intent intent, String reason) {return mFactory.obtain().setIntent(intent).setReason(reason);}
当程序运行到这里时, ActivityStarter的set函数传入的各个参数取值如下:
- caller = ApplicationThreadProxy, 用于跟调用者进程ApplicationThread进行通信的binder代理类.
- callingUid = -1;
- callingPackage = ContextImpl.getBasePackageName(),获取调用者Activity所在包名
- intent: 这是启动Activity时传递过来的参数;
- resolvedType = intent.resolveTypeIfNeeded
- voiceSession = null;
- voiceInteractor = null;
- resultTo = Activity.mToken, 其中Activity是指调用者所在Activity, mToken对象保存自己所处的ActivityRecord信息
- resultWho = Activity.mEmbeddedID, 其中Activity是指调用者所在Activity
- requestCode = -1;
- startFlags = 0;
- profilerInfo = null;
- outResult = null;
- config = null;
- options = null;
- ignoreTargetSecurity = false;
- userId = AMS.handleIncomingUser, 当调用者userId跟当前处于同一个userId,则直接返回该userId;当不相等时则根据调用者userId来决定是否需要将callingUserId转换为mCurrentUserId.
- iContainer = null;
- inTask = null;
[1.6] >> ActivityStarter.execute()
int execute() {try {// TODO(b/64750076): Look into passing request directly to these methods to allow// for transactional diffs and preprocessing.if (mRequest.mayWait) {>> to see [1.7] <<return startActivityMayWait(mRequest.caller, mRequest.callingUid,mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,mRequest.inTask, mRequest.reason,mRequest.allowPendingRemoteAnimationRegistryLookup);} else {return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,mRequest.ignoreTargetSecurity, mRequest.componentSpecified,mRequest.outActivity, mRequest.inTask, mRequest.reason,mRequest.allowPendingRemoteAnimationRegistryLookup);}} finally {onExecutionComplete();}}
- execute()函数就是根据布尔值Request.mayWait() 来判断执行startActivity() or startActivityMayWait()
- 由startActivityAsUser()可知,obtainStarter执行了setMayWait(),所以mayWait为true,执行startActivityMayWait()方法
[1.7] >> ActivityStarter.startActivityMayWait()
private int startActivityMayWait(...) {// 提示系统准备启动ActivitymSupervisor.getActivityMetricsLogger().notifyActivityLaunching();...>> to see [1.8] <</*通过PMS和传递过来的intent去查询目标页面的ResolveInfo。这个类里放了ActivityInfo、ServiceInfo、ProviderInfo,*/ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0, computeResolveFilterUid(callingUid, realCallingUid, mRequest.filterCallingUid));...//通过解析ResolveInfo,得到ActivityInfo对象>> to see [1.12] << ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);.../*创建一个ActivityRecord数组,然后startActivityLocked会填充上0索引,以便于执行完了startActivityLocked函数后保存对象并作后边的处理工作*/final ActivityRecord[] outRecord = new ActivityRecord[1];>> to see [1.13] <<int res = startActivity(...);...// 通知系统目标Activity已经启动完成mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]);return res;}
- 通过ASS.resolveIntent()来解析一个与IntentFilter对应的Intent获取信息,部分信息对应于AndroidManifest的<intent>标签
- 通过ASS.resolveActivity()来解析一个与Intent对应的Activity信息(从AndroidManifest中activity或者receiver节点中检索这些信息)
[1.8] >> ActivityStackSupervisor.resolveIntent()
ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags,int filterCallingUid) {...try {return mService.getPackageManagerInternalLocked().resolveIntent(intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);}...}PackageManagerInternal getPackageManagerInternalLocked() {if (mPackageManagerInt == null) {>> to see [1.9] <<mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);}return mPackageManagerInt;}
- 调用PackageManagerService.PackageManagerInternal()的resolveIntent()方法
[1.9] >> PackageManagerService.PackageManagerService()
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {...synchronized (mPackages) {// Expose private service for system components to use.LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());...} } private class PackageManagerInternalImpl extends PackageManagerInternal {@Overridepublic ResolveInfo resolveIntent(Intent intent, String resolvedType,int flags, int userId, boolean resolveForStart, int filterCallingUid) {return resolveIntentInternal(intent, resolvedType, flags, userId, resolveForStart, filterCallingUid);} }private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,int flags, int userId, boolean resolveForStart, int filterCallingUid) {try {>> see [1.10] <<final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,flags, filterCallingUid, userId, resolveForStart, true);...>> see [1.11] <<final ResolveInfo bestChoice = chooseBestActivity(intent, resolvedType, flags, query, userId);return bestChoice;} finally {Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);}}
- 可见在PMS的构造函数中将PackageManagerInternalImpl的对象put到LocalService中
- PackageManagerInternalImpl中重写的resolveIntent函数调用PackageManagerInternal()
- 通过queryIntentActivitiesInternal()方法获取符合Intent的所有目标Activity信息
- 将返回的Activity信息,再通过ChooseBestActivity()选择最合适的Activity信息返回
[1.10] >> PackageManagerService.queryIntentActivitiesInternal()
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,String resolvedType, int flags, int filterCallingUid, int userId,boolean resolveForStart, boolean allowDynamicSplits) {...// 获取intent中的Component信息ComponentName comp = intent.getComponent();if (comp == null) {if (intent.getSelector() != null) {intent = intent.getSelector();comp = intent.getComponent();}}flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart, comp != null || pkgName != null /*onlyExposedExplicitly*/);if (comp != null) {final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);// 根据Component信息, flag, 目标Activity的userId,获取对应的Activity信息final ActivityInfo ai = getActivityInfo(comp, flags, userId);...return applyPostResolutionFilter(list, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart, userId, intent);}...// 当component未空时,通过Activity.queryIntentForPackage()获取目标Activity的resolve信息final PackageParser.Package pkg = mPackages.get(pkgName);result = null;if (pkg != null) {result = filterIfNotSystemUser(mActivities.queryIntentForPackage(intent, resolvedType, flags, pkg.activities, userId), userId);}if (result == null || result.size() == 0) {addInstant = isInstantAppResolutionAllowed(intent, null /*result*/, userId, true);if (result == null) {result = new ArrayList<>();}}...return applyPostResolutionFilter( result, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart, userId, intent);}
- 获取ActivityInfo,并通过applyPostResolutionFilter()对activity进行过滤筛选
[1.11] >> PackageManagerService.chooseBestActivity()
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType, int flags, List<ResolveInfo> query, int userId) {if (query != null) {// 假如多个activity有相同的优先级,则让用户进行选择ResolveInfo r0 = query.get(0);ResolveInfo r1 = query.get(1);// 假如第一个activity优先级更高或者具有不同的默认值,则优先选择该activityif (r0.priority != r1.priority || r0.preferredOrder != r1.preferredOrder|| r0.isDefault != r1.isDefault) {return query.get(0);}/* 通过获取setting中的信息来判断当前是否已经设置了优先项,若有则默认选择对应的activity。 */ResolveInfo ri = findPreferredActivity(intent, resolvedType, flags, query, r0.priority, true, false, debug, userId);if (ri != null) {return ri;}/* 若没有,则通过ResolverActivity的onTargetSelected函数调PackageManager.addPreferredActivity()来执行弹出弹框,让用户进行选择*/ri = new ResolveInfo(mResolveInfo);ri.activityInfo = new ActivityInfo(ri.activityInfo);ri.activityInfo.labelRes = ResolverActivity.getLabelRes(intent.getAction());final String intentPackage = intent.getPackage();if (!TextUtils.isEmpty(intentPackage) && allHavePackage(query, intentPackage)) {final ApplicationInfo appi = query.get(0).activityInfo.applicationInfo;ri.resolvePackageName = intentPackage;if (userNeedsBadging(userId)) {ri.noResourceId = true;} else {ri.icon = appi.icon;}ri.iconResourceId = appi.icon;ri.labelRes = appi.labelRes;}ri.activityInfo.applicationInfo = new ApplicationInfo( ri.activityInfo.applicationInfo);if (userId != 0) {ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId,UserHandle.getAppId(ri.activityInfo.applicationInfo.uid));}if (ri.activityInfo.metaData == null) ri.activityInfo.metaData = new Bundle();ri.activityInfo.metaData.putBoolean(Intent.METADATA_DOCK_HOME, true);return ri;}return null;}
- 当传入的ResovleInfo List只有一个值时,不用进行选择
- 当存在多个符合intent信息的Activity的ResolveInfo, 则先判断activity的优先级,再判断是否有默认选项
- 当存在多个选择则没有设置默认选项时,app通过ResolverActivity的onTargetSelected函数调用pm.addPreferredActivity()方法来执行弹出选择弹框,让用户进行选择
[1.12] >> ActivityStackSupervisor.resolveActivity()
ActivityInfo resolveActivity(Intent intent, ResolveInfo rInfo, int startFlags,ProfilerInfo profilerInfo) {final ActivityInfo aInfo = rInfo != null ? rInfo.activityInfo : null;if (aInfo != null) {//将最新的info信息重新存储到intent中intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));...final String intentLaunchToken = intent.getLaunchToken();if (aInfo.launchToken == null && intentLaunchToken != null) {aInfo.launchToken = intentLaunchToken;}}return aInfo;}
[1.13] >> ActivityStarter.startActivity()
private int startActivity(...) {int err = ActivityManager.START_SUCCESS;//获取应用的进程描述类对象ProcessRecordProcessRecord callerApp = null;if (caller != null) {callerApp = mService.getRecordForAppLocked(caller);...}ActivityRecord sourceRecord = null;ActivityRecord resultRecord = null;if (resultTo != null) {//获取应用当前所在的ActivityRecord信息sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);if (sourceRecord != null) {if (requestCode >= 0 && !sourceRecord.finishing) {//当使用的是startActivityForResult()的话,resultRecord存的就是当前ActivityresultRecord = sourceRecord;}}}final int launchFlags = intent.getFlags();/*FLAG_ACTIVITY_FORWARD_RESULT这个标记允许我们把startActivityForResult的线路拉长,比如A->B->C,然后C可以直接把值传递到A*/if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) { ... }...//执行后resultStack = nullfinal ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();//ActivityController不为空的情况,比如monkey测试过程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;}}//判断目标Activity是否已经关闭工作或者目标application被挂起,是则拦截activity启动mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid, checkedOptions)) {...}//判断启动的activity的权限是否已被允许,GRANT的话abort为falseboolean abort = !mSupervisor.checkStartAnyActivityPermission(...);.../*如果权限需要在任何应用程序运行之前进行确认,将弹出权限确认框,在确认完成后立即启动活动。*/if (mService.mPermissionReviewRequired && aInfo != null) {if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(aInfo.packageName, userId)) {IIntentSender target = mService.getIntentSenderLocked(...);final int flags = intent.getFlags();Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);newIntent.setFlags(...) {newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);}intent = newIntent;...rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0, computeResolveFilterUid(callingUid, realCallingUid, mRequest.filterCallingUid));aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null);}}...// 创建出我们的目标ActivityRecord对象,存到传入数组0索引上ActivityRecord r = new ActivityRecord(...);if (outActivity != null) {outActivity[0] = r;}...//检查是否有需要延迟启动的Activity,如果有,则启动mController.doPendingActivityLaunches(false);>> see [1.14] <<return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,true /* doResume */, checkedOptions, inTask, outActivity);}
- checkStartAnyActivityPermission检测步骤:
- (1)首先是检测是否有root权限
- (2)然后如果export=false,且callingUid不等于启动的uid(不在一个进程),则不予权限。
- (3)activity的permission与application相同,则授权。
- (4)activity的permission为空授权;
- (5)请求启动的activity设定了permission,那么检查caller的activity中是否声明了使用这个permission,如果声明了授权。
- 其中有两个返回值代表启动Activity失败:
- START_INTENT_NOT_RESOLVED: 从Intent中无法找到相应的Component或者ActivityInfo
- START_NOT_CURRENT_USER_ACTIVITY:该Activity对当前用户不可见
[1.14] >> ActivityStarter.startActivity()
private int startActivity(...) {int result = START_CANCELED;try {//通知Wms(WindowManagerService)阻塞一下SurfacemService.mWindowManager.deferSurfaceLayout();//WMS.deferSurfaceLayout>> see [1.15]<<result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, outActivity);} finally {//启动activity失败的话,解除activity与任务的关联。final ActivityStack stack = mStartActivity.getStack();if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,null /* intentResultData */, "startActivity", true /* oomAdj */);}mService.mWindowManager.continueSurfaceLayout();}postStartActivityProcessing(r, result, mTargetStack);return result;}
- 在执行多个更改时非常有用,但是为了优化性能,应该只执行一次布局传递
- deferSurfaceLayout可以被多次调用,当调用WMS.continueSurfaceLayout()后,将恢复布局。
[1.15] >> ActivityStarter.startActivityUnchecked()
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,...) {/*根据启动intent识别LaunchMode,如果是startActivityForResult并且启动模式是NEW_TASK的话,就会让startActivityForResult的回调失效。*/setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,voiceInteractor); //判断启动模式,并且在mLaunchFlags上追加对应的标记computeLaunchingTaskFlags();//获取到Activity的启动栈computeSourceStack();//根据上面的计算,应用识别到的flagsmIntent.setFlags(mLaunchFlags);...mIntent.setFlags(mLaunchFlags);/*决定是否应将新activity插入到现有task中。如果不是则返回null,如果是则返回包含将新activity添加到其中的task的ActivityRecord。*/ActivityRecord reusedActivity = getReusableIntentActivity();...if (reusedActivity != null) {// 如果mStartactivity没有与其关联的任务,请与复用的ActivityTask关联if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {mStartActivity.setTask(reusedActivity.getTask());}if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0|| isDocumentLaunchesIntoExisting(mLaunchFlags)|| isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {final TaskRecord task = reusedActivity.getTask();// 在这种情况下,我们希望从task中删除除正在启动的activity之外的所有activity。将task重置为初始状态。final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,mLaunchFlags);// Activityrecord删除对taskRecord的引用,在后面调用setTargetStackAndMoveToFrontIfNeeded()时需要task引用。if (reusedActivity.getTask() == null) {reusedActivity.setTask(task);}if (top != null) {if (top.frontOfTask) {// 将目标activityRecord传入task栈顶top.getTask().setIntent(mStartActivity);}// 传递目标activity的intent,确保将会最先被执行deliverNewIntent(top);}}reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);if (reusedActivity != null) {setTaskFromIntentActivity(reusedActivity);}}/*接下来判断是否需要新创建一个task出来,比如NEW_TASK如果不需要新建就通过setTaskFromSourceRecord()直接把目标Activity放入到对应的task内*/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;}//检查是否具有contentProvider的uri访问权限mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);/*判断是否需要发送警告(PowerManager实现),判断依据是resumedActivity被回收或者是进程被杀死或者是目标Activity的进程和resumedActivity的进程不一致的时候*/mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);>> see [1.16]<<mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition, mOptions);if (mDoResume) {>> see [1.17]<<mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); } return START_SUCCESS;}
- r -> 准备启动的activity, sourceRecord -> 当前的activity
- 假如Intent中设置的Launch信息与Manifest有冲突,则优先选择Manifest
[1.16] >> ActivityStack.startActivityLocked
void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,boolean newTask, boolean keepCurTransition, ActivityOptions options) {TaskRecord rTask = r.getTask();final int taskId = rTask.taskId;// 将目标activity所在的Task放在Task栈的顶端,同时将activity对应的window置顶if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {insertTaskAtTop(rTask, r);}TaskRecord task = null;//假如Activity还在原来的栈中运行,此时就将Activity移动到ActivityStack的顶端if (!newTask) {boolean startIt = true;for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {if (task == rTask) {if (!startIt) {//初始化WMS的设置,将activity加入栈顶r.createWindowContainer();ActivityOptions.abort(options);return;}break;} else if (task.numFullscreen > 0) {startIt = false;}}}// 将要启动的activity设置到Task的的栈顶task.setFrontOfTask();...}
- 主要任务是将目标Activity和Activity所在的栈都放到容器的顶端
[1.17] >> ActivityStack.resumeTopActivityInnerLocked()
@GuardedBy("mService")private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {if (!mService.mBooting && !mService.mBooted) {// Not ready yet!return false;}// 找出目前栈顶的activity,因为目标Activity已经入栈了,所以next就是目标Activityfinal ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);...next.delayedResume = false;// 如果目标Activity是resume状态,那么直接通知Wms执行Activity的过渡if (mResumedActivity == next && next.isState(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_STACK) mStackSupervisor.validateTopActivitiesLocked();return false;}// 如果目标Activity已经是sleep状态,如果进入睡眠状态Activity也会进入Pause状态if (shouldSleepOrShutDownActivities()&& 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;}...// 将当前activity置为pause状态boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);if (pausing && !resumeWhilePausing) {if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,"resumeTopActivityLocked: Skip resume: need to start pausing");if (next.app != null && next.app.thread != null) {//用于更新进程的使用情况,把目标Activity的进程放在LRU列表的顶部mService.updateLruProcessLocked(next.app, true, null);}if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();if (lastResumed != null) {lastResumed.setWillCloseOrEnterPip(true);}return true;}/* 当most recent的Activity不是在“历史记录”里,而是因为设备进入睡眠状态而停止,而不是“停止+销毁”,因为我们正在使一个新的Activity成为最顶层,我们需要确保销毁它。*/if (shouldSleepActivities() && mLastNoHistoryActivity != null &&!mLastNoHistoryActivity.finishing) {requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,null, "resume-no-history", false);mLastNoHistoryActivity = null;}// 确保启动目标Activity的app状态不为stoptry {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);}// 准备开启app的activityboolean anim = true;if (prev != null) {if (prev.finishing) {// 通知WMS进行app页面过渡准备if (mStackSupervisor.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 (mStackSupervisor.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);}}} ...// 获取最近Foucus的TaskStackActivityStack lastStack = mStackSupervisor.getLastStack();// 目标Activity所在的app进程已存在的情况下,if (next.app != null && next.app.thread != null) {// 目标activity正在成为可见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;final ActivityState lastState = next.getState();mService.updateCpuStats();if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)");// 设置Activity的状态为Resumenext.setState(RESUMED, "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;...synchronized(mWindowManager.getWindowManagerLock()) {// 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;final ActivityState lastState = next.getState();// 唤醒CPUmService.updateCpuStats();if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next+ " (in existing)");next.setState(RESUMED, "resumeTopActivityInnerLocked");// 更新目标Activity所在的进程状态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;/* 当目标Activity所在的Task为FocusTask时,将Task顶端的目标Activity的LaunchActivityItem添加到ClientTransaction上 */if (mStackSupervisor.isFocusedStack(this)) {notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,true /* markFrozenIfConfigChanged */, false /* deferResume */);}try {final ClientTransaction transaction = ClientTransaction.obtain(next.app.thread, next.appToken);// 判断是否需要触发onActivityResult函数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);transaction.addCallback(ActivityResultItem.obtain(a));}}// 是否需要触发onNewIntent函数if (next.newIntents != null) {transaction.addCallback(NewIntentItem.obtain(next.newIntents,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.getAppWarningsLocked().onResumeActivity(next);mService.showAskCompatModeDialogLocked(next);next.app.pendingUiClean = true;next.app.forceProcessStateUpTo(mService.mTopProcessState);next.clearOptionsLocked();// 将ResumeActivityItem添加到ClientTransaction中transaction.setLifecycleStateRequest( ResumeActivityItem.obtain( next.app.repProcState, mService.isNextTransitionForward()));// 执行ClientTransaction中的LaunchActivityItem,ResumeActivityItem等>> see [1.18] <<mService.getLifecycleManager().scheduleTransaction(transaction);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.setState(lastState, "resumeTopActivityInnerLocked");// lastResumedActivity being non-null implies there is a lastStack present.if (lastResumedActivity != null) {lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");}Slog.i(TAG, "Restarting because process died: " + next);if (!next.hasBeenLaunched) {next.hasBeenLaunched = true;} else if (SHOW_APP_STARTING_PREVIEW && lastStack != null&& lastStack.isTopStackOnDisplay()) {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);// 当目标activity的进程不存在的时候,创建进程启动app >> see [1.19] <<mStackSupervisor.startSpecificActivityLocked(next, true, true);}if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();return true;}
- 将目前的Activity的状态设为Pause
- 当目标Activity所在的进程存在的话,则将目标Activity设为Resume状态,通过ClientLifecycleManager.scheduleTransaction()方法进行启动app
- 当目标Activity所在的进程不存在的话,则通过ActivityStackSupervisor.startSpecificActivityLocked()方法开启进程,进行app启动
[1.18] >> ClientLifecycleManager.scheduleTransaction()
1. class ClientLifecycleManager {void scheduleTransaction(ClientTransaction transaction) throws RemoteException {final IApplicationThread client = transaction.getClient();transaction.schedule(); //转 2if (!(client instanceof Binder)) {transaction.recycle();}}... }2. public class ClientTransaction implements Parcelable, ObjectPoolItem {public void schedule() throws RemoteException {mClient.scheduleTransaction(this); //转 3}... }3. public final class ActivityThread extends ClientTransactionHandler {private class ApplicationThread extends IApplicationThread.Stub {public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {ActivityThread.this.scheduleTransaction(transaction); // 转 4}}... }4. public abstract class ClientTransactionHandler {void scheduleTransaction(ClientTransaction transaction) {transaction.preExecute(this);sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);}... }5. public final class ActivityThread extends ClientTransactionHandler {class H extends Handler {public void handleMessage(Message msg) {switch (msg.what) {case EXECUTE_TRANSACTION:final ClientTransaction transaction = (ClientTransaction) msg.obj;mTransactionExecutor.execute(transaction); // 转 6if (isSystem()) {transaction.recycle();}break;...}}}... } 6. public class TransactionExecutor {public void execute(ClientTransaction transaction) {final IBinder token = transaction.getActivityToken();executeCallbacks(transaction); //转 6.1executeLifecycleState(transaction); //转 6.2mPendingActions.clear();log("End resolving transaction");}... }6.1/** Cycle through all states requested by callbacks and execute them at proper times. */@VisibleForTestingpublic void executeCallbacks(ClientTransaction transaction) {final List<ClientTransactionItem> callbacks = transaction.getCallbacks();...final int size = callbacks.size();for (int i = 0; i < size; ++i) {final ClientTransactionItem item = callbacks.get(i);...>> to see [1.18.1] <<item.execute(mTransactionHandler, token, mPendingActions);item.postExecute(mTransactionHandler, token, mPendingActions);if (r == null) {// Launch activity request will create an activity record.r = mTransactionHandler.getActivityClient(token);}}}6.2/** Transition to the final state if requested by the transaction. */private void executeLifecycleState(ClientTransaction transaction) {final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();final IBinder token = transaction.getActivityToken();final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);if (r == null) {// Ignore requests for non-existent client records for now.return;}// Cycle to the state right before the final requested state.cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);// Execute the final transition with proper parameters.>> to see [1.18.2] <<lifecycleItem.execute(mTransactionHandler, token, mPendingActions);lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);}
- 在ClientTransaction和ActivityThead之间绕了几圈之后,最后通过ActivityThread的executeCallbacks()和executeLifecycleState()函数进行操作
- 通过6.1/6.2可以看到,实际是通过执行Transaction中Callback的ClientTransactionItem
和LifecycleItem的excute方法- 也就是执行之前通过transaction.setLifecycleStateRequest()添加的ResumeActivityItem.excute()和mStackSupervisor.ensureVisibilityAndConfig()添加的LaunchActivityItem.excute()方法
[1.18.1] >> LaunchActivityItem.excute()
public class LaunchActivityItem extends ClientTransactionItem {@Overridepublic void execute(ClientTransactionHandler client, IBinder token,PendingTransactionActions pendingActions) {Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,mPendingResults, mPendingNewIntents, mIsForward,mProfilerInfo, client);>> to see [1.18.1.1] <<client.handleLaunchActivity(r, pendingActions, null /* customIntent */);Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);}... }
- 这里就是根据传入的参数,生成目标Activity的实例Record--ActivityClientRecord
- 通过ActivityThread.handleLaunchActivity()启动activity
[1.18.1.1] >> ActivityThread.handleLaunchActivity()
@Overridepublic Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {// 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);// Initialize before creating the activityif (!ThreadedRenderer.sRendererDisabled) {GraphicsEnvironment.earlyInitEGL();}WindowManagerGlobal.initialize();>> to see [1.18.1.2] <<final Activity a = performLaunchActivity(r, customIntent);// 当启动App成功后,设置InstanceStateif (a != null) {r.createdConfig = new Configuration(mConfiguration);reportSizeConfigurations(r);if (!r.activity.mFinished && pendingActions != null) {pendingActions.setOldState(r.state);pendingActions.setRestoreInstanceState(true);pendingActions.setCallOnPostCreate(true);}} 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();}}return a;}
[1.18.1.2] >> ActivityThread.performLaunchActivity()
/** Core implementation of activity launch. */private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {// 获取目标Activity的组件信息ActivityInfo aInfo = r.activityInfo;if (r.packageInfo == null) {r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,Context.CONTEXT_INCLUDE_CODE);}ComponentName component = r.intent.getComponent();if (component == null) {component = r.intent.resolveActivity(mInitialApplication.getPackageManager());r.intent.setComponent(component);}if (r.activityInfo.targetActivity != null) {component = new ComponentName(r.activityInfo.packageName,r.activityInfo.targetActivity);}//创建目标Activity的ContextContextImpl appContext = createBaseContextForActivity(r);Activity activity = null;try {//通过反射的方式创建activityjava.lang.ClassLoader cl = appContext.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);StrictMode.incrementExpectedActivityCount(activity.getClass());r.intent.setExtrasClassLoader(cl);r.intent.prepareToEnterProcess();if (r.state != null) {r.state.setClassLoader(cl);}} catch (Exception e) {...}try {//创建ApplicationApplication app = r.packageInfo.makeApplication(false, mInstrumentation);if (activity != null) {CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());Configuration config = new Configuration(mCompatConfiguration);if (r.overrideConfig != null) {config.updateFrom(r.overrideConfig);}Window window = null;if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {window = r.mPendingRemoveWindow;r.mPendingRemoveWindow = null;r.mPendingRemoveWindowManager = null;}//将context和组件信息跟目标Activity绑定appContext.setOuterContext(activity);activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback);if (customIntent != null) {activity.mIntent = customIntent;}r.lastNonConfigurationInstances = null;checkAndBlockForNetworkAccess();activity.mStartedActivity = false;int theme = r.activityInfo.getThemeResource();if (theme != 0) {activity.setTheme(theme);}activity.mCalled = false;//启动目标Activity,调用Activity的onCreate方法>> to see [1.18.1.3] <<if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}r.activity = activity;}r.setState(ON_CREATE);mActivities.put(r.token, r);}...return activity;}
[1.18.1.3] >> Instrumentation.callActivityOnCreate()
/*** Perform calling of an activity's {@link Activity#onCreate}* method. The default implementation simply calls through to that method.** @param activity The activity being created.* @param icicle The previously frozen state (or null) to pass through to onCreate().*/public void callActivityOnCreate(Activity activity, Bundle icicle) {prePerformCreate(activity);activity.performCreate(icicle);postPerformCreate(activity);}
- 执行目标Activity的onCreate操作,进入目标Activity的生命周期
- 执行完了onCreate,那下一步就是onStart, 然后就是onResume了。
[1.18.2] ResumenActivityItem.excute()
@Overridepublic void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");>> to see [1.18.2.1] <<client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward, "RESUME_ACTIVITY");Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);}
- 执行ActivityThread.handleResumeActivity()
[1.18.2.1] >> ActivityThread.handleResumeActivity()
@Overridepublic void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, 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;// TODO Push resumeArgs into the activity for consideration>> to see [1.18.2.2] <<// 将目标Activity更新为onResume状态final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);...// 设置WindowManager,显示目标Activityr.nextIdle = mNewActivities;mNewActivities = r;Looper.myQueue().addIdleHandler(new Idler());}
[1.18.2.2] >> ActivityThread.performResumeActivity()
@VisibleForTestingpublic ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,String reason) {// 根据token通过IPC方式获取对应的ActivityRecordfinal ActivityClientRecord r = mActivities.get(token);...if (finalStateRequest) {r.hideForNow = false;r.activity.mStartedActivity = false;}try {r.activity.onStateNotSaved();r.activity.mFragments.noteStateNotSaved();checkAndBlockForNetworkAccess();if (r.pendingIntents != null) {deliverNewIntents(r, r.pendingIntents);r.pendingIntents = null;}if (r.pendingResults != null) {deliverResults(r, r.pendingResults, reason);r.pendingResults = null;}>> to see [1.18.2.3] <<// 将目标Activity设为onResumer.activity.performResume(r.startsNotResumed, reason);r.state = null;r.persistentState = null;r.setState(ON_RESUME);}return r;}
[1.18.2.3] >> Activity.performResume()
final void performResume(boolean followedByPause, String reason) {//在onResume之前先调用onStart,很符合Activity的生命周期>> to see [1.18.2.4] <<performRestart(true /* start */, reason);...// 调用目标Activity的onResume()方法mInstrumentation.callActivityOnResume(this);// 在onResume()方法执行完毕之前,目标Activity需要完成页面显示动作// 当onResume()方法执行完毕后,调用该方法...onPostResume();}
- 在执行onResume()前,先执行onStart()
- 页面要在onResume()执行完之前完成显示动作
[1.18.2.4] >> Activity.performStart()
final void performRestart(boolean start, String reason) {...// 调用Activity的onRestart()方法mInstrumentation.callActivityOnRestart(this);...// onRestart()之后,再调用onStart()方法if (start) {performStart(reason);}}final void performStart(String reason) {...// 调用Activity的onStart()方法mInstrumentation.callActivityOnStart(this);...// 标志Activity已经完全启动状态,开始进行DecorView页面绘制并显示mActivityTransitionState.enterReady(this);}
- 因为目标Activity所在的app存在于后台,根据activity的生命周期,先调用onRestart()再调用onStart()方法(resumeTopActivityInnerLocked()中可见判断app是否存在)
- 至此,当目标Activity所在App已经存在于后台(或者是分屏)时,其他app或adb命令通过startActivity方式启动该目标Activity的流程已经完成。
这篇关于安卓startActivity的流程 基于API-28的源码解析(上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!