美文网首页
AMS分析「 Activity的组织方式 」

AMS分析「 Activity的组织方式 」

作者: 泡面先生_Jack | 来源:发表于2018-09-12 10:38 被阅读0次

ActivityManagerService服务可以管理系统中所有的Activity,但是AMS服务是如何管理Activity呢?

AMS中Activity的组织方式

activity组织方式.png

由上图可见,Activity在AMS中组织结构为:
1:AMS中可能管理多个屏幕设备,存放在ActivityDisplays列表中
2:每个屏幕在AMS中对应一个ActivityDisplay的数据结构
3:一个屏幕中会有多个ActivityStack
4:一个ActivityStack中可能会有多个TaskRecord
5:一个TaskRecord中可能会有多个ActivityRecord

AMS中Activity相关数据结构

ActivityRecord

ActivityRecord对应一个Activity,是Activity在AMS服务中的数据结构。下面代码是ActivityRecord的一些属性。

/**
 * An entry in the history stack, representing an activity.
 */
public final class ActivityRecord extends ConfigurationContainer implements
            AppWindowContainerListener {
    final ActivityManagerService service; // 指向AMS服务
    final IApplicationToken.Stub appToken; // ActivityRecord的Token信息,和WMS中的AppWindowToken对应
    AppWindowContainerController mWindowContainerController; 负责ActivityRecord和AppWindowToken之间联系
    public final ActivityInfo info; // Activity相关的信息
    public final ApplicationInfo appInfo; // information about activity's app
    final int launchedFromPid; // 启动该Activity的Pid
    final int launchedFromUid; // 启动该Activity的Uid
    final String launchedFromPackage; // 哪一个package启动的这个Activity
    final int userId;          // Which user is this running for?
    final Intent intent;    // the original intent that generated us
    public final String packageName; // Activity所在进程的包名
    final String processName; // 此Acitivity希望运行在哪一个进程中国
    final String taskAffinity; // as per ActivityInfo.taskAffinity
    boolean fullscreen; // 是否是全屏Acitivity?
    final boolean noDisplay;  // Activity是否显示
    private final boolean componentSpecified;  // did caller specify an explicit component?

    static final int APPLICATION_ACTIVITY_TYPE = 0;
    static final int HOME_ACTIVITY_TYPE = 1;
    static final int RECENTS_ACTIVITY_TYPE = 2;
    static final int ASSISTANT_ACTIVITY_TYPE = 3;
    int mActivityType; //Activity的类型,分为以上四种

    private CharSequence nonLocalizedLabel;  // Activity的label.
    private int labelRes;           // Activity Label资源Id
    private int icon;               // Icon资源Id.
    private int logo;               // Logo资源Id.
    private int theme;              // 主题资源Id.
    private TaskRecord task;        // 所在的TaskRecord.
    private long createTime = System.currentTimeMillis(); //创建时间
    long displayStartTime;  // when we started launching this activity
    long fullyDrawnStartTime; // when we started launching this activity
    private long startTime;         // last time this activity was started
    long lastVisibleTime;   // 最近一次visible的时间
    long cpuTimeAtResume;   // 在resume Activity时候 CPU的时间
    long pauseTime;         // 最近Pause Activity的时间
  
    ActivityRecord resultTo; // 需要接受返回数据的那个Activity
    final String resultWho; // additional identifier for use by resultTo.
    final int requestCode;  // code given by requester (resultTo)
    
    ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
    HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
    ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
    
    HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold //Activity中所有的连接信息
    UriPermissionOwner uriPermissions; // current special URI access perms.
    public ProcessRecord app;      // if non-null, hosting application //所在的进程信息

    boolean frontOfTask;    // 是不是这个Task中的根Activity?
    boolean stopped;        // 是不是这个Activity Pause完成?
    boolean finishing;      // activity 是否在 pending finish 列表?
    
    int launchMode;         // Activity 的 launch mode 属性.
    boolean visible;        // 这个 activity 的 window 是否需要显示?
                                        
    boolean sleeping;       // 是否告诉这个Activity 进入 sleep状态?
    boolean nowVisible;     // is this activity's window visible?
    boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.

TaskRecord

TaskRecord对应Android中提到的任务栈,但什么是任务栈呢?

  1. android任务栈又称为Task,它是一个栈结构,具有后进先出的特性,用于存放我们的Activity组件。
  2. 我们每次打开一个新的Activity或者退出当前Activity都会在一个称为任务栈的结构中添加或者减少一个Activity组件,因此一个任务栈包含了一个activity的集合, android系统可以通过Task有序地管理每个activity,并决定哪个Activity与用户进行交互:只有在任务栈栈顶的activity才可以跟用户进行交互。
  3. 在我们退出应用程序时,必须把所有的任务栈中所有的activity清除出栈时,任务栈才会被销毁。当然任务栈也可以移动到后台, 并且保留了每一个activity的状态. 可以有序的给用户列出它们的任务, 同时也不会丢失Activity的状态信息。
  4. 需要注意的是,一个App中可能不止一个任务栈,某些特殊情况下,单独一个Actvity可以独享一个任务栈。还有一点就是一个Task中的Actvity可以来自不同的App,同一个App的Activity也可能不在一个Task中。

下面看下TaskRecord的实现

final class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
    
    final int taskId;       // Task ID.
    Intent intent;          // 启动这个Task的Intent信息.
    
    long firstActiveTime;   // 第一次激活Task的时间.
    long lastActiveTime;    // 最近一次激活的时间
    boolean inRecents;      // Task是否在Recent列表中?
    boolean isAvailable;    // Task是否可以被launch?
    boolean rootWasReset;   // True if the intent at the root of the task had
                            // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
    boolean autoRemoveRecents;  // If true, 当Task中Activity Finish的时候自动从Recent中移除
         
    boolean hasBeenVisible; // Task中任何一个Activity是否对用户可见

    int numFullscreen;      // Task中全屏Activity的数量

    int mResizeMode;        // The resize mode of this task and its activities.
                            // Based on the {@link ActivityInfo#resizeMode} of the root activity.
    private boolean mSupportsPictureInPicture;  // Whether or not this task and its activities
            // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
            // of the root activity. 是否支持画中画模式
   
    private int mLockTaskMode;  // Which tasklock mode to launch this task in. One of
                                // ActivityManager.LOCK_TASK_LAUNCH_MODE_*

    final ArrayList<ActivityRecord> mActivities; //Task中所有的Activity

    /** Current stack. Setter must always be used to update the value. */
    private ActivityStack mStack; Task所在的ActivityStack

    /** Takes on same set of values as ActivityRecord.mActivityType */
    int taskType; Task类型

    /** Takes on same value as first root activity */
    boolean isPersistable = false;
    int maxRecents;
    
    /** Indication of what to run next when task exits. Use ActivityRecord types.
     * ActivityRecord.APPLICATION_ACTIVITY_TYPE indicates to resume the task below this one in the
     * task stack. */
    private int mTaskToReturnTo = APPLICATION_ACTIVITY_TYPE;

    // Used in the unique case where we are clearing the task in order to reuse it. In that case we
    // do not want to delete the stack when the task goes empty.
    private boolean mReuseTask = false;

    private Bitmap mLastThumbnail; // Last thumbnail captured for this item.
    private final File mLastThumbnailFile; // File containing last thumbnail.
    private final String mFilename;
    private TaskThumbnailInfo mLastThumbnailInfo;
    CharSequence lastDescription; // Last description captured for this item.

    // Whether or not this task covers the entire screen; by default tasks are fullscreen.
    //是否是全屏
    boolean mFullscreen = true; 

    // Bounds of the Task. null for fullscreen tasks.
    //Task的边界
    Rect mBounds = null;
    private final Rect mTmpStableBounds = new Rect();
    private final Rect mTmpNonDecorBounds = new Rect();
    private final Rect mTmpRect = new Rect();

    // Minimal width and height of this task when it's resizeable. -1 means it should use the
    // default minimal width/height.
    //Task缩放的最小宽高
    int mMinWidth;
    int mMinHeight;

    //负责和WindowManagerService中 Task沟通的控制类
    private TaskWindowContainerController mWindowContainerController;

ActivityStack

ActivityStack管理了一系列的TaskRecord,通过mStackId来唯一标识,持有ActivityStackSupervisor的引用。
ActivityStack的种类一共有5种

frameworks/base/core/java/android/app/ActivityManager.java
public static class StackId {
        /** Invalid stack ID. */
        public static final int INVALID_STACK_ID = -1;
 
        /** First static stack ID. */
        public static final int FIRST_STATIC_STACK_ID = 0;
 
        /** Home activity stack ID. */
        public static final int HOME_STACK_ID = FIRST_STATIC_STACK_ID;
 
        /** ID of stack where fullscreen activities are normally launched into. */
        public static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;
 
        /** ID of stack where freeform/resized activities are normally launched into. */
        public static final int FREEFORM_WORKSPACE_STACK_ID = FULLSCREEN_WORKSPACE_STACK_ID + 1;
 
        /** ID of stack that occupies a dedicated region of the screen. */
        public static final int DOCKED_STACK_ID = FREEFORM_WORKSPACE_STACK_ID + 1;
 
        /** ID of stack that always on top (always visible) when it exist. */
        public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;
 
        /** Last static stack stack ID. */
        public static final int LAST_STATIC_STACK_ID = PINNED_STACK_ID;
        ...
}
  • HOME STACK
    HOME_STACK_ID标识的ActivityStack主要维护了launcheractivity和recentactivity所在的TaskRecord

  • FREEFORM STACK
    FREEFORM_WORKSPACE_STACK_ID标识的ActivityStack主要维护了FREEFORM模式下的TaskRecord

  • DOCKED STACK
    分屏的应用进入分屏模式后会在DOCKED_STACK_ID标识的ActivityStack中

  • PINNED STACK
    进入画中画模式之后会在PINNED_STACK_ID标识的ActivityStack中。

  • FULLSCREEN STACK
    一般情况下,我们接触到的绝大部分都是在FULLSCREEN_WORKSPACE_STACK_ID(全屏显示)标识的ActivityStack中。

ActivityStack并不是开机就创建的,而是在需要时才创建。
以下的ActivityStack的实现

/**
 * State and management of a single stack of activities.
 */
class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
        implements StackWindowListener {

    // Ticks during which we check progress while waiting for an app to launch.
    static final int LAUNCH_TICK = 500;

    //Activity Pause 超时时间
    // How long we wait until giving up on the last activity to pause.  This
    // is short because it directly impacts the responsiveness of starting the
    // next activity.
    private static final int PAUSE_TIMEOUT = 500;

    //Activity STOP超时时间
    // How long we wait for the activity to tell us it has stopped before
    // giving up.  This is a good amount of time because we really need this
    // from the application in order to get its saved state.
    private static final int STOP_TIMEOUT = 10 * 1000;

    //是否显示Starting Window
    // Set to false to disable the preview that is shown while a new activity
    // is being started.
    private static final boolean SHOW_APP_STARTING_PREVIEW = true;

    //Activity 的状态
    enum ActivityState {
        INITIALIZING,
        RESUMED,
        PAUSING,
        PAUSED,
        STOPPING,
        STOPPED,
        FINISHING,
        DESTROYING,
        DESTROYED
    }

    // Stack 不是显示状态.
    static final int STACK_INVISIBLE = 0;
    // Stack 处于显示状态
    static final int STACK_VISIBLE = 1;

    //AMS服务
    final ActivityManagerService mService;
    //WMS服务
    private final WindowManagerService mWindowManager;
    //和WMS服务中TaskStack沟通的控制类
    T mWindowContainerController;
    //Recent Task
    private final RecentTasks mRecentTasks;

    //该Stack中所有的TaskRecord
    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();

    /**
     * List of running activities, sorted by recent usage.
     * The first entry in the list is the least recently used.
     * It contains HistoryRecord objects.
     */
    final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();

    /**
     * Animations that for the current transition have requested not to
     * be considered for the transition animation.
     */
    final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<>();

    /**
     *当前正处于Pausing状态的Activity
     * When we are in the process of pausing an activity, before starting the
     * next one, this variable holds the activity that is currently being paused.
     */
    ActivityRecord mPausingActivity = null;

    /**
     * 上一次Pause的Activity
     * This is the last activity that we put into the paused state.  This is
     * used to determine if we need to do an activity transition while sleeping,
     * when we normally hold the top activity paused.
     */
    ActivityRecord mLastPausedActivity = null;

    /**
     * 当前处于resume状态的Activity
     * Current activity that is resumed, or null if there is none.
     */
    ActivityRecord mResumedActivity = null;

    //Stack是否是全屏的,默认的Stack是全屏Stack
    // Whether or not this stack covers the entire screen; by default stacks are fullscreen
    boolean mFullscreen = true;
    // 当前Stack的大小,全屏的话默认为Null
    // Current bounds of the stack or null if fullscreen.
    Rect mBounds = null;

    // Stack ID
    final int mStackId;
    /** The other stacks, in order, on the attached display. Updated at attach/detach time. */
    // TODO: This list doesn't belong here...
    // 其他的Stack
    ArrayList<ActivityStack> mStacks;
    //Stack所在Display的 ID
    /** The attached Display's unique identifier, or -1 if detached */
    int mDisplayId;

    /** Run all ActivityStacks through this */
    //负责管理所有的Stack
    protected final ActivityStackSupervisor mStackSupervisor;

ActivityDisplay

Activity Display代表一个物理屏幕,mStacks是该屏幕上所有的ActivityStack

    class ActivityDisplay extends ConfigurationContainer {
        /** Actual Display this object tracks. */
        int mDisplayId; //DisplayId
        Display mDisplay; 

        //该屏幕上的所有ActivityStack
        /** All of the stacks on this display. Order matters, topmost stack is in front of all other
         * stacks, bottommost behind. Accessed directly by ActivityManager package classes */
        final ArrayList<ActivityStack> mStacks = new ArrayList<>();

        //在创建的将Display放入mActivityDisplays列表中
        ActivityDisplay() {
            mActivityDisplays.put(mDisplayId, this);
        }

ActivityDisplays

ActivityDisplays是Activity Display的列表,存放了当前所有的屏幕信息。可能会有多个屏幕同时存在。
在ActivityDisplay创建的时候就默认放入了activityDisplay列表中。

 private final SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<>();

相关文章

网友评论

      本文标题:AMS分析「 Activity的组织方式 」

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