美文网首页
深入学习ActivityRecord,ActivityStack

深入学习ActivityRecord,ActivityStack

作者: 过期的薯条 | 来源:发表于2021-01-03 14:16 被阅读0次

    1.引言

    学习android AMS模块时,有三个概念让我总是混淆,每次想起来都得重新看看。它们分别是:ActivityStack,ActivityTask 以及TaskRecord。下面正式开始老老实实学习下这三个类。看看他们是如何为AMS贡献力量的。
    转载: https://blog.csdn.net/nanyou519/article/details/104716759

    2.正题

    2.1 相关概念

    image.png

    上图中显示了用户在手机中的3个任务,A:短信,B:拍照,C:邮件,每一个任务在android中我们用一个task来表示。每一个task中包含许多不同的界面显示给用户,其中每一个界面,我们都可以看做是一个activity。我们从上图中可以看到,邮件task复用了短信和拍照中的activity A1和B2。这其实很容易理解,这种设计既节省了内存开销,而且保证同一功能界面每次展示给用户都是相同的,保证了用户体验的一致性。

    Activity中的关键数据结构有:

    • ActivityRecord

    • TaskRecord

    • ActivityStack

    • ActivityDisplay

    • ActivityStackSupervisor

    • ProcessRecord

    我们先用一张图来描述这些数据结构之间的关系,然后在分别对它们进行一些解释。

    image.png
    • ActivityRecord
        ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,
                int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage,
                @Nullable String _launchedFromFeature, Intent _intent, String _resolvedType,
                ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo,
                String _resultWho, int _reqCode, boolean _componentSpecified,
                boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
                ActivityOptions options, ActivityRecord sourceRecord) {
            super(_service.mWindowManager, new Token(_intent).asBinder(), TYPE_APPLICATION, true,
                    null /* displayContent */, false /* ownerCanManageAppTokens */);
    
            mAtmService = _service;
            appToken = (Token) token;
            info = aInfo;
            mUserId = UserHandle.getUserId(info.applicationInfo.uid);//多用户 userid
            packageName = info.applicationInfo.packageName;//包名
            mInputApplicationHandle = new InputApplicationHandle(appToken);
            intent = _intent;
    
            // If the class name in the intent doesn't match that of the target, this is probably an
            // alias. We have to create a new ComponentName object to keep track of the real activity
            // name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
            if (info.targetActivity == null
                    || (info.targetActivity.equals(intent.getComponent().getClassName())
                    && (info.launchMode == LAUNCH_MULTIPLE
                    || info.launchMode == LAUNCH_SINGLE_TOP))) {
                mActivityComponent = intent.getComponent();
            } else {
                mActivityComponent =
                        new ComponentName(info.packageName, info.targetActivity);
            }
    

    ActivityRecord是对Activity的描述。

    • TaskRecord
      ActivityRecord 会通过setTask方法引入一个TaskRecord。TaskRecord是一个栈式管理结构,它的职责就是管理ActivityRecord,记录activity开启的先后顺序。每个ActivityRecord都必须属于一个TaskRecord,TaskRecord与ActivityRecord是一对多的关系,栈顶的ActivityRecord表示当前用户可见的界面。TaskRecord中的成员变量

    final ArrayList<ActivityRecord> mActivities;//按照顺序保存的ActivityRecord
    private ActivityStack mStack //当前TaskRecord 所属于的ActivityStack

    • ActvityStack
      它的职责是管理TaskRecord。每个TaskRecord都必须属于一个ActivityStack,TaskRecord与ActivityStack是一对多的关系,栈顶的TaskRecord代表当前用户可见的任务。ActivityStack中的成员变量.
    /**
    * The back history of all previous (and possibly still
    * running) activities.  It contains #TaskRecord objects.
    */
    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
    

    每个Activity都会有一个状态,譬如显示,销毁。这些状态的变化都需要ActivityStack来进行管理。Activity的状态是通过ActivityStack中的成员变量ActivityState来定义:

    enum ActivityState {
        INITIALIZING,
        RESUMED,
        PAUSING,
        PAUSED,
        STOPPING,
        STOPPED,
        FINISHING,
        DESTROYING,
        DESTROYED,
        RESTARTING_PROCESS
    }
    

    • ActivityDisplay
      ActivityDisplay表示一个屏幕,Android支持三种屏幕:主屏幕,外接屏幕(HDMI等),虚拟屏幕(投屏)。一般情况下,即只有主屏幕时,ActivityStackSupervisor与ActivityDisplay都是系统唯一

    • ActivityStackSupervisor
      ActivityStackSupervisor中有俩个变量:mHomeStack 和 mFocusedStack

    /** The stack containing the launcher app. Assumed to always be attached to
         * Display.DEFAULT_DISPLAY. */
         ActivityStack mHomeStack;
         
        /** The stack currently receiving input or launching the next activity. */
        ActivityStack mFocusedStack;
    

    mHomeStack管理launcher app;mFocusedStack 管理非launcher的app

    • ProcessRecord
      记录着属于一个进程的所有ActivityRecord,运行在不同TaskRecord中的ActivityRecord可能属于同一个ProcessRecord

    通过我们上面的描述,我们可以看出这些数据结构是一层包含一层,层层递推的。

    image.png

    当我们启动一个新的activity的时候,首先会为这个activity创建一个ActivityRecord,然后在为这个Activty分配所属的TaskRecord,这个TaskRecord又要分配到对应的ActivityStack,ActivityStack也要分配到所属的ActivityDisplay。这一整套关系确立之后,我们才能够真正启动这个Activity。为了尽量简化我们后面Activity启动流程的分析,这里我们就先把这些数据结构的创建过程单独拎出来分析。

    2.2 代码分析

    • ActivityRecord的创建
      ActivityRecord的创建比较简单,它是在activity启动过程中的startActivity函数中被创建的
    
    /frameworks/base/services/core/java/com/android/server/wm/
    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,
        SafeActivityOptions options,boolean ignoreTargetSecurity, boolean 
        componentSpecified, ActivityRecord[] outActivity,
        TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
        PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
    ......
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
        callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
        resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
        mSupervisor, checkedOptions, sourceRecord);
    ......
    
    

    我们主要看一下ActivityDisplay,ActivityStack和TaskRecord的创建和联系过程,这个过程相对繁琐,我们先把时序图列出来,然后跟着时序图来分析代码

    image.png
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
    1465              IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    1466              int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
    1467              ActivityRecord[] outActivity, boolean restrictedBgActivity) {
              ......
    1665          // Should this be considered a new task?
    1666          int result = START_SUCCESS;
    1667          if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
    1668                  && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
    1669              newTask = true;
                      //开始为ActivityRecord配置对应的TaskRecord和ActivityStack
    1670              result = setTaskFromReuseOrCreateNewTask(taskToAffiliate);
    
    

    接下来我们看下TaskRecord和ActivityStack的创建和关联过程, 其实整个Activity这些重要结构体的创建以及对应关系的建立比较复杂,它有很多情况,对应不同的路径,我们这里只是选择了一种情况来进行分析。

    //frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
    2298      private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
    2299          if (mRestrictedBgActivity && (mReuseTask == null || !mReuseTask.containsAppUid(mCallingUid))
    2300                  && handleBackgroundActivityAbort(mStartActivity)) {
    2301              return START_ABORTED;
    2302          }
    2303          // 1.创建获取ActivityStack
    2304          mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions);
    2305  
    2306          // Do no move the target stack to front yet, as we might bail if
    2307          // isLockTaskModeViolation fails below.
    2308  
    2309          if (mReuseTask == null) {
                      //2.创建TaskRecord
    2310              final TaskRecord task = mTargetStack.createTaskRecord(
    2311                      mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId),
    2312                      mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
    2313                      mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
    2314                      mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord,
    2315                      mOptions);
                      //3.将ActivityRecord添加到TaskRecord中
    2316              addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
    2317              updateBounds(mStartActivity.getTaskRecord(), mLaunchParams.mBounds);
    2318  
    2319              if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
    2320                      + " in new task " + mStartActivity.getTaskRecord());
    2321          } else {
    2322              addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
    2323          }
    2324  
    2325          if (taskToAffiliate != null) {
    2326              mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
    2327          }
    2328  
    2329          if (mService.getLockTaskController().isLockTaskModeViolation(
    2330                  mStartActivity.getTaskRecord())) {
    2331              Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
    2332              return START_RETURN_LOCK_TASK_MODE_VIOLATION;
    2333          }
    2334  
    2335          if (mDoResume) {
                      //4.将当前要显示的ActivityStack移到栈顶
    2336              mTargetStack.moveToFront("reuseOrNewTask");
    2337          }
    2338          return START_SUCCESS;
    2339      }
    
    
    

    我们可以看到setTaskFromReuseOrCreateNewTask主要做了4件事:

    1.为已创建的ActivityRecord寻找创建ActivityStack

    2.创建TaskRecord

    3.将ActivityRecord添加到TaskRecord中

    4.将ActivityStack移到栈顶准备显示

    这样这几个重要的数据结构,就像我们上面列出的它们之间的关系图一样,建立起来了层层包含的关系。下面我们来一件件来分析它们

    //frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
    2589      private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, int launchFlags,
    2590              ActivityOptions aOptions) {
    2591          final TaskRecord task = r.getTaskRecord();
    2592          ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
    2593          if (stack != null) {
    2594              return stack;
    2595          }
           ......
    

    getLaunchStack看名字也可以猜到是寻找合适的ActivityStack,成功之后直接返回。所以上面省略的部分应该是对ActivityStack创建获取失败之后的处理,我们不用关心,直接去看getLaunchStack函数。

    frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
    2673      private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
    2674              ActivityOptions aOptions) {
    2675          // We are reusing a task, keep the stack!
    2676          if (mReuseTask != null) {
    2677              return mReuseTask.getStack();
    2678          }
    2679  
    2680          if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
    2681                   || mPreferredDisplayId != DEFAULT_DISPLAY) {
    2682              final boolean onTop = aOptions == null || !aOptions.getAvoidMoveToFront();
    2683              final ActivityStack stack =
    2684                      mRootActivityContainer.getLaunchStack(r, aOptions, task, onTop, mLaunchParams);
    2685              return stack;
    2686          }
              ......
    

    这里调用了RootActivityContainer的getLaunchStack函数

    //frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
    1673      <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
    1674              @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop,
    1675              @Nullable LaunchParamsController.LaunchParams launchParams) {
    1676          int taskId = INVALID_TASK_ID;
    1677          int displayId = INVALID_DISPLAY;
    1678          //Rect bounds = null;
              ......
    1706          if (displayId != INVALID_DISPLAY && canLaunchOnDisplay(r, displayId)) {
    1707              if (r != null) {
                          //get合适的Activitystack,如果存在直接返回
    1708                  stack = (T) getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
    1709                          launchParams);
    1710                  if (stack != null) {
    1711                      return stack;
    1712                  }
    1713              }
                      //根据displayId获取ActivityDisplay对象
    1714              final ActivityDisplay display = getActivityDisplayOrCreate(displayId);
    1715              if (display != null) {
                          //根据ActivityDisplay创建ActivityStack
    1716                  stack = display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
    1717                  if (stack != null) {
    1718                      return stack;
    1719                  }
    1720              }
    1721          }
              ......
    
    

    这根据displayId获取对应的ActivityDisplay对象,然后通过这个ActivityDisplay对象来创建ActivityStack。

    375      <T extends ActivityStack> T getOrCreateStack(int windowingMode, int activityType,
    376              boolean onTop) {
    377          if (!alwaysCreateStack(windowingMode, activityType)) {
    378              T stack = getStack(windowingMode, activityType);
    379              if (stack != null) {
    380                  return stack;
    381              }
    382          }
    383          return createStack(windowingMode, activityType, onTop);
    384      }
    385  
    386      /**
    387       * Returns an existing stack compatible with the input params or creates one
    388       * if a compatible stack doesn't exist.
    389       * @see #getOrCreateStack(int, int, boolean)
    390       */
    391      <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r,
    392              @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType,
    393              boolean onTop) {
    394          // First preference is the windowing mode in the activity options if set.
    395          int windowingMode = (options != null)
    396                  ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
    397          // Validate that our desired windowingMode will work under the current conditions.
    398          // UNDEFINED windowing mode is a valid result and means that the new stack will inherit
    399          // it's display's windowing mode.
    400          windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
    401          return getOrCreateStack(windowingMode, activityType, onTop);
    402      }
    
    

    终于看到了createStack函数,看名字感觉离最终ActivityStack的创建已经不远。

    //frameworks/base/services/core/java/com/android/server/wm/ActivityDisplay.java
    420      <T extends ActivityStack> T createStack(int windowingMode, int activityType, boolean onTop) {
              ......
    454          final int stackId = getNextStackId();
    455          return createStackUnchecked(windowingMode, activityType, stackId, onTop);
    456      }
    
    

    获取下一个stackId,继续调用createStackUnchecked完成ActivityStack的创建

    //frameworks/base/services/core/java/com/android/server/wm/ActivityDisplay.java
    459      <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
    460              int stackId, boolean onTop) {
    461          if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
    462              throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
    463                      + "activity type.");
    464          }
    465          return (T) new ActivityStack(this, stackId,
    466                  mRootActivityContainer.mStackSupervisor, windowingMode, activityType, onTop);
    467      }
    

    终于完成了ActivityStack的创建。而且我们会发现ActivityStack是由ActivityDisplay创建的,至此ActivityRecord和ActivityStack都已经创建完成,我们接着回到setTaskFromReuseOrCreateNewTask函数去看下TaskRecord的创建

    //frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
    5475      TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
    5476              IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    5477              boolean toTop, ActivityRecord activity, ActivityRecord source,
    5478              ActivityOptions options) {
                  //创建TaskRecord
    5479          final TaskRecord task = TaskRecord.create(
    5480                  mService, taskId, info, intent, voiceSession, voiceInteractor);
    5481          // add the task to stack first, mTaskPositioner might need the stack association
                  //新建的TaskRecord插入到了ActivityStack中mTaskHistory中,将TaskRecord和ActivityStack关联在了一起。
    5482          addTask(task, toTop, "createTaskRecord");
    5483          final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
    5484          final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
    5485                  .isKeyguardOrAodShowing(displayId);
    5486          if (!mStackSupervisor.getLaunchParamsController()
    5487                  .layoutTask(task, info.windowLayout, activity, source, options)
    5488                  && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
    5489              task.updateOverrideConfiguration(getRequestedOverrideBounds());
    5490          }
    5491          task.createTask(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
    5492          return task;
    5493      }
    
    
    

    到这我们完成了TaskRecord的创建,并且将TaskRecord与ActivityStack建立起了联系。我们继续回到setTaskFromReuseOrCreateNewTask接着执行第3步操作。

    //frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
    2554      private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
    2555          if (mStartActivity.getTaskRecord() == null || mStartActivity.getTaskRecord() == parent) {
                      //将当前Activity插入到TaskRecord中的mActivities的顶部,建立ActivityRecord与TaskRecord的联系
    2556              parent.addActivityToTop(mStartActivity);
    2557          } else {
    2558              mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
    2559          }
    2560      }
     
    

    最后调用moveToFront,将stack移到栈的顶部。至此我们已经完成了Acitivity启动所需要的ActivityRecord,TaskRecord,ActivityStack的创建,并按照我们最开始讲的Activity的管理方式,对它们建立起了关联。Activity的运行过程中,可能的情况非常之多,但我们只要牢记这几个结构体之间的关系,Activity的管理就是对这几个关键结构体根据不同的情况一直进行调整,这样分析代码的时候思路就会清晰很多.

    总结:


    image.png

    相关文章

      网友评论

          本文标题:深入学习ActivityRecord,ActivityStack

          本文链接:https://www.haomeiwen.com/subject/urqnbktx.html