Activity启动流程分析

2,719 阅读8分钟

最近在复习看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启动相关的核心类和核心步骤都包含了,并做了个简单的介绍。到时需要深入研究那块直接找到对于的代码查看就行。希望可以帮助到大家,一起进步。