ActivityManagerService基本概念

内容出自Android内核剖析书

AmS 所 供的主要功能:

  1. 统一调度各应用程序的 Activity。应用程序要运行 Activity,会首先 给 AmS,然后由 AmS决定该 Activity 是否可以启动,如果可以,AmS 再通知应用程序运行指定的 Activity。换 话说, 运行 Activity 是各应用进程的“内 ”,AmS 并不 ,但是 AmS 必须知道各应用进程都运行 了哪些 Activity。
  2. 内存管理。Android 方声称,Activity 出后,其所在的进程并不会被立即 ,从而下 在 启动该 Activity 时能 启动 度。这些 Activity 只有当系统内存 张时, 会被自动 , 应用程序不用关 这个问题。而这些正是在 AmS 中完成的。
  3. 进程管理。AmS 向外 供了查 系统正在运行的进程信息的 API。这些都比较简单。 下面就根据这些功能点,来分析 AmS 的代码。

Activity调度机制

在 Android 中,Activity 调度的基本思 是这样的:各应用进程要启动新的 Activity 或者停止当前 的 Activity,都要首先 给 AmS,而不能“ 自处理”。AmS 在内部为所有应用进程都做了 ,当AmS 接到启动或停止的 时,首先更新内部 ,然后再通知相应客户进程运行或者停止指定的 Activity。由于 AmS内部有所有Activity的 ,也就理所当然地能 调度这些Activity,并根据Activity 和系统内存的 态自动 后 的 Activity。

具体来讲,启动一个 Activity 有以下几种方式。

  1. 在应用程序中调用 startActivity()启动指定的 Activity。
  2. 在 Home 程序中单 一个应用图标,启动新的 Activity。
  3. 按“Back”键,结 当前 Activity,自动启动上一个 Activity。
  4. 按“Home”键,显示出当前任务列表,从中 一个启动。

这四种启动方式的主体处理流程都会按照第一种启动方式运行,后面三种方式只是在前端消息处理上各有不同 。

AmS的几个重要概念

AmS 中定义了几个重要的数据类,分别用来保存进程(Process)、活动(Activity)和任务(Task)。

ProcessRecord

该类framework/base/services/java/com/android/server/am/ 下,该 最后的 am 代表 Activity Manager,和 AmS 有关的重要类都在该目 下。

一个 APK 文件运行时会对应一个进程,当然,多个 APK 文件也可以运行在同一个进程中。 ProcessRecord 正是 一个进程中的相关信息,该类中内部变量可分为三个部分, 先不用 具 体某个变量如何被使用,而只需要先了解它们的作用.

HistoryRecord

AmS 中使用 HistoryRecord 数据类来保存每个 Activity 的信息,有些读者可能 ,Activity 本身也 是一个类 ,为什么还要用 HistoryRecord 来保存 Activity 的信息,而不直接使用 Activity 呢?因为, Activity 是具体的功能类,这就好比每一个读者都是一个 Activity,而“ 校”要为每一个读者建立一 个 案,这些 案中并不包含每个读者具体的 习能力,而只是 生的 信息、 名、出生 、 关系等。HistoryRecord 正是 AmS 为每一个 Activity 建立的 案,该数据类中的变量主要包含两部分

需要注意,HistoryRecord 类也是一个 Binder,它基于 IApplicationToken.Stub 类,因此,可以被 IPC 调用,一般是在 WmS 中进行该对象的 IPC 调用。

TaskRecord

AmS 中使用任务的 确保 Activity 启动和 出的顺序。比如以下启动流程,A、B、C 分别代表 三个应用程序,数字 1、2、3 分别代表该应用中的 Activity。

A1 A2 A3 B1 B2 C1 C2,此时应该处于 C2,如果 AmS 中没有任务的 ,此时 要从 C2 启动 B1,那么会存在以下两个问题:

  1. 虽然程序上是要启动 B1,但是用户可能期望启动 B2,因为 B1 和 B2 是两个关联的 Activity,并 且 B2 已经运行于 B1 之后。如何 供给程序员一种 , 然指定启动 B1,但如果 B2 已经运 行,那么就启动 B2。

    1. 假设已经成功从 C2 转到 B2,此时如果用户按“Back”键,是应该回到 B1 呢,还是应该回到 C2?

任务 的引入正是为了解决以上两个问题,HistoryRecord 中包含一个 int task 变量,保存该 Activity 所属哪个任务,程序员可以使用 Intent.FLAG_NEW_TASK 标识 AmS 为启动的 Activity 重 新创建一个 Task。

有了 Task 的 后,以上情况将会是这样的:

然程序明确指定从 C2 启动到 B1,程序员可以在 intent 的 FLAG 中添加 NEW_TASK 标识,从而 使得 AmS 会判断 B1 是否已经在 mHistory 中。如果在,则 到 B1 所在的 Task,并从该 Task 中的最上 面的 Activity 处运行,此处也就是 B2。当然,如果程序的确要启动 B1,那么就不要使用 NEW_TASk 标识,使用的话,mHistory 中会有两个 B1 , 属于不同的 Task。

需要注意的是,TaskRecord 中并没有该任务中所包含的 Activity 列表,比如 ArrayList 或者 HistoryRecord[]之类的变量,这意 着不能直接通过任务 id 到其所包含的 Activity。要 到这个 目的,可以 AmS 中 mHistory 中的全部 HistroyRecord,然后根据每一个 HistoryRecord 中的 TaskRecord task 变量确定是否属于指定的任务。

AmS 中的一些重要调度相关的变量

要了解 AmS 调度、管理系统中的 Activity 的 节,必须了解 AmS 中定义的重要内部变量。要一下 了解这些变量的使用时机并 易事,因此,本节仅简要说明一些变量的作用,至于具体使用的时机,要 结 调度的具体过程了解。

系统常量

  1. static final int MAX_ACTIVITIES = 20;

    系统只能有一个 Activity 处于执行 态,对于 执行 态的 Activity,AmS 会在内部暂时缓存起来, 而不是立即 ,但如果后 的 Activity 数目 过该常量,则会 制 一些 先 较 的 Activity, 所谓的“ 先 ”的规则见第 10.2 节。

  2. static final int MAX_RECENT_TASKS = 20;

    AmS 会 最近启动的 Activity,但只 20 个, 过该常量后,AmS 会 最 的 Activity。

  3. static final int PAUSE_TIMEOUT = 500;

    当 AmS 通知应用进程暂停指定的 Activity 时,AmS 的 是有 的,因为只有 500 ,如果应 用进程在该常量时间内还没有暂停,AmS 会 制暂停关 该 Activity。这就是为什么在应用程序设计时, 不能在 onPause()中做过多事情的原因。

  4. static final int LAUNCH_TIMEOUT = 10*1000;

    当 AmS 通知应用进程启动(Launch)某个 Activity 时,如果 过 10s,AmS 就会放 。

  5. static final int PROC_START_TIMEOUT = 10*1000;

    当 AmS 启动某个客户进程后,客户进程必须在 10 之内 AmS 自己已经启动,否则 AmS 会 认为指定的客户进程不存在。

    等待序列

由于 AmS 用 Service 机制运作,所有的客户进程要做什么事情,都要先请求 AmS,因此,AmS 内部必须有一些消息序列保存这些请求,并按顺序依 进行相应的操作。

  1. final ArrayList mHistory = new ArrayList();

    这是最最重要的内部变量,该变量保存了所有正在运行的 Activity,所谓正在运行是指该 HistoryRecord 的 finishing 态为 true。比如当前和用户 的 Activity 属于正在运行,从 A1 启动到 A2, 管 A1 看不见了,但是依然是正在运行,从 A2 按“Home”键回到 面,A2 也是正在运行,但如果 从 A2 按“Back”键回到 A1,A2 就不是正在运行 态了,它会从 mHistory 中 除 。

  2. private final ArrayList mLRUActivities = new ArrayList();

    LRU 代表 Latest Recent Used,即最近所用的 Activity 列表,它不像 mHistory 仅保存正在运行的 Activity,mLRUActivities 会保存所有过去启动过的 Activity。

  3. final ArrayListmPendingActivityLaunches = new ArrayList();

    当 AmS 内部还没有 好时,如果客户进程请求启动某个 Activity,那么会被暂时保存到该变量 中,这也就是 Pending 的含义。这种情况一般发生在系统启动时,系统进程会查 系统中所有属性为 Persisitant 的客户进程,此时由于 AmS 也正在启动,因此,会暂时保存这些请求。

  4. final ArrayList mStoppingActivities = new ArrayList();

    在 AmS 的设计中,有这样一个理 : 先启动,其 再停止。即当用户请求启动 A2 时,如果 A1 正在运行,AmS 首先会暂停 A1,然后启动 A2,当 A2 启动后再停止 A1。在这个过程中,A1 会被 时 保存到 mStoppingActivities 中,知道 A2 启动后并处于 时,再回过头来停止 mStoppingActivities 中 保存的 HistoryRecord 列表。

  5. final ArrayList mFinishingActivities = new ArrayList();

    和 mStoppingActivities 有点类似,当 AmS 认为某个 Activity 已经处于 finish 态时,不会立即 该 Activity,而是会保存到该变量中,直到 过系统设定的 线后, 去回收该变量中的 Activity。

当前不同状态的HistroryRecord

  1. HistoryRecord mPausingActivity = null;

    正在暂停的 Activity,该变量只有在暂停某个 Activity 时 有值,代表正在暂停的 Activity。

  2. HistoryRecord mResumedActivity = null;

    当前正在运行的 Activity,这里的正在运行并不见得一定是正在与用户 。比如当用户请求执行 A2 时,当前正在运行 A1,此时 AmS 会首先暂停 A1,而在暂停的过程中,AmS 会通知 WmS 暂停获 取用户消息,而此时 mResumedActivity 依然是 A1。

  3. HistoryRecord mFocusedActivity = null;

    这里的Focus并 是正在和用户 ,而是AmS通知WmS应该和用户 的Activity,而在 WmS 正处理这个消息之前,用户还是不能和Activity 。

  4. HistoryRecord mLastPausedActivity = null; 上一 暂停的 Activity。
时间: 2024-12-28 16:30:17

ActivityManagerService基本概念的相关文章

android内核剖析学习笔记:AMS(ActivityManagerService)内部原理和工作机制

一.ActivityManagerService提供的主要功能: (1)统一调度各应用程序的Activity (2)内存管理 (3)进程管理 二.启动一个Activity的方式有以下几种: (1)在应用程序中调用startActivity启动指定的Activity (2)在Home程序中单击一个应用图标,启动新的Activity (3)按"Back"键,结束当前Activity,返回到上一个Activity (4)长按"Home"键,显示出当前正在运行的程序列表,从

[深入理解Android卷二 全文-第六章]深入理解ActivityManagerService

由于<深入理解Android 卷一>和<深入理解Android卷二>不再出版,而知识的传播不应该因为纸质媒介的问题而中断,所以我将在CSDN博客中全文转发这两本书的全部内容 第6章 深入理解ActivityManagerService 本章主要内容: ·  详细分析ActivityManagerService 本章所涉及的源代码文件名及位置: ·  SystemServer.java frameworks/base/services/java/com/android/server/

WPF 依赖属性概念

理解依赖属性 在 WPF 中变成相比较于 传统 Windows Forms 变成发生了较大的改变. 属性现在以一组服务的形式提供给开发人员. 这组服务就叫做属性系统. 由 WPF 属性系统所支持的属性成为依赖属性. 依赖属性的概念 WPF 在依赖属性中提供了标准属性无法提供的功能, 特性如下: 决定属性值: 依赖属性的属性值可以在运行时有其他元素或者是其他信息所决定, 决定的过程具有一个优先次序. 自动验证或变更通知: 依赖属性哟一个自定的回调方法, 当属性值变更时被执行, 这个回调能验证新的值

Docker的概念及剖析原理和特点

一.docker的简介: 应用容器是个啥样子呢,一个做好的应用容器长的就像一个装好了一组特定应用的虚拟机一样,比如我现在想用mysql数据库,我直接找个装好了的MySQL的容器就可以了,想用的时候一运行容器,MySQL服务就起来了,就可以使用MySQL了 为什么不能直接安装一个MySQL?或者是SqlServer呢也可以啊? 答:因为有的时候根据每个人的电脑的不同,在物理机安装的时候会出现各种各样的错误,突然你的机器中病毒了或者是挂了,你所有的服务都需要重新安装. 注意:    但是有了dock

老男孩教育每日一题-2017年5月11-基础知识点: linux系统中监听端口概念是什么?

1.题目 老男孩教育每日一题-2017年5月11-基础知识点:linux系统中监听端口概念是什么? 2.参考答案 监听端口的概念涉及到网络概念与TCP状态集转化概念,可能比较复杂不便理解,可以按照下图简单进行理解? 将整个服务器操作系统比喻作为一个别墅 服务器上的每一个网卡比作是别墅中每间房间 服务器网卡上配置的IP地址比喻作为房间中每个人 而房间里面人的耳朵就好比是监听的端口 当默认采用监听0.0.0.0地址时,表示房间中的每个人都竖起耳朵等待别墅外面的人呼唤当别墅外面的用户向房间1的人呼喊时

Tensorflow一些常用基本概念与函数(四)

摘要:本系列主要对tf的一些常用概念与方法进行描述.本文主要针对tensorflow的模型训练Training与测试Testing等相关函数进行讲解.为'Tensorflow一些常用基本概念与函数'系列之四. 1.序言 本文所讲的内容主要为以下列表中相关函数.函数training()通过梯度下降法为最小化损失函数增加了相关的优化操作,在训练过程中,先实例化一个优化函数,比如 tf.train.GradientDescentOptimizer,并基于一定的学习率进行梯度优化训练: optimize

Tensorflow一些常用基本概念与函数(三)

摘要:本系列主要对tf的一些常用概念与方法进行描述.本文主要针对tensorflow的数据IO.图的运行等相关函数进行讲解.为'Tensorflow一些常用基本概念与函数'系列之三. 1.序言 本文所讲的内容主要为以下相关函数: 操作组 操作 Data IO (Python functions) TFRecordWrite,rtf_record_iterator Running Graphs Session management,Error classes 2.tf函数 2.1 数据IO {Da

数据结构基础概念

1.数据的特点:可以输入到计算机,可以被计算机程序处理 2.数据是一个抽象的概念,将其进行分类后得到程序设计语言中的类型.如:int float char等等 3.数据元素-组成数据的基本单位,数据项:一个数据元素由若干数据项组成 4.数据对象 -性质相同的数据元素的集合 5.数据元素之间不是独立的,存在特定的关系,这些关系即结构 6.数据结构指数据对象中数据元素之间的关系,编写一个"好"的程序之前,必须分析待处理问题中各个对象的特性,以及对象之间的关系 7.逻辑结构 集合结构--数据

Data guard概念篇一(转载)

本文转载至以下链接,感谢作者分享! http://tech.it168.com/db/2008-02-14/200802141545840_1.shtml 一.Data Guard配置(Data Guard Configurations) Data Guard是一个集合,由一个primary数据库(生产数据库)及一个或多个standby数据库(最多9个)组成.组成Data Guard的数据库通过Oracle Net连接,并且有可能分布于不同地域.只要各库之间可以相互通信,它们的物理位置并没有什么