最近在复习看ams是发现,Android Q之后源码已经修改,activity的启动改为有activitytaskmanagerservice实现,目前博客的文章都是基于ams,因此记录一下自己的学习过程,如有错误,还请勘误。 本文主要分析大致流程。
首先列出一下核心类:
Activity:界面展示等ui操作,大家比较熟悉
ActivityThread:应用的主线程,入口
ActivityTaskManagerService(ATMS):负责管理activity
ActivityManagerService(AMS):之前版本负责管理activity,与ATMS同一个父类
ActivityStarter:负责启动模式,启动Flag相关处理
ActivityStack:负责管理单独栈activity和其状态,即具体启动的执行等
ActivityStackSupervisor:与ActivityStack类似,但设计window相关的操作
ClientTransactionItem:执行具体activity生命周期的抽象类,子类:LaunchActivityItem等
ClientTransaction:处理相关的信息和生命周期状态
TransactionExecutor:管理信息的执行顺序
一个问题
设置MainActivity(首页)启动模式为singleTask,依次启动标准模式的其他activity,然后点击home键进入后台,再次点击图标,生命周期如何走:
一,启动大致流程
点击图标启动--ATMS检测是否有运行的Activity--通知应用暂停运行的Activity
应用完成暂停通知ATMS--检测进程是否存在---存在启动目标Activity,不存在启动进程,然后在启动应用
另附上个人总结的启动流程,流程比较复杂,就单独放个链接,感兴趣的可以结合这看。www.processon.com/view/link/5…
二,结合源码分析
1,点击桌面图标启动 Launcher.startActivitySafely--Activity.startActivity 对桌面启动细节感兴趣的可以参考这篇博客
2,进入Activity Activity.startActivity-->Activity.startActivityForResult
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
然后调用 mInstrumentation.execStartActivity的方法,大家留意传入的参数 Instrumentation这个类负责应用和系统进程的交互,以及应用和Activity类的加载等操作: newActivity;newApplication
3,mInstrumentation.execStartActivity的方法,会利用binder机制,跨进程调用ATMS.startActivity
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityTaskManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
4,进入系统进程,ATMS.startActivity方法,然后一次调用其类内部方法,最后调用 startActivityAsUser方法
return getActivityStartController().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,处理启动模式,FLAG等操作
5,进入ActivityStarter,执行execute,这里看是否需要等待,会进入两个方法
if (mRequest.mayWait) {
startActivityMayWait
} else {
startActivity
}
然后逐步调用,最后执行到startActivityUnchecked方法,这个方法比较关键,一些核心的处理都在这里,上面问题的答案也在这里
- 首先调用下面三个方法
computeLaunchingTaskFlags();
computeSourceStack();
ActivityRecord reusedActivity = getReusableIntentActivity();
- computeLaunchingTaskFlags会根据不同情形,重新配置intent.FlAG,具体大家可以看一下源码,下面列出部分代码,针对来自非Activity的处理,例如ContextImpl启动的,还有针对SigleInstance的处理
if (mInTask == null) {
if (mSourceRecord == null) {
//目标Activity全新创建,这种情况下,永远是启动一个新的task
if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
"Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
}
} else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
// The original activity who is starting us is running as a single
// instance... this new activity it is starting must go on its
// own task.
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
} else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
// The activity being started is a single instance... it always
// gets launched into its own task.
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
}
}
- computeSourceStack主要负责sourceRecord的处理,看起是否正在finish,如果正在finish,拷贝其信息,然后将其设置为空。
if (!mSourceRecord.finishing) {
mSourceStack = mSourceRecord.getActivityStack();
return;
}
// If the source is finishing, we can't further count it as our source. This is because the
// task it is associated with may now be empty and on its way out, so we don't want to
// blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
// a task for it. But save the task information so it can be used when creating the new task.
if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
+ "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
mNewTaskInfo = mSourceRecord.info;
// It is not guaranteed that the source record will have a task associated with it. For,
// example, if this method is being called for processing a pending activity launch, it
// is possible that the activity has been removed from the task after the launch was
// enqueued.
final TaskRecord sourceTask = mSourceRecord.getTaskRecord();
mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
}
mSourceRecord = null;
mSourceStack = null;
- getReusableIntentActivity 给方法先判断是否是后台进程切换到前台,如果是;返回当前task顶部复用的activity;如果不是,在属于给应用的task里查找目标activity;没有找到就是null, 这里就会对SingleInstance进行了处理。对其查找进行了单独优化,这个方法比较重要,大家可以看一下源码。这也是为什么我们切换到前台是,会显示之前的界面的原因,逻辑就在这里
// If bring to front is requested, and no result is requested and we have not been given
// an explicit task to launch in to, and we can find a task that was started with this
// same component, then instead of launching bring that one to the front.
putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
ActivityRecord intentActivity = null;
if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
final TaskRecord task = mRootActivityContainer.anyTaskForId(mOptions.getLaunchTaskId());
intentActivity = task != null ? task.getTopActivity() : null;
} else if (putIntoExistingTask) {
.....具体可看源码
}
接下来我们回到上面的startActivityUnchecked方法,当找到复用的activity,且启动模式为SingleInstance或SinleTask是,其会进行移除上面的,
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
final TaskRecord task = reusedActivity.getTaskRecord();
// 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);
}
其会在复用的activity的栈里,移除目标activity之前的,而不是复用的,==这也是上面问题的答案,当设置为singleTask后,会先destory上面的,且先destoryB,的原因==
6,接下来根据不同的情况,但最后都会进入ActivityStack.resumeTopActivityInnerLocked,因为流程比较复杂,先列出大致步骤,然后在逐个分析
- 先暂停已运行的activity
boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
- 暂停后,判断是否进程存在
if (next.attachedToProcess()) {}
- 不存在,则通知应用启动进程,这里不分析了,但肯定会调用ActivityThread.main
- 存在则复用
7,暂停应用,在pauseBackStacks这里,会调用ActivityStack的startPausingLocked
if (resumedActivity != null
&& (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
|| !stack.isFocusable())) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + resumedActivity);
someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
dontWait);
}
在其里面传入PauseActivityItem,和之前运行activity的线程等信息
mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately));
然后调用ClientTransaction.schedule
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
if (!(client instanceof Binder)) {
// If client is not an instance of Binder - it's a remote call and at this point it is
// safe to recycle the object. All objects used for local calls will be recycled after
// the transaction is executed on client in ActivityThread.
transaction.recycle();
}
//mClient:private IApplicationThread mClient;很熟悉,就是ActivityThread.ApplicationThread
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
这样就回到了ActivityThread,大家记得看一下ActivityThread的父类,这样就进入了应用进程
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
这里面调用的方法,就是ActivityThread父类ClientTransactionHandler的方法
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
在回到ActivityThread.H,记得之前传入的PasuingActivityItem
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
进入TransactionExecutor,执行execute方法,给方法有两个个方法比较重要
executeCallbacks(transaction);
executeLifecycleState(transaction);
主要分析executeCallbacks
final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
在这个方法里,会调用我们之前传入的PauseActivityItem的方法
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
"PAUSE_ACTIVITY_ITEM");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
public void postExecute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
if (mDontReport) {
return;
}
try {
// TODO(lifecycler): Use interface callback instead of AMS.
ActivityTaskManager.getService().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
里面有两个方法,一个是client.handlePauseActivity,client就是ClientTransactionHandler,即ActivityThread。这样就会进行暂停
另一个就是ActivityTaskManager.getService().activityPaused(token);通知ATMS完成暂停,进行暂停相关信息的操作,到这里暂停就完成了。其中activity的暂停流程大家也就明白了。
- 接下里就是另一个问题,那接下来的生命周期方法怎么走的,或这之前的,
// Cycle to the state right before the final requested state.
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
大家看注释,这最终状态前走完之前配置的状态
if (closestPreExecutionState != UNDEFINED) {
cycleToPath(r, closestPreExecutionState, transaction);
}
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
在cycleToPath方法里最终会调用performLifecycleSequence,其会根据配置的顺序依次调用相应的方法
/** Transition the client through previously initialized state sequence. */
private void performLifecycleSequence(ActivityClientRecord r, IntArray path, ClientTransaction transaction)
8,进程存在,复用,与暂停后面的逻辑类型,只是传入的为ResumeActivityItem这里就不展开了
9,接下来分析应用未启动的情形
- ActivityThread.main
- ActivityThread.attach
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
进入AMS的attachApplication,即通知系统进程引用启动,这里主要是线程启动,相关配置还未完成,然后调用attachApplicationLocked
thread.bindApplication(processName, appInfo, providers,
instr2.mClass,
profilerInfo, instr2.mArguments,
instr2.mWatcher,
instr2.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
disabledCompatChanges);
.....
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
- 配置应用相关的属性
- thread.bindApplcation
- mAtmInternal.attachApplication(app.getWindowProcessController());
其中thread.bindApplicaion,即ActivityThread.ApplicationThread.bindApplication
sendMessage(H.BIND_APPLICATION, data);
//在ActivityThread.h handleMessage
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break
在handleBindApplication完成application初始化,
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
}
}
mInstrumentation.callApplicationOnCreate(app);
这里可以看的ContentProvider先于application.onCreate方法,
-接下来启动Activity
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
class LocalService extends ActivityTaskManagerInternal
- 调用ATMS.localService.attachApplication
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
synchronized (mGlobalLockWithoutBoost) {
return mRootActivityContainer.attachApplication(wpc);
}
}
最后调用ActivityStack.realStartActivityLocked
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
后续流程基本与pasue和resume类似,就不描述了。
到此,activity启动相关的核心类和核心步骤都包含了,并做了个简单的介绍。到时需要深入研究那块直接找到对于的代码查看就行。希望可以帮助到大家,一起进步。