Android四大组件系列1 AMS相关数据结构

一 概述

AMS 也即 ActivityManagerService 是 Android framework 的三大核心功能之一(其他两个是 View,WindowManagerService),它的代码庞大(约2万行),逻辑纷繁,主要负责系统中四大组件的启动、切换、调度及应用程序进程的管理和调度等工作。对于这样庞大复杂的代码,我们应该从它的功能角度出发,分析它的每个功能对应的代码逻辑,逐个突破。

AMS 是运行在 SystemServer 进程中众多服务中的一个(如:PackageManagerService,WindowManagerService 等),这些服务分别运行在不同的线程中.其他进程需要通过 Binder 机制来和 ActivityManagerService 跨进程通信,一个应用进程在和 ActivityManagerService 交互的过程中,还涉及到 ActivityThread,ApplicationThread 等类的交互,下面将介绍这几个类的相关概念,以及他们之间的交互模型。

二 ActivityThread和ApplicationThread

ActivityThread 类代表的就是 Android 应用程序进程中的主线程,注意它代表主线程而不是说它就是一个 Thread 线程类,因为系统在创建完一个新应用程序进程后,会在这个进程的主线程中调用 ActivityThread 类的 main 函数来初始化这个进程,在这个 main 函数里会执行一个 loop 循环使当前主线程进入消息循环,所以我们称 Android 应用程序进程的入口函数是 ActivityThread 类的 main 函数,也就是说一个ActivityThread 类对应于一个应用程序进程。

public final class ActivityThread extends ClientTransactionHandler {
    ......
    final ApplicationThread mAppThread = new ApplicationThread();
    final Looper mLooper = Looper.myLooper();
    final H mH = new H();
    final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
    ......
    final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
    ......
    Application mInitialApplication;
    final ArrayList<Application> mAllApplications
            = new ArrayList<Application>();
    ......
    final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders
        = new ArrayMap<IBinder, ProviderClientRecord>();
    ......
    private class ApplicationThread extends IApplicationThread.Stub {
        ......   
    }
    ......
}

ActivityThread 中有几个重要的实例变量需要简要介绍下,成员变量 mActivities 包含了当前进程中所有的 Activity 组件信息,注意集合中不是简单的保存 Activity 实例,而是将每个 Activity 实例对应的相关数据封装成一个 ActivityClientRecord 保存起来,内部保存了很多 Activity 相关的数据,其中当然也有其对应的 Activity 实例。同样的,mServices 保存的是当前进程中所有的 Service 组件信息,不过就是直接存放的当前 Service 的信息,没有封装。mLocalProviders 保存的是当前进程中所有的 ContentProvider 组件信息。这些集合都有一个 IBinder 类型的 Key,其作用也就是显而易见的,即为了进行 IPC 调用,这个 IBinder 类型的 Key 作为一个唯一标识使用,通过这个 Key 可以在 AMS 中找到其对应的组件信息记录。

mAppThread 是 ApplicationThread 类型的变量,它是 ActivityThread 的内部类,也是一个 Binder 类型的对象,也就是说可以作为服务端实现跨进程通信。那么,在应用进程中的 ActivityThread 通过 Binder 机制和系统进程中的 AMS 通信时,使用的就是 ApplicationThread 对象来作为应用进程的服务端,接收 AMS 的指令并将指令发送给 ActivityThread 执行,所以它是 ActivityThread 与 AMS 跨进程通信的桥梁。因为 ApplicationThread 对象会被 Binder 线程调用,而 ActivityThread 是运行在主线程中的,所以 ApplicationThread 会通过 mH 对象发送消息给主线处理。
在这里插入图片描述

三 AMS主要相关类

3.1 ProcessRecord

一个 APK 文件运行时会对应一个进程, 当然, 多个 APK 文件也可以运行在同一个进程中。ProcessRecord 正是记录一个进程中的相关信息, 该类中内部变量可分为三个部分,主要信息包括:该进程对应的 APK 文件的内部信息,该进程的内存状态信息,以及该进程中包含的所有 Activity、Provider、Service 等组件信息。

class ProcessRecord implements WindowProcessListener {
    ......
    final ApplicationInfo info; //进程中第一个APK包信息 
    ......
    final String processName;
    ......
    // List of packages running in the process
    final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList = new ArrayMap<>();
    ......
    IApplicationThread thread;
    ......
    int pid;
    ......
    final ArraySet<BroadcastRecord> curReceivers = new ArraySet<BroadcastRecord>();
    ......
    // all ServiceRecord running in this process
    final ArraySet<ServiceRecord> services = new ArraySet<>();
    ......
    final ArrayMap<String, ContentProviderRecord> pubProviders = new ArrayMap<>();
}

3.2 TaskRecord

在 Android 中,每一件事可以被看作是一个 Task,一个 Task 又可以被细分成多个子步骤,每个子步骤可以被看作是一个 Activity。这个 Activity 既可以是本程序进程中的 Activity,也可以是其他程序进程中的的 Activity,这种基于组件的设计,弱化了进程的概念,通过重用 Activity 可以节省一定的开销,同时也为用户提供了一致的界面和用户体验。比如,你在自己的程序中想发邮件,你就可以定义一个具有 “send” 动作的 Intent,并且传入一些数据,如对方邮箱地址、邮件内容等,然后就会有系统的 Activity 被打开,发送完邮件,点击返回仍然还是会回到你的应用程序当中,这让用户看起来好像刚才那个编写邮件的 Activity 就是你的应用程序当中的一部分。所以说,即使有很多个 Activity 分别都是来自于不同应用程序的,Android 系统仍然可以将它们无缝地结合到一起,之所以能实现这一点,就是因为这些 Activity 都是存在于一个相同的任务 (Task) 当中的,用数据结构 TaskRecord 表示。

Task 中有一个 ActivityRecord 的集合 mActivities,它是以 Stack 的方式来管理其中的 Activity,所以,具有相同 Task 的 Activity 会放在同一个集合中(也叫回退栈), 先启动的 Activity 成为栈底成员,最后启动的 Activity 将作为栈顶成员显示在界面上。当有多个 Task 时,Android 系统只支持一个处于前台的 Task,其余的 Task 均处于后台,这些后台 Task 内部 Activity 保持顺序不变,用户可以一次将整 个Task 挪到后台或置为前台。比如,当用户在 Home 界面上点击了一个应用的图标时,这个应用的任务就会被转移到前台。如果这个应用目前并没有任何一个任务的话(说明这个应用最近没有被启动过),系统就会去创建一个新的任务,并且将该应用的主 Activity 放入到返回栈当中。如果用户一直地按 Back 键,这样返回栈中的 Activity 会一个个地被移除,直到最终返回到主屏幕。当返回栈中所有的 Activity 都被移除掉的时候,对应的任务也就不存在了。用过 Android 手机的同学应该知道,长按 Home 键,系统会弹出近期 Task 列表,使用户能快速在多个 Task 间切换。
在这里插入图片描述
下面我们用一个例子来说明这种管理方式。
在这里插入图片描述
上图中显示了用户在手机中的3个任务,A:短信,B:拍照,C:邮件,每一个任务在 Android 中是用一个 Task 来表示。每一个 Task 中包含许多不同的界面显示给用户,其中每一个界面,我们都可以看做是一个 Activity。我们从上图中可以看到,邮件 Task 复用了短信和拍照中的 Activity A1 和 B2。这其实很容易理解,这种设计既节省了内存开销,而且保证同一功能界面每次展示给用户都是相同的,保证了用户体验的一致性。在 Android 中要实现上面这样的一套管理机制,需要设计一些数据结构来支持,涉及到的数据结构有:ActivityRecord,TaskRecord,ActivityStack,ActivityDisplay,ActivityStackSupervisor 和 ProcessRecord,我们先用一张图来描述这些数据结构之间的关系,然后在分别对它们进行说明。
在这里插入图片描述

class TaskRecord extends ConfigurationContainer {    
    ......
    final int taskId;       // Unique identifier for this task.
    String affinity;        // The affinity name for this task, or null; may change identity.
    ......
    /** List of all activities in the task arranged in history order */
    final ArrayList<ActivityRecord> mActivities; 
    /** Current stack. Setter must always be used to update the value. */
    private ActivityStack mStack;//当前任务的管理者    
    ......
}

TaskRecord 的 affinity 属性是第一次创建这个 Task 时指定的值,可以把他当作这个 Task 的名字,Activity 所在的 Task 可以通过 AndroidManifest.xml 中 标签中的 android:taskAffinity=“xxx” 来指定,通常不去主动设置一个 Activity 的 taskAffinity 属性,那么 taskAffinity 的值缺省使用包名。所以,同一个应用中所有的 Activity 的 taskAffinity 属性值默认都是相同的,都是包名.所以在应用中使用 FLAG_ACTIVITY_NEW_TASK 标志去启动一个本应用中的一个 Activity,也不会创建一个新的 Task,除非这个 Activity 额外指定了不同的 taskAffinity 属性值。

mActivities 表示当前栈中管理的所有 ActivityRecord.

mStack 表示当前 TaskRecord 所属的 ActivityStack。TaskRecord 除了要维护管理它包含的 ActivityRecord,它本身作为一个栈,还需要维护自身任务栈的状态。

3.3 ActivityRecord

AMS 中使用 ActivityRecord 数据类来保存每个 Activity 的相关信息,该数据类中的变量主要包含两部分:

  • 配置信息:该 Activity 组件相关的 XML 中的配置信息 ,比如 ,属于哪个 Package ,所在的进程名称、任务名、组件类名、logo、主题,等等,这些信息基本上是固定的.
  • 运行状态信息:比如 idle、stop、fishing 等,这些变量一般为 boolean 类型,这些状态值与应用程序中所说的 onCreate、onPause、onStart 等生命周期状态有所不同.
final class ActivityRecord extends ConfigurationContainer {
    ......
    final ActivityTaskManagerService mAtmService;// owner
    final IApplicationToken.Stub appToken;// window manager token
    private TaskRecord task;        // the task this is in.
    ......
}

ActivityRecord 中的大部分成员变量都是记录 Activity 的相关信息,其中有一个成员变量 appToken 需要重点关注,从定义可以看出 appToken 是用来进行跨进程通信的,Android 系统中用 AMS 来管理 Activity,而它和应用程序是运行在不同进程中的,appToken 就可以看做是连接系统进程和应用进程的桥梁,我们后面会详细介绍它的作用.成员变量 task 代表当前 Activity 属于哪一个栈,相关的栈信息就保存在 TaskRecord 中。ActivityRecord 与 TaskRecord 的关系简单总结如下:

TaskRecord 的职责就是管理 ActivityRecord,记录 Activity 开启的先后顺序。每个 ActivityRecord 都必须属于一个 TaskRecord,TaskRecord 与 ActivityRecord 是一对多的关系,栈顶的 ActivityRecord 表示当前用户可见的界面.

3.4 ActivityStack

对于多个 Task 的组织及管理方式,Android 设计了一个 ActivityStack 类来负责上述工作,它的职责是管理 TaskRecord。每个 TaskRecord 都必须属于一个 ActivityStack,ActivityStack 与 TaskRecord 是一对多的关系,栈顶的 TaskRecord 代表当前用户可见的任务。ActivityStack 用 mTaskHistory 这个 ArrayList 保存所有属于该 ActivityStack 的 TaskRecord 实例(这个集合叫做任务栈)。另外 ActivityStack 有多种类型:mHomeStack,mLastFocusedStack 等,在 ActivityStack 中用 mStackId 来标识。

class ActivityStack extends ConfigurationContainer {
    ...... 
    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>(); 
    ......
    final int mStackId;
    ......
    /** Run all ActivityStacks through this */
    protected final ActivityStackSupervisor mStackSupervisor;
    ......
    enum ActivityState {
        INITIALIZING,
        RESUMED,
        PAUSING,
        PAUSED,
        STOPPING,
        STOPPED,
        FINISHING,
        DESTROYING,
        DESTROYED,
        RESTARTING_PROCESS
    }
    ......
}

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

3.5 ActivityDisplay

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

3.6 ActivityStackSupervisor

在 Android4.4 以后,并不采用原先的 mHistory 来管理所有的 ActivityRecord ,而是按层次进行管理,这其中就引入了一个新的类:ActivityStackSupervisor,用来管理所有的 ActivityStack(之前只有一个 mMainStack,由 AMS 来管理的 )

public class ActivityStackSupervisor implements RecentTasks.Callbacks {
    ......
    final ActivityTaskManagerService mService;
    ......
    WindowManagerService mWindowManager;
    ......
}

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

四 Activity通信

我们知道,在 Android 中的 system_server 进程中运行着系统中重要的服务(AMS,PMS,WMS).对系统服务 AMS 来说,它需要与应用程序进行通信,调度 Activity 执行,管理 Activity 的状态。

对每一个应用程序来说,它运行在独立的进程中,有自己独立的内存空间,它需要接受 AMS 的调度,执行 Activity 相应的生命周期回调函数。所以不管是从系统到应用还是从应用到系统,它们都需要跨进程调用。

Android 中的跨进程通信方法就是 Binder。Android 为系统与应用间的相互通信设计了两个 Binder 接口。

IApplicationThread: 系统进程请求应用进程的接口。

IActivityTaskManager,IActivityManager:应用进程请求系统进程的接口。以前的版本只有 IActivityManager 一个接口,但是因为 AMS 的代码实在太多了,所以谷歌在最近的版本里新加了 IActivityTaskManager,把之前一些 AMS 里面的工作挪到了 ActivityTaskManager 里面.

我们在介绍 Activiy 有关的重要数据结构的时候提到了 ProcessRecord,ProcessRecord 的一个重要的作用就是 AMS 可以利用它远程调用到应用进程中的函数。在应用进程 ActivityThread 创建的时候,它会将自己的 ApplicationThread 绑定到 AMS 中,整个绑定过程如下:

ActivityThread.main() -> ActivityThread.attach() -> IActivityManager.attachApplication(ApplicationThread)

AMS 作为 IActivityManager 接口服务端的实现,会响应客户端的请求,最终 AMS.attachApplication() 会被执行,该函数接收跨进程传递过来的 ApplicationThread 实例,然后将其赋值给 AMS 维护的 ProcessRecord.thread。这样后面 AMS 就可以通过 ProcessRecord.thread 调用应用进程中的函数了。

我们除了要在应用进程和系统进程中进行通信,还需要一个方法能够在应用进程和系统进程中同步 Activity 的状态。

AMS 中采用 ActivityRecord 来描述 Activity,应用进程中采用 ActivityClientRecord 和 Activity。这三者之间一一对应,从而达到 Activity 状态在系统进程和应用进程之间的同步。

而达到这一目的的关键就是我们在讲解 ActivityRecord 时提到的成员变量 appToken。

final class ActivityRecord extends ConfigurationContainer {
	final IApplicationToken.Stub appToken; // window manager token 
	ActivityRecord(ActivityTaskManagerService _service, ......) {
			......
			appToken = new Token(this, _intent);
			......
	} 
	static class Token extends IApplicationToken.Stub {
        private final WeakReference<ActivityRecord> weakActivity;
        private final String name;

        Token(ActivityRecord activity, Intent intent) {
            weakActivity = new WeakReference<>(activity);
            name = intent.getComponent().flattenToShortString();
        }
        private static @Nullable ActivityRecord tokenToActivityRecordLocked(
                Token token) {
            if (token == null) {
                return null;
            }
            ActivityRecord r = token.weakActivity.get();
            if (r == null || r.getActivityStack() == null) {
                return null;
            }
            return r;
        }
        ......
        @Override
        public String getName() {
            return name;
        }
    }
}

在创建 ActivityRecord 的时候我们会对 appToken 进行赋值,然后我们发现 Token 中持有 ActivityRecord 的弱引用,也就是说可以通过 appToken 找到 ActivityRecord。因此我们只要把 appToken 传到 App 进程中,并赋值给 ActivityClientRecord 和 Activity,就可以建立这三者之间的对应关系。

frameworks/base/core/java/android/app/ActivityThread.java

public final Activity startActivityNow(Activity parent, String id,
        Intent intent, ActivityInfo activityInfo, IBinder token,
        Bundle state, ......, IBinder assistToken) {
        ActivityClientRecord r = new ActivityClientRecord();
            r.token = token;
            r.assistToken = assistToken;
            r.ident = 0;
            r.intent = intent;
            r.state = state;
            r.parent = parent;
            r.embeddedID = id;
            r.activityInfo = activityInfo;
            r.lastNonConfigurationInstances = lastNonConfigurationInstances;
        if (localLOGV) {
            ComponentName compname = intent.getComponent();
            String name;
            if (compname != null) {
                name = compname.toShortString();
            } else {
                name = "(Intent " + intent + ").getComponent() returned null";
            }
            Slog.v(TAG, "Performing launch: action=" + intent.getAction()
                    + ", comp=" + name
                    + ", token=" + token);
        }
        
        return performLaunchActivity(r, null /* customIntent */);
    }

可以看到 ActivityThread 中创建了 ActivityClientRecord,并将 token 赋值给了该 ActivityClientRecord.

private Activity performLaunchActivity(ActivityClientRecord r, 
        Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
     if (r.packageInfo == null) {
         r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
               Context.CONTEXT_INCLUDE_CODE);
     }

        Activity activity = null;
        try {
            ......
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            ......
        } catch (Exception e) {
            ......
        }

   if (activity != null) {
         ......
         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);
         ......
    }
}

frameworks/base/core/java/android/app/Activity.java

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, ......) {
        attachBaseContext(context);
        ......
        mToken = token;
        ......
}

Activity.attach() 中将 ActivityClientRecord.token 赋值给了Activity.mToken。至此,ActivityRecord、ActivityClientRecord、Activity 三者的一一对应关系就建立完毕了。

总结一下,ActivityRecord 和 ActivityClientRecord 都是保存 Activity 信息的对象。只不过,ActivityRecord 归系统进程使用,ActivityClientRecord 归应用进程使用。他们之间通过 token 建立同步关系。

五 数据结构的生成

当我们启动一个新的 Activity 的时候,首先会为这个 Activity 创建一个 ActivityRecord,然后再为这个 Activty 分配所属的 TaskRecord,这个 TaskRecord 又要分配到对应的 ActivityStack 中,而 ActivityStack 也要分配到所属的 ActivityDisplay。

这一整套关系确立之后,我们才能够真正启动这个 Activity。为了便于理解我们后面对 Activity 启动流程的分析,这里我们就先把这些数据结构的创建过程单独拎出来分析。

5.1 ActivityRecord 的创建

ActivityRecord 的创建比较简单,它是在 Activity 启动过程中的 startActivity 函数中被创建的

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

private int startActivity(IApplicationThread caller, Intent intent,
      Intent ephemeralIntent, String resolvedType, ......) {
        ......
        ActivityRecord r = new ActivityRecord(mService, callerApp,
        callingPid, callingUid, callingPackage, intent, resolvedType, 
        aInfo, mService.getGlobalConfiguration(), resultRecord, 
        resultWho, requestCode, componentSpecified, 
        voiceSession != null, mSupervisor, options, sourceRecord);
        ......
}

5.2 ActivityDisplay,ActivityStack,TaskRecord 的创建

我们主要看一下 ActivityDisplay,ActivityStack 和 TaskRecord 的创建和联系过程,这个过程相对繁琐,我们先把时序图列出来,然后跟着时序图来分析代码。
在这里插入图片描述
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

private int startActivityUnchecked(final ActivityRecord r, 
    ActivityRecord sourceRecord, ......) {
        ......
        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) {
           ......
            // 开始为 ActivityRecord 配置对应的 TaskRecord 和 ActivityStack
            result = setTaskFromReuseOrCreateNewTask(
                    taskToAffiliate, preferredLaunchStackId, topStack);
        } else {
            ......
        }
        ......
}

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

private ActivityStack mTargetStack;

private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate,
        int preferredLaunchStackId, ActivityStack topStack) {
        // 1.创建获取 ActivityStack
        mTargetStack = computeStackFocus(
                mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
        // Do no move the target stack to front yet, as we might bail if
        // isLockTaskModeViolation fails below.
        if (mReuseTask == null) {
            // 2.创建 TaskRecord
            final TaskRecord task = mTargetStack.createTaskRecord(
                mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
                mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                ........);
            // 3.将 ActivityRecord 添加到 TaskRecord 中
            addOrReparentStartingActivity(task, 
                    "setTaskFromReuseOrCreateNewTask - mReuseTask");
            if (mLaunchBounds != null) {
                ......
            }
            ......
        } else {
            addOrReparentStartingActivity(mReuseTask, 
                    "setTaskFromReuseOrCreateNewTask");
        }
        ......
        if (mDoResume) {
            // 4.将当前要显示的 ActivityStack 移到栈顶
            mTargetStack.moveToFront("reuseOrNewTask");
        }
        return START_SUCCESS;
}

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

  • 为已创建的 ActivityRecord 寻找创建 ActivityStack
  • 创建 TaskRecord
  • 将 ActivityRecord 添加到 TaskRecord 中
  • 将 ActivityStack 移到栈顶准备显示

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

5.2.1 ActivityStack 创建

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask,
    Rect bounds, int launchFlags, ActivityOptions aOptions) {
        final TaskRecord task = r.getTask();
        ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
        if (stack != null) {
            return stack;
        }
        ......
}

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

ActivityStarter.java

private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, 
    TaskRecord task, ActivityOptions aOptions) {
        // We are reusing a task, keep the stack!
        if (mReuseTask != null) {
            return mReuseTask.getStack();
        }

        if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
                 || mPreferredDisplayId != DEFAULT_DISPLAY) {
            final boolean onTop = aOptions == null ||
                    !aOptions.getAvoidMoveToFront();
            final ActivityStack stack =
                    mRootActivityContainer.getLaunchStack(r, aOptions, task, 
                    onTop, mLaunchParams, ......);
            return stack;
        }
        ......
}

这里调用了 RootActivityContainer 的 getLaunchStack 函数

frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java

<T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
     @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask,
     boolean onTop, @Nullable LaunchParamsController.LaunchParams launchParams, 
     int realCallingPid, int realCallingUid) {
     
        int taskId = INVALID_TASK_ID;
        int displayId = INVALID_DISPLAY;
        // Rect bounds = null;
        // We give preference to the launch preference in activity options.
        if (options != null) {
            taskId = options.getLaunchTaskId();
            displayId = options.getLaunchDisplayId();
        }
        ......
        // Checking if the activity's launch caller, or the realCallerId of
        // the activity from start request (i.e. PendingIntent caller)
        // is allowed to launch on the display.
        if (displayId != INVALID_DISPLAY && (canLaunchOnDisplay(r, displayId)
                || canLaunchOnDisplayFromStartRequest)) {
            if (r != null) {
                // get 合适的 Activitystack,如果存在直接返回
                stack = (T) getValidLaunchStackOnDisplay(displayId, r,
                candidateTask, options, launchParams);
                if (stack != null) {
                    return stack;
                }
            }
            // 根据 displayId 获取 ActivityDisplay 对象
            final ActivityDisplay display = 
                getActivityDisplayOrCreate(displayId);
            if (display != null) {
                // 根据 ActivityDisplay 创建 ActivityStack
                stack = display.getOrCreateStack(r, options, 
                candidateTask, activityType, onTop);
                if (stack != null) {
                    return stack;
                }
            }
        }
        ......
}

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

frameworks/base/services/core/java/com/android/server/wm/ActivityDisplay.java

<T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r,
     @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask,
     int activityType, boolean onTop) {
        // First preference is the windowing mode in the 
        // activity options if set.
        int windowingMode = (options != null)
                ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
        
        windowingMode = validateWindowingMode(windowingMode, r, 
                candidateTask, activityType);
        return getOrCreateStack(windowingMode, activityType, onTop);
    }
    
<T extends ActivityStack> T getOrCreateStack(int windowingMode, 
        int activityType, boolean onTop) {
        if (!alwaysCreateStack(windowingMode, activityType)) {
            T stack = getStack(windowingMode, activityType);
            if (stack != null) {
                return stack;
            }
        }
        return createStack(windowingMode, activityType, onTop);
    }

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

<T extends ActivityStack> T createStack(int windowingMode, int activityType,
        boolean onTop) {
        ......
        final int stackId = getNextStackId();
        return createStackUnchecked(windowingMode, activityType, 
                stackId, onTop);
    }

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

<T extends ActivityStack> T createStackUnchecked(int windowingMode,
    int activityType, int stackId, boolean onTop) {
        if (windowingMode == WINDOWING_MODE_PINNED && activityType !=
             ACTIVITY_TYPE_STANDARD) {
    throw new IllegalArgumentException("Stack with windowing mode  "
                    + "cannot with non standard activity type.");
        }
        return (T) new ActivityStack(this, stackId,
           mRootActivityContainer.mStackSupervisor, windowingMode,
           activityType, onTop);
    }

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

5.2.2 TaskRecord创建

frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java

TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
     IVoiceInteractionSession voiceSession, ......) {
        return createTaskRecord(taskId, info, intent, voiceSession,
           voiceInteractor, toTop, null /*activity*/, null /*source*/, null);
}

TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
            IVoiceInteractionSession voiceSession, ......) {
        // 创建 TaskRecord
        final TaskRecord task = TaskRecord.create(
                mService, taskId, info, intent, voiceSession, voiceInteractor);
        // add the task to stack first, mTaskPositioner might need 
        // the stack association
        // 新建的 TaskRecord 插入到了 ActivityStack 中 mTaskHistory 中,
        // 将 TaskRecord 和 ActivityStack 关联在了一起。
        addTask(task, toTop, "createTaskRecord");
        final int displayId = mDisplayId != 
            INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
        ......
        task.createTask(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
        return task;
    }

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

5.2.3 ActivityRecord 与 TaskRecord 关联

private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
        if (mStartActivity.getTaskRecord() == null || 
              mStartActivity.getTaskRecord() == parent) {
        // 将当前 Activity 插入到 TaskRecord 中的 mActivities 的顶部,
        // 建立 ActivityRecord 与 TaskRecord 的联系
            parent.addActivityToTop(mStartActivity);
        } else {
            mStartActivity.reparent(parent, 
                  parent.mActivities.size() /* top */, reason);
        }
} 

最后调用 moveToFront,将 stack 移到栈的顶部。

六 总结

至此我们已经介绍了 Acitivity 启动所需要的 ActivityRecord,TaskRecord,ActivityStack 等数据结构的创建方式,并比照我们最开始讲的 Activity 的管理方式,对它们相互之间的关联过程,通过代码表述了出来。

在 Activity 的运行过程中,可能的情况非常之多,但我们只要牢记住,这几个结构体之间的关系就能抓住重点,Activity 的管理就是对这几个关键结构体,根据不同的情况进行调整,这样分析代码的时候思路就会清晰很多。

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值