AMS
第一章:AMS 的架构与组件
1.1 AMS 整体架构
在 Android 系统的庞大体系中,AMS(Activity Manager Service)就如同一个中枢神经系统,是整个系统的核心服务之一,对应用的性能和用户体验有着直接且关键的影响 。它的整体架构由 Client 端和 Service 端两大部分组成,这两端相互协作,如同精密仪器中的各个部件,共同保证了系统的高效运转。
Client 端主要负责实现各种组件,像 Activity、Service 这些构成 Android 应用的基础元素都在这一端实现。Client 端通过特定的系统接口与 AMS 进行通信,就好比人与人之间通过语言来交流想法一样。开发者可以通过 Android Framework 提供的 API 来与 AMS 交互,这些 API 就像是搭建起的桥梁,让应用能够顺利地在 Android 系统上运行。例如,当我们在应用中点击一个按钮启动一个新的 Activity 时,就是通过 Client 端利用 API 向 AMS 发送请求来实现的。
Service 端则是 AMS 的具体实现部分,它运行在重要的 SystemServer 进程中。这一端不仅要响应来自 Client 端的各种请求,更重要的是要管理各个应用进程的生命周期。可以把 Service 端想象成一个大管家,要管理家里的各种事务。为了高效地完成任务,它需要具备出色的任务调度能力和资源管理能力,保证系统资源能合理分配,应用能稳定运行。Service 端与客户端之间采用 Binder IPC 服务进行交互,这种机制就像一条高速公路,保证了通信的高效和安全。
Binder IPC 服务在 AMS 架构中占据着举足轻重的地位。它不仅是 Client 端和 Service 端之间通信的桥梁,更是保证系统稳定性和安全性的关键。通过 Binder IPC,AMS 能够快速处理来自各个应用的请求,并且确保这些请求在安全的环境中执行。这种设计既提升了系统的整体性能,也为开发者提供了一个可靠、易用的平台来构建应用。
AMS 的整体架构充分体现了 Android 系统对于高效、安全和稳定运行的追求。Client 端和 Service 端的协同工作,以及 Binder IPC 服务的高效通信,共同构成了这个强大而复杂的系统服务。对于开发者和用户来说,理解 AMS 的架构和工作原理是深入了解 Android 系统运行机制的重要一步。
1.2 核心组件与功能
AMS 内部包含多个关键组件,这些组件相互配合,共同实现了 AMS 强大的功能。
ActivityRecord:它在 AMS 中就像是一个记录员,负责保存每个 Activity 的详细信息,包括 Activity 当前的状态,是正在运行、暂停还是停止,以及它所属的任务栈信息等。每当有新的 Activity 被创建,或者已有 Activity 的状态发生变化时,对应的 ActivityRecord 都会及时更新。这样,AMS 就能通过查询 ActivityRecord 来随时掌握系统中所有 Activity 的实时状态,进而做出合理的调度决策。比如,当用户启动一个新的 Activity 时,AMS 会检查该 Activity 是否已经在任务栈中存在,如果存在就把它移到栈顶,让用户能够快速访问;如果不存在,就创建一个新的 ActivityRecord 并将其压入栈中。
ProcessRecord:这是 AMS 进行进程管理的基础组件,可以看作是进程的档案管理员。它记录了每个进程的详细信息,包括进程的创建时间、优先级、资源使用情况,以及绑定的服务等。AMS 通过 ProcessRecord 来跟踪和管理系统中的所有进程,确保它们按照既定的规则运行。在系统资源紧张的时候,AMS 会根据 ProcessRecord 中的信息来判断哪个进程应该被优先终止,以释放资源,保障系统的正常运行。比如,后台一些长时间没有使用且占用资源较多的进程可能就会被优先终止。
TaskRecord:它主要用于管理 Activity 的启动和退出顺序,以及任务栈的状态。在 Android 系统中,用户可以同时运行多个任务,每个任务由一个或多个 Activity 组成。TaskRecord 就像是一个任务的组织者,记录着这些任务的详细信息,包括任务的创建时间、包含的 Activity 列表以及任务的状态等。AMS 通过 TaskRecord 来确保 Activity 能够按照既定的规则进行切换和调度,为用户提供流畅、连贯的使用体验。例如,当用户在多个应用之间切换时,TaskRecord 能保证用户回到某个应用时,该应用的界面状态和用户离开时一致。
BroadcastQueue:它负责广播的调度和分发,是 Android 系统中广播通信机制的重要管理者。在 Android 系统里,广播是一种重要的通信方式,允许应用程序之间发送和接收消息。BroadcastQueue 就像是一个快递分发中心,管理着这些广播消息,确保广播能够准确地发送给目标接收器。当系统发生一些事件,比如电池电量低时,AMS 会通过 BroadcastQueue 发送一个相应的广播消息,所有注册了该广播接收器的应用程序都会收到这个消息,并做出相应的响应,比如提示用户电量不足。
这些核心组件共同协作,通过精确地记录和跟踪系统中的 Activity、进程、任务和广播等信息,确保 Android 系统能够高效地管理应用程序的生命周期、进程和资源,为用户提供优质的使用体验。它们的设计和实现充分体现了 Android 系统的灵活性和可扩展性,让开发者能够轻松构建出功能丰富、性能卓越的应用程序。
1.3 组件间的交互与通信
在 Android 系统中,AMS 内部组件之间的交互与通信是保证系统顺畅运行的关键环节,而这种交互主要通过 Binder IPC(Inter - Process Communication)机制来实现。Binder 机制就像一个高效的信使,允许不同进程间的对象进行通信,它通过 AIDL(Android Interface Definition Language)接口,让 Client 端能够与 AMS 进行通信,从而请求执行相应的操作。
当 Client 端发起一个请求,比如启动一个 Activity 时,这个请求就会通过 Binder IPC 被发送到 AMS。AMS 收到请求后,会进行一系列复杂的处理流程。首先,它会进行严格的权限检查和安全性验证,就像门卫检查访客的身份和权限一样,确保请求的来源是合法的,请求的操作也是被允许的。这一步至关重要,是保障系统安全性和稳定性的重要防线。
一旦请求通过了权限和安全性验证,AMS 就会进一步处理。如果是启动 Activity 的请求,AMS 会调用内部的 ActivityRecord 组件。ActivityRecord 保存了 Activity 的各种信息,通过它,AMS 能够准确地追踪和管理每个 Activity 的生命周期。同时,AMS 还会利用 TaskRecord 组件来管理 Activity 的启动和退出顺序,TaskRecord 负责维护任务栈的状态,保证 Activity 能够按照规则进行切换和调度,确保用户体验的连贯性和系统的稳定性。
在处理完 Client 端的请求后,AMS 还需要通过 BroadcastQueue 组件将相关的广播发送给目标接收器。比如,在 Activity 启动完成后,AMS 会发送一个广播通知系统和其他应用。BroadcastQueue 负责广播的调度和分发,保证广播能够准确地传递给目标接收器。
AMS 内部组件之间的交互与通信是 Android 系统运行的基础。通过 Binder IPC 机制,Client 端能够与 AMS 进行高效、安全的通信,从而实现对应用程序生命周期、任务栈、进程、广播、服务等的全面管理。这种精细化的管理不仅提升了系统的性能,也确保了用户体验的顺畅和稳定。
随着 Android 系统的不断发展和更新,AMS 的架构设计和组件交互方式也在持续优化和改进,以适应新的应用场景和用户需求。所以,深入理解 AMS 的内部机制和组件交互方式,对于开发高效、稳定、安全的 Android 应用具有重要意义。在实际应用中,我们需要密切关注 AMS 的性能指标和运行状态,及时发现并解决问题,保障系统的顺畅运行和用户的满意度。通过深入研究和理解这一机制,我们能更好地掌握 Android 系统的运行原理,开发出更优秀的应用程序,同时也需要不断学习和探索新的方法来优化和提升 AMS 的性能和稳定性。
第二章:AMS 的工作原理与机制
2.1 工作原理概述
AMS 作为 Android 系统的核心服务,其工作原理的核心在于对系统资源进行精细化的管理和调度,从而确保应用程序能够与用户进行顺畅的交互。它就像一个智能的交通管理员,全面控制着应用程序的生命周期、任务栈、进程状态,同时还负责广播的发送与接收以及服务的管理。这个机制非常复杂,因为它需要实时响应各种系统事件和用户请求,并且要保证系统资源的合理分配,维持应用程序的稳定运行。
管理应用程序的生命周期是 AMS 的主要功能之一。在 Android 系统中,应用程序的生命周期完全由 AMS 严格把控。当一个新的应用程序启动时,AMS 就像一个贴心的助手,会为其创建一个新的进程,并分配相应的系统资源。随着用户在不同应用程序之间切换,AMS 会根据实际需要调整各个应用程序的状态,比如将其设置为运行、暂停或停止,目的是确保当前活跃的应用程序能够获得足够的资源,快速响应用户的操作。例如,当用户从一个游戏应用切换到聊天应用时,AMS 会暂停游戏应用,把更多的资源分配给聊天应用,保证聊天的流畅性。
除了生命周期管理,AMS 还承担着维护任务栈(TaskRecord)的重要职责。任务栈是一个记录用户与应用互动历史的数据结构,它决定了用户在多任务环境下切换应用时的行为。AMS 通过 TaskRecord 精确地追踪每个 Activity 的启动和退出顺序,以及它们在任务栈中的位置。当用户按下 “返回” 键时,AMS 会参考任务栈来决定应该关闭哪个 Activity,这样就能保持用户体验的连贯性。比如,用户依次打开了 A、B、C 三个 Activity,当按下返回键时,AMS 会根据任务栈的记录,先关闭 C,再关闭 B,最后回到 A。
在进程管理方面,AMS 通过 ProcessRecord 组件来监控和管理每个应用程序进程的状态。这包括进程的创建、销毁以及资源使用情况的追踪。AMS 会根据进程的优先级、当前系统资源状况以及用户的行为来动态地调整进程的状态,比如将其置于前台运行或后台挂起,以此来优化系统性能和响应速度。例如,当系统资源紧张时,AMS 会优先将后台一些不重要的进程挂起,释放资源给前台正在运行的重要进程。
广播机制是 Android 系统中一种重要的通信手段,AMS 中的 BroadcastQueue 组件负责广播的调度与分发。无论是系统广播还是应用内广播,都需要通过 AMS 来进行传递。AMS 会确保广播按照设定的权限和优先级被正确地发送给目标接收器,从而实现系统级和应用级事件的有效通知与响应。比如,当系统连接到新的 Wi-Fi 时,会发送一个广播通知所有注册了该广播接收器的应用,应用可以根据这个通知进行相应的操作,如自动更新网络数据。
AMS 的工作原理并不是孤立存在的,而是与 Android 系统的其他组件和服务紧密集成。例如,当系统资源紧张时,AMS 可能需要与内存管理服务协同工作,共同决定哪些进程应该被优先保留,哪些进程需要被终止以释放资源。这种跨组件的协同工作是确保 Android 系统稳定、高效运行的关键。
总的来说,AMS 的工作原理可以概括为:通过对应用程序生命周期、任务栈、进程状态以及广播机制的全面管理,实现系统资源的合理分配和应用程序的稳定运行。这一机制确保了用户在使用 Android 设备时能够获得流畅、稳定的体验,是 Android 系统不可或缺的重要组成部分。
2.2 任务调度与优先级管理
在 Android 系统中,AMS 的任务调度与优先级管理是保证系统高效、稳定运行的关键环节。每个进程在系统中都根据其类型、运行状态及资源使用情况被赋予了不同的优先级,就像学校里的学生有不同的学号一样。而 AMS 则依据这些优先级,结合任务的紧急程度,进行精细化的任务调度与资源分配。
进程的优先级并不是固定不变的,它会随着系统状态的变化而动态调整。比如,前台运行的进程通常具有较高的优先级,这是为了确保用户交互的流畅性,因为用户正在直接与这些进程进行交互,比如正在玩游戏或者正在看视频,这些进程需要及时响应用户的操作。而后台进程则可能根据其资源占用情况和系统需求,被赋予较低的优先级。例如,一些在后台自动更新数据的进程,如果系统资源紧张,它们的优先级就会降低,以便系统能够优先保障前台进程的资源需求。AMS 通过实时监控进程状态,并根据预定义的策略调整其优先级,从而实现资源的合理分配和高效利用。
在任务调度方面,AMS 遵循严格的优先级顺序。优先级较高的任务就像有特权的人一样,将优先获得系统资源,并被优先执行。这种调度策略确保了关键任务和紧急任务能够及时得到处理,从而提升了系统的响应速度和用户体验。比如,当用户正在进行视频通话时,视频通话相关的任务具有较高优先级,系统会优先分配资源给它,保证通话的质量和流畅性。同时,AMS 还具备灵活的任务排序功能,能够根据任务的紧急程度和用户需求,对任务队列进行动态调整。例如,当用户突然打开一个重要的文件时,打开文件的任务会被提升优先级,优先于其他一些后台任务执行。
AMS 在任务调度与优先级管理过程中,充分考虑了系统的稳定性和安全性。通过实施严格的权限检查和安全性验证,AMS 确保了只有经过授权的任务才能被执行,这就像一个严格的保安,只允许有通行证的人进入,从而有效防止了恶意软件和攻击行为对系统造成的损害。
为了提升任务调度与优先级管理的效率,AMS 还采用了多种优化技术。例如,通过利用高效的算法和数据结构,AMS 能够在短时间内完成大量的任务调度和优先级调整操作。就像一个熟练的收银员,能够快速准确地处理大量的交易。同时,AMS 还具备强大的自我修复和容错能力,能够在遇到异常情况时迅速恢复正常状态,确保系统的持续稳定运行。比如,当某个任务因为意外错误而无法正常执行时,AMS 能够及时发现并采取措施,如重新调度任务或者终止出现问题的进程,以保证系统整体不受太大影响。
2.3 消息传递与事件处理
AMS 高效的消息传递与事件处理机制是保障 Android 系统流畅运行的关键,它主要建立在 Handler 和 Looper 的基础之上,形成了一套完善且高效的消息处理体系。
在 AMS 的 Service 端,Looper 线程扮演着一个非常重要的角色,它就像一个不知疲倦的守卫,不断地监听和处理消息队列中的消息。这个线程会持续地轮询消息队列,一旦有新的消息到来,它就能迅速作出响应。当 Client 端通过 Binder IPC 机制向 AMS 发送请求时,这些请求首先会被封装成特定的消息格式,然后被放入到消息队列中等待后续的处理。
Looper 线程的工作方式就像是消息队列的 “守门人”。它会不断地从队列中取出消息,然后根据消息的类型和内容,调用相应的处理函数。这些处理函数就像是一个个专业的工人,被设计成能够根据具体的业务逻辑和策略,灵活调用 AMS 中的各个组件进行相应的处理。例如,如果消息是关于启动一个新的 Activity 的请求,处理函数便会调用 ActivityRecord 等组件来记录和管理这个 Activity 的生命周期和状态。
这种消息传递与事件处理机制不仅高效,而且具有很强的可扩展性和灵活性。由于处理函数是根据消息内容动态调用的,因此可以很容易地添加新的处理逻辑来应对未来可能出现的新类型消息。这就好比一个灵活的工厂,可以根据不同的订单生产不同的产品。这种设计使得 AMS 能够持续进化,以适应不断变化的 Android 生态系统和用户需求。
同时,这种机制还确保了系统的稳定性和安全性。所有的请求都必须通过消息队列和处理函数的层层筛选与处理,这有效地防止了恶意请求或无效请求对系统的干扰。就像一个严格的安检系统,能够把危险物品挡在门外。而且,由于消息队列的缓冲作用,即使在高峰时段,系统也能够保持流畅的运行状态,为用户提供最佳的使用体验。比如,在用户同时进行多个操作,产生大量请求时,消息队列可以暂时存储这些请求,然后按照顺序依次处理,避免了系统因为瞬间的高负荷而崩溃。
三、AMS 关键组件
3.1 ActivityManagerService
在 Android 系统这个复杂的生态系统中,ActivityManagerService(简称 AMS)扮演着极为重要的角色,是 Android 系统的核心服务之一。它主要负责管理应用程序的生命周期和任务栈,通过一系列的机制确保系统能够稳定运行,并且资源能够得到高效利用。
从 Java 的角度来看,ActivityManagerService 是一个实现了 IActivityManager 接口的 Binder 服务。这种设计有很大的优势,它允许 AMS 通过 Binder 机制与客户端应用程序进行跨进程通信。在 Android 系统中,不同的应用程序可能运行在不同的进程中,而 AMS 作为一个系统服务,也运行在自己的进程中。通过 Binder 机制,AMS 能够和各个应用程序进行交互,实现系统服务与应用程序之间的无缝衔接。
AMS 的核心职责涵盖多个方面。首先是管理应用程序的生命周期。它时刻监控和控制着应用程序的运行状态,包括启动、暂停、恢复和销毁等活动 。在 Activity 的生命周期管理上,它通过维护 Activity 的各种状态,确保用户界面的连贯性和响应性。当用户在不同应用程序之间切换时,AMS 能够及时地暂停当前 Activity 并恢复上一个 Activity,让用户获得流畅的操作体验。
其次是进程管理。AMS 通过维护一个进程列表,实时监控各个进程的状态,从而实现对系统资源的有效利用。它会根据预设的策略,在必要的时候终止那些非关键进程,以此来维持系统的整体稳定性。特别是在内存紧张的情况下,这种智能的进程管理机制就显得尤为重要,它能够优先保障关键进程的运行,确保系统的核心功能不受影响。
再者是任务栈管理。AMS 通过维护一系列的 Activity 栈,实现了应用程序之间的切换和导航。每个任务栈都代表着一个独立的应用程序执行流,AMS 通过管理这些栈来控制应用程序的行为和用户界面的呈现。这种基于栈的数据结构设计,不仅为用户提供了直观的导航体验,同时也实现了应用程序资源的有效回收。
在实现这些核心功能的过程中,AMS 依赖于几个关键的数据结构。ActivityRecord 用于描述单个 Activity 的详细信息,包括 Activity 的状态、所属的任务栈等。TaskRecord 表示一个完整的任务栈,它包含了多个 ActivityRecord,记录了任务栈中各个 Activity 的执行顺序。ActivityStack 则负责管理一组相关的 TaskRecord,它对任务栈进行统一的管理和调度。
这些数据结构相互配合,共同构成了 AMS 管理应用程序生命周期和任务栈的基础框架。通过它们,AMS 能够精确地控制每个 Activity 的状态变化,并且有效地组织和管理多个并发运行的应用程序。
3.2 ActivityTaskManagerService
ActivityTaskManagerService(ATMS)是 Android 10 引入的一个新组件,在 Android 系统中也扮演着重要的角色。它主要负责管理 activities 和与 activity 相关的容器,比如 task、stacks、display 等,这体现了 Android 系统在任务管理和用户界面呈现方面不断优化的努力。
从 Java 的角度来看,ATMS 是一个实现了 IActivityTaskManager 接口的 Binder 服务。和 AMS 类似,这种设计允许 ATMS 通过 Binder 机制与客户端应用程序进行跨进程通信,实现系统服务与应用程序之间的无缝对接。
ATMS 的核心职责包括管理任务栈和 Activity 的切换与调度。它通过维护一系列的 ActivityStack,来实现应用程序之间的切换和导航。每个任务栈代表一个独立的应用程序执行流,ATMS 通过管理这些栈来控制应用程序的行为和用户界面的呈现。
ATMS 还负责处理 Activity 的启动、切换、恢复、暂停等逻辑。它通过 ActivityStackSupervisor 类来实现对任务栈的精细化管理。ActivityStackSupervisor 类负责调度任务栈内的 Activity 切换,维护任务栈的栈顶状态,并且处理各种复杂的生命周期事件。
下面是一段 ATMS 的关键代码示例:
public class ActivityTaskManagerService {
final ActivityStackSupervisor mStackSupervisor;
public ActivityTaskManagerService(Context context) {
mStackSupervisor = new ActivityStackSupervisor(this);
}
void startActivity() {
mStackSupervisor.startActivityLocked();
}
}
从这段代码中可以看出,ATMS 的核心职责是通过 ActivityStackSupervisor 类来实现的。这种设计方式实现了任务栈管理的解耦,提高了系统的可维护性和可扩展性。当需要对任务栈管理的逻辑进行修改或者扩展时,只需要在 ActivityStackSupervisor 类中进行相应的操作,而不会对 ATMS 的其他部分造成太大的影响。
ATMS 的工作流程一般是这样的:当系统接收到启动 Activity 的请求时,ATMS 会通过 ActivityStackSupervisor 找到合适的目标任务栈。然后,ATMS 会调用目标任务栈的相应方法来启动 Activity。在整个过程中,ATMS 还会负责处理各种复杂的生命周期事件,比如 Activity 的暂停、恢复等。通过这样的工作流程,ATMS 能够有效地管理任务栈和 Activity 的各种状态变化,为用户提供流畅的操作体验。
3.3 ActivityStackSupervisor
ActivityStackSupervisor 是 ActivityManagerService 的核心组件之一,在 Android 系统中起着关键的作用。它的主要职责是管理两个非常重要的 Activity 栈,即 mHomeStack 和 mFocusedStack。
mHomeStack 主要用于管理 Launcher 相关的任务。Launcher 是用户打开手机后看到的主屏幕界面,mHomeStack 负责管理与 Launcher 相关的各种 Activity,确保 Launcher 能够正常运行,并且用户能够方便地在主屏幕上启动其他应用程序。
mFocusedStack 则用于管理当前接收输入或启动下一个 Activity 的任务栈。当用户在某个应用程序中进行操作时,mFocusedStack 会管理这个应用程序相关的 Activity 栈,保证用户的操作能够得到及时响应。当用户启动一个新的 Activity 时,mFocusedStack 会根据相关规则来决定如何处理这个新的 Activity,比如是将它添加到当前任务栈中,还是创建一个新的任务栈。
ActivityStackSupervisor 通过精心设计的数据结构和算法,实现了对 Activity 的精细控制和高效调度。它能够根据不同的情况,合理地管理 Activity 在任务栈中的进出,确保 Android 系统在任务管理和用户界面呈现方面有卓越的表现。这种双栈结构的设计非常巧妙,它不仅简化了系统内部的逻辑处理,还为开发者提供了更加灵活的方式来管理和组织应用程序的执行流程。开发者可以根据自己的需求,更好地利用这两个栈来实现应用程序的各种功能,提高应用程序的用户体验。
3.4 ProcessList
在 Android 系统的进程管理中,ProcessList 是 ActivityManagerService(AMS)的一个关键组件,它扮演着至关重要的角色。ProcessList 主要负责维护系统中所有进程的信息,这些信息包括进程 ID、优先级和状态等关键数据。
通过维护这份详细的进程列表,ProcessList 为 AMS 提供了全面的系统视图。有了这个视图,AMS 能够高效地管理进程生命周期和系统资源。比如说,当系统需要分配内存资源时,AMS 可以根据 ProcessList 中记录的进程优先级和状态,来决定哪些进程可以获得更多的资源,哪些进程可能需要释放一些资源。
ProcessList 的核心功能体现在以下几个方面。首先是进程信息维护,它会不断地存储和更新所有活动进程的相关信息。随着系统中进程的创建、销毁以及状态的变化,ProcessList 会及时地更新这些信息,确保数据的准确性和实时性。
其次是进程优先级计算。ProcessList 会根据进程类型和状态动态地计算进程的优先级。不同类型的进程,比如前台进程、后台进程、服务进程等,它们的优先级是不同的。而且,进程的状态也会影响其优先级,比如一个正在运行重要任务的进程,它的优先级可能会比处于空闲状态的进程高。ProcessList 会综合考虑这些因素,为每个进程计算出一个合理的优先级。
再者是资源分配辅助。在内存不足的情况下,AMS 需要决定哪些进程可以被终止,以释放更多的内存资源。这时,ProcessList 就会协助 AMS 进行决策。它会根据进程的优先级和其他相关信息,为 AMS 提供参考,帮助 AMS 做出合理的选择。
通过这些功能,ProcessList 显著增强了 AMS 的进程管理能力和系统资源利用率。它为 Android 系统的稳定运行提供了坚实的支撑,确保系统在各种情况下都能够合理地管理进程,保障系统的性能和稳定性。
四、进程管理
4.1 进程优先级
在 Android 系统中,进程优先级管理是一项极为关键的资源分配策略,它对于优化系统性能和高效利用资源起着重要作用。Android 采用了多层次的进程优先级体系,这一体系不仅对进程的生存周期有着显著影响,还在系统内存紧张时决定了资源的分配方式 。
Android 系统中的进程优先级主要通过三个关键指标来衡量。
4.1.1 oom_adj
oom_adj(Out-Of-Memory Adjustment)主要用于低内存杀手(LMK,Low Memory Killer)机制,它决定了进程被终止的概率 。oom_adj 的值越低,表明进程越重要,在内存紧张时越不容易被杀死;反之,oom_adj 的值越高,进程越容易被终止。例如,前台正在运行的应用程序进程的 oom_adj 值通常较低,因为它们直接与用户交互,对用户体验影响较大,所以系统会尽量保护它们不被杀死;而一些在后台长时间闲置的进程,其 oom_adj 值可能较高,在内存不足时就可能会被优先终止。
4.1.2 procState
procState 反映了进程的当前状态,它会影响系统服务对进程的处理方式 。不同的 procState 值代表着进程处于不同的运行状态,比如前台运行、后台运行、空闲等。系统会根据 procState 的值来判断进程的重要性和资源需求情况,进而做出相应的决策。例如,处于前台运行状态的进程(其 procState 值表示为前台状态),系统会优先为其分配资源,保证其流畅运行;而对于处于空闲状态的进程(其 procState 值表示为空闲状态),系统可能会在资源紧张时减少对其资源分配,甚至考虑终止它。
4.1.3 schedGroup
schedGroup 确定了进程的 CPU 调度组,它会影响进程获得的 CPU 资源份额 。不同的 schedGroup 对应着不同的 CPU 调度策略。例如,对于一些对实时性要求较高的进程,如游戏应用进程,可能会被分配到较高优先级的 CPU 调度组(如 SCHED_GROUP_TOP_APP),这样它们就能在 CPU 资源竞争中获得更多的 CPU 时间片,以保证游戏的流畅运行;而对于一些后台服务进程,可能会被分配到默认的 CPU 调度组(如 SCHED_GROUP_DEFAULT),它们获得的 CPU 资源相对较少,但也能满足基本的运行需求。
这三个指标共同构成了一个复杂而精细的进程优先级系统,确保系统在资源分配和进程管理方面能够达到最佳效果。通过综合考虑 oom_adj、procState 和 schedGroup,系统能够更加准确地评估每个进程的重要性和资源需求,从而在资源有限的情况下,合理地分配资源,优先保障关键进程的运行,同时有效回收非关键进程的资源,维持系统的整体稳定性和响应性 。
进程优先级的具体分类如下:
优先级类别adj 范围procState 值schedGroup前台进程0 - 199PROCESS_STATE_FOREGROUNDSCHED_GROUP_TOP_APP可见进程200 - 499PROCESS_STATE_VISIBLESCHED_GROUP_DEFAULT服务进程500 - 599PROCESS_STATE_SERVICESCHED_GROUP_DEFAULT辅助进程600 - 699PROCESS_STATE_AUXILIARYSCHED_GROUP_DEFAULT空进程900 - 906PROCESS_STATE_EMPTYSCHED_GROUP_BACKGROUND缓存进程900 - 906PROCESS_STATE_CACHEDSCHED_GROUP_BACKGROUND
影响进程优先级的主要因素包括:
- 进程中运行的组件类型:如 Activity、Service。如果进程中运行着前台 Activity,那么这个进程的优先级会相对较高;而如果只是运行一些后台 Service,优先级则会低一些。
- 组件的当前状态:例如是前台状态还是后台状态。处于前台状态的组件所在的进程优先级更高,因为它们直接与用户交互,对用户体验影响更大。
- 进程的内存使用情况:内存使用较少的进程可能会在资源紧张时更受 “青睐”,因为终止它们对系统的影响相对较小。
- 系统的整体资源状况:当系统资源充足时,进程优先级的差异对资源分配的影响可能相对较小;但当系统资源紧张时,进程优先级就会成为决定资源分配和进程是否被终止的关键因素。
AMS 通过 computeOomAdjLocked 方法动态计算进程的优先级。这个方法会综合考虑上述因素,为每个进程计算出一个合理的 adj 值。例如,一个运行着前台 Activity 的进程,由于其组件类型和状态的原因,computeOomAdjLocked 方法会为它计算出一个较低的 adj 值,使它在内存紧张时更不容易被杀死;而一个只运行后台 Service 且内存使用较多的进程,可能会获得较高的 adj 值,在内存不足时就更容易被终止 。这种多层次的优先级系统使得 Android 系统能够在资源紧张的情况下,精准地保护关键进程,同时高效地回收非关键进程的资源,从而维持系统的整体稳定性和响应性,为用户提供流畅的使用体验 。
4.2 进程调度
在 Android 系统中,AMS 肩负着进程调度的核心任务。它主要通过 updateLruProcessLocked 和 updateOomAdjLocked 两个关键方法来实现进程优先级的动态调整 。
4.2.1 updateLruProcessLocked 方法
updateLruProcessLocked 方法会考虑进程的类型、状态和资源使用情况等因素。它会根据这些信息对进程进行排序,将那些长时间未使用或者资源占用较多且不重要的进程排在后面。例如,对于一些在后台长时间闲置且占用了一定内存资源的进程,updateLruProcessLocked 方法会将它们的位置调整到进程列表的靠后位置,以便在需要时可以优先对它们进行处理 。
4.2.2 updateOomAdjLocked 方法
updateOomAdjLocked 方法则是根据进程的各种属性,为每个进程计算出一个合理的 oom_adj 值,从而决定进程在低内存情况下的存活概率 。如前面所述,oom_adj 值越低,进程在内存紧张时越不容易被杀死。updateOomAdjLocked 方法会综合考虑进程中运行的组件类型、组件状态、进程的内存使用情况以及系统的整体资源状况等多方面因素来计算 oom_adj 值。例如,一个前台正在运行的应用程序进程,由于其重要性,updateOomAdjLocked 方法会为它计算出一个较低的 oom_adj 值,以确保它在内存紧张时能够得到优先保护;而对于一个后台的辅助进程,如果它占用了较多的内存且不是很活跃,updateOomAdjLocked 方法可能会为它计算出一个较高的 oom_adj 值,在内存不足时就可能会优先终止它 。
AMS 还利用 ProcessList 类来维护系统中所有进程的信息。ProcessList 类中存储了进程的 ID、优先级、状态等详细数据,为进程管理提供了全面的系统视图 。通过这个视图,AMS 可以清晰地了解每个进程的情况,从而更准确地进行进程调度。例如,当系统内存紧张时,AMS 可以根据 ProcessList 中记录的进程信息,结合 updateLruProcessLocked 和 updateOomAdjLocked 方法的计算结果,快速确定哪些进程可以被终止以释放内存资源,哪些进程需要保留以保证系统的正常运行 。
这种精细的进程调度机制确保了 Android 系统能够有效地平衡资源利用和用户体验。在内存紧张时,它能够优先保护关键进程,比如正在进行通话的电话应用进程、前台正在运行的重要应用程序进程等,保证这些进程的正常运行,避免对用户造成不良影响;同时,对于一些非关键进程,如后台长时间闲置的应用程序进程、占用大量内存但当前不是很重要的进程等,会根据情况进行合理的处理,释放它们占用的资源,以维持系统的整体性能 。这样,Android 系统在各种情况下都能保持较好的运行状态,为用户提供稳定、流畅的使用体验 。
4.3 OOM 管理
在 Android 系统的内存管理中,AMS 扮演着关键角色,主要通过 OOM Killer 机制和 IdleHandler 机制来实现有效的内存管理 。
4.3.1 OOM Killer 机制
OOM Killer(Out-Of-Memory Killer)机制是 AMS 在内存管理中的重要手段。当系统内存压力较大时,AMS 会根据进程的优先级和系统资源状况,动态调整进程的 oom_adj 值,从而决定在内存紧张时哪些进程应被终止 。
这个机制的核心在于 computeOomAdjLocked 方法,它综合考虑了多个因素来为每个进程计算 oom_adj 值。这些因素包括进程类型、状态和资源使用情况等。例如,对于前台进程,由于其直接与用户交互,对用户体验影响较大,computeOomAdjLocked 方法会为其计算出较低的 oom_adj 值,使它们在内存紧张时不容易被终止;而对于后台的缓存进程或空进程,它们的 oom_adj 值会相对较高,在内存不足时就更容易被终止 。通过这种方式,AMS 能够优先保护那些对用户体验至关重要的进程,同时释放那些非关键进程占用的内存资源,以缓解系统的内存压力 。
4.3.2 IdleHandler 机制
AMS 还利用 IdleHandler 机制来优化内存使用。当系统处于闲置状态时,也就是没有太多前台任务在执行,CPU 相对空闲的时候,IdleHandler 会被触发 。IdleHandler 会执行一系列的内存回收操作,比如清理一些缓存数据、释放不再使用的资源等。通过这种方式,有助于提高系统的
请继续
整体性能和资源利用率。例如,系统在一段时间内没有新的用户操作,进入闲置状态,IdleHandler 会检查系统中各个进程的缓存数据,对于一些长时间未使用的缓存数据进行清理,将这些缓存占用的内存释放出来,以便其他更需要内存的进程使用 。
这种多层次的内存管理策略确保了 Android 系统能够在资源受限的情况下维持良好的用户体验和系统稳定性。在内存紧张时,OOM Killer 机制能够精准地选择合适的进程进行终止,释放内存资源;而在系统闲置时,IdleHandler 机制又能及时清理不必要的资源,提高内存的利用率。这两种机制相互配合,使得 Android 系统在不同的内存状况下都能有效地管理内存,保障系统的正常运行,为用户提供流畅的使用环境 。同时,这种内存管理策略也体现了 Android 系统在资源管理方面的高效性和智能性,能够根据系统的实际情况动态地调整内存分配和进程管理策略,以适应各种复杂的应用场景 。
五、任务栈管理
5.1 Task 概念
在 Android 系统中,Task 是一个核心概念,它代表了一系列相关联的 Activity 组成的执行单元 。Task 在系统中起着非常重要的作用,它与 ActivityManagerService(AMS)密切相关,AMS 通过维护 Task 栈来管理应用程序的执行流程和用户界面的导航历史 。
Task 通过 TaskRecord 类进行管理,TaskRecord 类维护了一个 ActivityRecord 的链表。这个链表用于跟踪 Task 中的 Activity 执行顺序,每个 ActivityRecord 对应一个 Activity 实例 。当一个应用程序启动多个 Activity 时,这些 Activity 会按照一定的顺序被添加到 Task 中,形成一个 Activity 的执行链条 。例如,在一个电商应用中,用户从商品列表 Activity 进入商品详情 Activity,再进入订单确认 Activity,这些 Activity 就会依次被添加到同一个 Task 中,形成一个与该应用购物流程相关的执行单元 。
这种基于栈的结构为用户提供了直观的导航体验。用户可以通过返回键按照 Activity 入栈的相反顺序依次返回上一个 Activity,就像浏览网页时的后退操作一样 。同时,它也实现了应用程序资源的有效回收。当一个 Activity 不再被使用时,它可以从 Task 栈中移除,相关的资源也可以被回收 。例如,当用户从订单确认 Activity 返回商品详情 Activity 后,订单确认 Activity 就可以从 Task 栈中弹出,其占用的部分资源可以被系统回收利用,提高了系统资源的利用率 。
通过 Task 机制,Android 系统能够高效地管理多个并发运行的应用程序。每个应用程序都可以有自己的 Task,不同应用程序的 Task 之间相互独立,互不干扰 。这样,系统可以同时管理多个应用程序的执行流程,确保每个应用程序的状态和导航历史都能得到正确的维护 。无论是用户在多个应用程序之间频繁切换,还是在一个应用程序中进行复杂的界面跳转操作,Task 机制都能保证系统的稳定性和用户体验的连贯性 。
5.2 Activity 栈管理
在 Android 系统的任务管理中,Activity 栈管理是一个关键环节,是 ActivityManagerService(AMS)的核心功能之一。它通过精心设计的数据结构和算法,实现了对应用程序执行流程的精细控制 。
5.2.1 核心组件
Activity 栈管理的核心组件包括:
- ActivityStackSupervisor:负责管理 Activity 的生命周期和任务栈。它是 Activity 栈管理的核心协调者,掌控着 Activity 在栈中的各种操作,如入栈、出栈等 。
- TaskRecord:表示一个任务,包含多个 ActivityRecord。它记录了一个任务中所有 Activity 的相关信息,以及这些 Activity 之间的执行顺序关系 。
- ActivityRecord:描述单个 Activity 的详细信息。包括 Activity 的状态(如是否正在运行、暂停、停止等)、所属的 Task、启动模式等 。
5.2.2 入栈和出栈操作
Activity 的入栈和出栈操作主要通过 ActivityStackSupervisor 类实现。ActivityStackSupervisor 类维护了两个关键的 Activity 栈:
- mHomeStack:用于管理 Launcher 相关的任务。Launcher 是用户打开手机后看到的主屏幕界面,mHomeStack 负责管理与 Launcher 相关的 Activity,确保用户能够方便地从主屏幕启动其他应用程序 。
- mFocusedStack:用于管理当前接收输入或启动下一个 Activity 的任务栈。当用户在某个应用程序中进行操作时,mFocusedStack 会管理该应用程序相关的 Activity 栈,保证用户的操作能够得到及时响应 。
当一个新的 Activity 被启动时,ActivityStackSupervisor 会根据 Activity 的启动模式和相关标志位,决定将其添加到哪个任务栈中 。这个过程涉及到多个关键方法的调用,例如:
private int startActivityUnchecked(ActivityStarter starter)
这个方法会根据不同的启动模式和标志位,选择合适的 TaskRecord 来添加新的 ActivityRecord 。例如,对于 standard 模式,它会调用setTaskFromSourceRecord()方法来获取或创建一个新的 TaskRecord 。在这种模式下,每次启动 Activity 都会创建一个新的 Activity 实例,并将其添加到当前任务栈的栈顶 。
在 Activity 的出栈操作中,最常见的是通过用户按下返回键或调用 finish () 方法来实现 。这时,ActivityStackSupervisor 会执行以下步骤:
- 弹出当前任务栈顶部的 ActivityRecord:将当前位于任务栈栈顶的 Activity 从栈中移除 。
- 更新任务栈状态:调整任务栈中其他 Activity 的状态和顺序,确保任务栈的状态正确 。
- 调用被移除 Activity 的 onDestroy () 方法:通知被移除的 Activity 进行资源清理等操作 。
- 如果任务栈变为空,考虑销毁整个 TaskRecord:当任务栈中所有的 Activity 都被移除后,TaskRecord 可能会被销毁,释放相关资源 。
5.2.3 不同启动模式下的栈管理逻辑
不同启动模式下的栈管理逻辑有所不同:
启动模式栈管理逻辑standard默认行为,每次启动都会创建新的实例,并将其添加到当前任务栈的栈顶 。例如,在一个新闻阅读应用中,每次点击不同的新闻链接进入新的新闻详情页,都会创建一个新的新闻详情 Activity 实例并压入栈顶 。singleTop如果任务栈顶部已有该 Activity 实例,则直接使用,不会创建新的实例 。比如,在一个聊天应用中,如果当前聊天界面(Activity)已经在任务栈顶部,当再次收到该聊天对象的消息并点击进入聊天界面时,不会创建新的聊天 Activity 实例,而是直接复用栈顶的实例 。singleTask清除任务栈中该 Activity 以上的所有实例,保留底部实例 。例如,在一个文件管理应用中,假设某个文件详情 Activity 设置为 singleTask 模式,当从文件列表 Activity 进入文件详情 Activity 后,再进行一系列其他操作进入了其他 Activity,此时如果再次启动文件详情 Activity,任务栈中位于文件详情 Activity 之上的其他 Activity 都会被清除,只保留文件详情 Activity 在栈顶 。singleInstance在整个系统范围内保证唯一性,不受任务栈限制 。这种模式下,该 Activity 会单独位于一个新的任务栈中,并且这个任务栈只有这一个 Activity 。比如,系统的来电界面 Activity 通常采用 singleInstance 模式,这样无论在任何应用程序中,来电时都会在一个独立的任务栈中显示来电界面,确保其能够及时响应且不受到其他应用程序任务栈的干扰 。
这种灵活的栈管理模式使得 Android 系统能够有效处理各种复杂的用户交互场景。无论是简单的应用程序界面跳转,还是复杂的多任务处理和应用程序间的交互,都能通过合理的 Activity 栈管理来实现 。同时,它也保证了资源的有效利用,避免了不必要的 Activity 实例创建和资源浪费 。通过这种方式,Android 系统能够为用户提供连贯、流畅的操作体验,满足不同应用场景下的需求 。
5.3 多窗口支持
在 Android 系统中,多窗口支持是自 Android 7.0 版本起引入的一项重要特性,它为用户提供了更灵活的界面操作体验,允许用户在同一屏幕上同时查看和操作多个应用程序 。
多窗口模式的核心原理涉及以下关键概念和类:
- ActivityStack:用于管理一组相关的 Activity 。在多窗口模式下,ActivityStack 需要对不同窗口中的 Activity 进行合理的组织和管理,确保每个 Activity 都能在对应的窗口中正确显示和运行 。
- ConfigurationContainer:提供多窗口模式的判定方法 。它可以根据系统的配置和用户的操作,判断当前是否应该进入多窗口模式,以及如何配置多窗口模式下的相关参数 。
- ActivityTaskManagerService:负责设置任务的窗口模式和调整分屏布局 。当系统进入多窗口模式时,ActivityTaskManagerService 会对各个任务的窗口模式进行设置,例如将某个应用的窗口设置为分屏主栈或分屏副栈,并根据用户的操作调整分屏布局,确保各个应用窗口能够合理地占据屏幕空间 。
进入分屏模式的过程通常涉及以下步骤:
- 将当前应用所在的 ActivityStack 设置为分屏主栈:通过将当前应用所在的 ActivityStack 的 windowingMode 设置为 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,将其指定为分屏主栈 。在分屏主栈中的 Activity 将占据屏幕的主要部分,通常是较大的显示区域 。
- 调用 resizeDockedStack 方法调整分屏布局:resizeDockedStack 方法会根据系统的要求和用户的操作,调整分屏布局 。例如,当用户手动拖动分屏边界时,resizeDockedStack 方法会根据新的边界位置重新计算各个应用窗口的大小和位置,确保它们能够适应新的屏幕布局 。
这些机制共同实现了 Android 系统的多窗口功能 。通过合理地利用 ActivityStack、ConfigurationContainer 和 ActivityTaskManagerService 等组件,Android 系统能够有效地管理多窗口模式下的应用程序,为用户提供便捷的多任务处理能力 。用户可以在同一屏幕上同时运行多个应用程序,例如一边观看视频一边回复消息,大大提高了操作效率和使用体验 。同时,这种多窗口支持也为开发者带来了新的挑战和机遇,开发者需要确保自己的应用程序在多窗口模式下能够正常运行,并且能够充分利用多窗口模式的优势,为用户提供更好的功能和体验 。
六、AMS 启动流程
6.1 SystemServer 中初始化
在 Android 系统的启动过程中,SystemServer 扮演着至关重要的角色,它是系统的核心组件之一。SystemServer 负责初始化和管理各种系统服务,其中 ActivityManagerService(AMS)就是由 SystemServer 启动并初始化的关键服务之一 。
SystemServer 启动 AMS 的过程是一个精心设计的多步骤流程,涉及多个类和方法的协同工作。这个过程不仅启动了 AMS 服务,还完成了多项必要的初始化工作,为系统的正常运行奠定了坚实的基础 。
6.1.1 创建 ActivityManagerService 实例
SystemServer 通过 SystemServiceManager 启动 ActivityManagerService.Lifecycle 类,从而创建 AMS 实例 。SystemServiceManager 是 SystemServer 中用于管理系统服务的重要类,它负责协调系统服务的启动、停止和生命周期管理 。在启动 AMS 时,SystemServiceManager 会调用相关的方法来创建 ActivityManagerService.Lifecycle 类的实例,而这个实例实际上就是 AMS 的核心部分 。
6.1.2 设置系统服务管理器
创建 AMS 实例后,SystemServer 会将自身的 SystemServiceManager 实例传递给 AMS 。这样 AMS 就可以通过这个 SystemServiceManager 实例来使用系统服务管理的相关功能 。例如,AMS 在后续的运行过程中,如果需要启动其他系统服务或者查询系统服务的状态,就可以通过这个传递过来的 SystemServiceManager 实例来实现 。
6.1.3 初始化电源管理
AMS 需要与电源管理功能进行集成,以实现对应用程序和系统服务在电源管理方面的控制 。因此,SystemServer 会调用 AMS 的 initPowerManagement () 方法,为 AMS 初始化电源管理功能 。在这个方法中,会进行一系列与电源管理相关的初始化操作,比如注册电源状态监听、设置电源管理策略等 。通过初始化电源管理,AMS 可以根据系统的电源状态(如充电状态、电量低等)来调整应用程序和系统服务的运行状态,以达到优化电源使用和保证系统稳定性的目的 。
6.1.4 设置系统进程
SystemServer 会调用 AMS 的 setSystemProcess () 方法,将当前 SystemServer 进程设置为系统进程,并将其纳入 AMS 的进程管理体系 。这样,AMS 就可以对 SystemServer 进程进行监控和管理,包括进程优先级的调整、资源分配等 。将 SystemServer 进程设置为系统进程,使其具有较高的优先级和特殊的权限,能够保证系统核心服务的稳定运行 。
6.1.5 安装系统 ContentProviders
ContentProviders 是 Android 系统中用于数据共享和访问的重要组件,系统中存在一些系统级别的 ContentProviders,它们提供了诸如联系人数据、短信数据等重要数据的访问接口 。SystemServer 会调用 AMS 的 installSystemProviders () 方法,安装这些系统级别的 ContentProviders 。在安装过程中,AMS 会对这些 ContentProviders 进行注册和初始化,确保它们能够正常提供数据服务 。其他应用程序可以通过 ContentResolver 来访问这些系统级别的 ContentProviders,获取所需的数据 。
6.1.6 设置 WindowManager
WindowManager 是 Android 系统中负责管理窗口的重要服务,它与 AMS 密切协作,共同管理应用程序的界面显示和用户交互 。SystemServer 会调用 AMS 的 setWindowManager () 方法,为 AMS 配置 WindowManager 服务 。通过这个方法,AMS 可以与 WindowManager 建立联系,实现对应用程序窗口的创建、显示、隐藏等操作的协同管理 。例如,当 AMS 需要启动一个 Activity 时,它会与 WindowManager 协作,创建 Activity 对应的窗口,并将其显示在屏幕上 。
6.1.7 执行 systemReady () 方法
当 AMS 完成前面的各项初始化工作后,SystemServer 会执行 AMS 的 systemReady () 方法,完成最后的初始化工作 。在 systemReady () 方法中,AMS 会进行一些全局性的设置和准备工作,例如启动一些后台线程、初始化一些关键的数据结构等 。这些工作完成后,AMS 就可以正式开始履行其管理应用程序生命周期和系统资源的职责了 。
这个过程展示了 Android 系统在启动关键服务时的精心设计 。通过逐步初始化和配置,确保了 AMS 能够顺利接管系统资源管理和应用程序生命周期控制的任务 。特别是将 SystemServer 进程本身纳入 AMS 的管理范围,体现了 Android 系统在进程管理上的闭环设计理念,确保了核心系统进程的安全性和可控性 。通过这种细致入微的初始化流程,Android 系统为 AMS 的高效运作奠定了坚实的基础,也为后续的应用程序启动和系统资源管理做好了充分准备 。
6.2 Binder 服务注册
在 Android Framework 中,AMS 的 Binder 服务注册是系统初始化过程中的关键一步,它涉及到系统中不同组件之间的通信和协作 。这个过程主要涉及两个核心类:ServiceManager 和 ActivityManagerService 。
6.2.1 创建 ServiceManager 实例
SystemServer 启动时会首先创建 ServiceManager 实例 。ServiceManager 是 Android 系统中负责管理系统服务的注册和查找的核心类 。它维护了一个服务注册表,所有的系统服务都需要在这个注册表中进行注册,以便其他组件能够通过 ServiceManager 来查找和使用这些服务 。
6.2.2 注册 AMS 服务
创建 ServiceManager 实例后,就需要将 AMS 服务注册到 ServiceManager 中 。这是通过 ServiceManager 的 addService () 方法来实现的 。在注册过程中,会将 AMS 的相关信息(如服务名称、服务接口等)添加到 ServiceManager 的服务注册表中 。具体来说,会调用以下关键代码:
IServiceManager sm = IServiceManager.Stub.asInterface(ServiceManagerNative.getDefault());
sm.addService("activity", new ActivityManagerService.Lifecycle());
在这段代码中,首先通过IServiceManager.Stub.asInterface(ServiceManagerNative.getDefault())获取到 ServiceManager 的代理对象sm 。然后,调用sm.addService("activity", new ActivityManagerService.Lifecycle())方法,将 AMS 的服务名称设置为 “activity”,并将 AMS 的实例(这里是ActivityManagerService.Lifecycle())注册到 ServiceManager 中 。
6.2.3 传递 Binder 对象
在注册 AMS 服务的过程中,实际上是将 AMS 的 Binder 对象传递给了 ServiceManager 。Binder 是 Android 系统中实现进程间通信(IPC)的重要机制,AMS 通过 Binder 机制与其他组件进行通信 。当将 AMS 的 Binder 对象传递给 ServiceManager 后,其他组件就可以通过 ServiceManager 获取到 AMS 的 Binder 对象,进而与 AMS 进行跨进程通信 。例如,当一个应用程序需要启动一个 Activity 时,它可以通过 ServiceManager 获取到 AMS 的 Binder 对象,然后通过这个 Binder 对象向 AMS 发送启动 Activity 的请求 。
通过以上步骤,完成了 AMS 的 Binder 服务注册 。这个过程实现了 AMS 与系统其他组件的绑定,为后续的跨进程通信奠定了基础 。其他组件可以通过 ServiceManager 方便地找到 AMS,并利用 AMS 提供的各种功能来实现应用程序的管理和系统资源的调度 。这种基于 Binder 机制的服务注册方式,使得 Android 系统中的各个组件能够高效、稳定地进行通信和协作,保证了系统的正常运行 。
6.3 与其他服务交互
在 Android Framework 中,AMS 与其他系统服务的交互是系统运作的核心机制之一,这种交互确保了系统的各个部分能够协同工作,实现各种复杂的功能 。AMS 与其他服务的交互主要通过 Binder 机制实现,涉及多个关键类和接口 。
除了与 WindowManagerService(WMS)密切合作来管理应用程序的窗口和界面显示外,AMS 还需要与以下服务进行频繁交互:
- PowerManagerService:用于管理设备的电源状态和睡眠 / 唤醒行为。AMS 与 PowerManagerService 交互,以便根据应用程序的状态和用户操作来控制设备的电源。例如,当用户长时间不操作设备时,PowerManagerService 可能会使设备进入睡眠状态以节省电量。此时,AMS 需要与 PowerManagerService 协作,确保在设备进入睡眠前,应用程序的状态得到妥善处理,如暂停正在运行的任务等。而当用户唤醒设备时,AMS 也需要与 PowerManagerService 配合,恢复应用程序的正常运行状态 。
- BatteryStatsService:提供电池使用统计信息,帮助优化功耗。AMS 可以从 BatteryStatsService 获取各个应用程序的电池使用情况,以此为依据来调整应用程序的运行策略,以达到优化电池功耗的目的。比如,如果某个应用程序消耗了大量的电池电量,AMS 可能会降低该应用程序的某些后台服务的优先级,或者在适当的时候暂停这些服务,以减少电池的消耗 。
- PackageManagerService:提供应用程序包信息,用于识别和管理应用程序。AMS 在启动应用程序、管理应用程序的生命周期等过程中,需要从 PackageManagerService 获取应用程序的相关信息,如应用程序的安装路径、版本信息、权限声明等。例如,当 AMS 要启动一个 Activity 时,它需要从 PackageManagerService 获取该 Activity 所在应用程序的相关信息,以确保能够正确地启动和管理该 Activity 。
- NotificationManagerService:处理通知的显示和管理。AMS 在某些情况下需要与 NotificationManagerService 交互来发送通知给用户。比如,当一个应用程序有新的消息或者重要事件发生时,AMS 可以通过 NotificationManagerService 来显示相应的通知,提醒用户。同时,AMS 也可能会根据系统的状态和用户的设置,来控制通知的显示方式和优先级 。
冷启动流程的设计体现了 Android 系统在性能优化和资源管理方面的深思熟虑。通过 Zygote 进程的预加载机制,减少了应用启动时的类加载和资源初始化开销,提高了应用的启动速度 。同时,ActivityThread 的主线程消息循环机制确保了应用的高效执行和系统资源的合理分配 。这种精心设计的冷启动流程不仅加快了应用的启动速度,还为 Android 系统的整体性能和用户体验提供了有力保障 。
7.2 热启动机制
在 Android 系统的应用启动过程中,热启动机制是一种优化策略,旨在加速应用的再次启动 。与冷启动不同,热启动通常发生在应用已经在后台运行,用户再次切换回该应用时 。这种机制主要通过 ApplicationCache 类实现,它缓存了应用的部分状态信息,以便在下次启动时快速恢复 。
7.2.1 缓存创建
当应用退出到后台时,系统会将部分状态信息和资源写入缓存文件 。这些状态信息包括 Activity 的当前状态、界面的显示位置、应用的一些临时数据等 。例如,在一个文档编辑应用中,当用户将应用切换到后台时,系统会将当前正在编辑的文档的内容、光标位置等信息缓存起来 。系统会通过 ApplicationCache 类的相关方法来实现缓存的创建 。具体来说,可能会将这些信息以某种格式(如二进制数据或者序列化后的对象)写入到一个特定的缓存文件中 。
7.2.2 缓存读取
当应用再次启动时,系统会优先从缓存文件中读取信息 。ApplicationCache 类会提供相应的方法来读取缓存文件中的数据 。例如,在文档编辑应用再次启动时,系统会调用 ApplicationCache 的读取方法,从之前创建的缓存文件中读取文档内容、光标位置等信息 。通过读取缓存,应用可以跳过部分初始化步骤,因为这些信息已经在缓存中保存,不需要重新计算或获取 。
7.2.3 状态恢复
读取缓存后,应用会快速恢复至上次关闭时的状态 。系统会根据读取到的缓存信息,重新设置 Activity 的状态、界面的显示位置等 。在文档编辑应用中,系统会根据缓存的文档内容和光标位置,将文档内容显示在界面上,并将光标定位到上次编辑的位置,用户可以继续进行编辑操作,就好像应用从未关闭过一样 。
关键代码片段如下:
public class ApplicationCache {
private static final String CACHE_FILE_NAME = "app_cache.dat";
public void saveToCache(Bundle outState) {
try {
FileOutputStream fos = openFileOutput(CACHE_FILE_NAME, MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(outState);
oos.close();
} catch (IOException e) {
Log.e(TAG, "Failed to save cache");
}
}
public Bundle loadFromCache() {
try {
FileInputStream fis = openFileInput(CACHE_FILE_NAME);
ObjectInputStream ois = new ObjectInputStream(fis);
return (Bundle) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
Log.e(TAG, "Failed to load cache");
}
return null;
}
}
在这段代码中,saveToCache 方法用于将应用的状态信息(以 Bundle 的形式传入)保存到缓存文件中 。它首先通过 openFileOutput 方法打开一个私有模式的文件输出流,然后使用 ObjectOutputStream 将 Bundle 对象写入文件 。loadFromCache 方法则用于从缓存文件中读取状态信息 。它通过 openFileInput 方法打开缓存文件的输入流,然后使用 ObjectInputStream 读取文件中的对象,并将其转换为 Bundle 类型返回 。如果读取过程中发生异常,如文件不存在或者数据格式错误,该方法会返回 null 。
这种机制显著缩短了应用的启动时间,尤其在频繁切换应用的场景下,能明显提升用户体验 。通过减少不必要的初始化步骤,热启动机制有效降低了系统资源消耗,同时提高了整体系统响应速度 。用户可以更快地回到之前使用的应用状态,继续进行操作,提高了工作效率和使用的便捷性 。同时,对于系统来说,减少了资源的浪费,使得系统能够在有限的资源下更好地运行多个应用 。
7.3 进程创建
在 Android 系统中,进程创建是应用启动的关键环节,这一过程主要由 ActivityManagerService(AMS)负责协调,涉及多个核心组件的协作 。
7.3.1 检查现有进程
当 AMS 收到启动应用的请求时,它首先会检查是否存在可用的进程来承载目标 Activity 。AMS 会维护一个进程列表,记录系统中所有正在运行的进程的信息 。它会根据应用的需求和进程的状态来判断是否有合适的进程可以复用 。例如,如果有一个之前已经启动过的相同应用的进程,并且该进程处于空闲状态或者可以被复用的状态,AMS 就会优先考虑使用这个进程来启动目标 Activity 。这样可以避免重复创建进程带来的资源开销,提高系统的效率 。
7.3.2 创建新进程
如果经过检查发现没有可用的进程来承载目标 Activity,AMS 就会通过 Zygote 进程创建新进程 。如前面所述,Zygote 进程是所有应用进程的父进程,它通过 fork () 系统调用创建新的应用进程 。在创建新进程时,AMS 会向 Zygote 进程发送创建进程的请求,并传递一些必要的参数,如应用的相关信息、进程的优先级等 。Zygote 进程接收到请求后,会进行一系列的操作来创建新的应用进程,包括复制自身的资源、进行特殊化处理等 。
7.3.3 初始化进程
新进程创建完成后,需要进行初始化操作 。AMS 会为新进程分配资源,包括内存、CPU 时间片等 。同时,AMS 会与新进程建立 Binder 通信通道,通过 Binder 机制,AMS 可以与新进程进行交互,对新进程中的应用进行管理 。例如,AMS 可以向新进程发送启动 Activity 的命令,新进程接收到命令后会按照相关流程启动 Activity 。在初始化过程中,新进程还会加载应用的相关代码和资源,创建应用的运行环境,为应用的正常运行做好准备 。
这个过程体现了 Android 系统在资源管理和进程隔离方面的精心设计 。通过优先检查现有进程并复用,减少了不必要的进程创建,提高了资源利用率 。而在需要创建新进程时,通过 Zygote 进程的高效创建机制和后续的初始化操作,确保了新进程能够快速、稳定地启动应用 。同时,通过 Binder 通信通道的建立,AMS 能够有效地对新进程中的应用进行管理,保证了应用的高效启动和系统的稳定性 。无论是在资源充足还是资源紧张的情况下,Android 系统的进程创建机制都能较好地满足应用启动的需求,为用户提供流畅的应用启动体验 。
冷启动过程中的关键类和方法包括:
ZygoteProcess:负责与 Zygote 进程通信,协调新应用进程的创建 。 RuntimeInit:初始化应用环境,启动主线程 。 ActivityThread:应用进程的入口点,管理应用程序的主线程和与 AMS 的通信 。 Instrumentation:用于创建和启动 Activity,对 Activity 的生命周期进行监控和干预 。 ActivityManagerService:管理应用生命周期,调度应用的启动和各种组件的状态变化 。
7.1.3 Activity 启动与渲染
AMS 调度:当应用进程初始化完成后,AMS 开始调度应用的 Activity 启动 。AMS 通过 Binder 通信调用 ApplicationThread 的 scheduleLaunchActivity () 方法 。ApplicationThread 是 ActivityThread 的内部类,它负责与 AMS 进行通信,接收 AMS 发送的各种命令,并将这些命令传递给 ActivityThread 进行处理 。 ActivityThread 处理:ActivityThread 接收到 AMS 发送的启动 Activity 的命令后,会通过 sendMessage (H.LAUNCH_ACTIVITY) 方法将启动 Activity 的消息发送到主线程的消息队列中 。主线程的消息循环会不断地从消息队列中取出消息并进行处理,当取出启动 Activity 的消息时,就会开始处理 Activity 的启动流程 。 Activity 创建:ActivityThread 在处理启动 Activity 的消息时,会通过 Instrumentation 类的 newActivity () 方法来创建 Activity 的实例 。Instrumentation 类在 Activity 的创建和启动过程中起着重要的作用,它可以对 Activity 的创建和启动进行监控和干预 。 Activity attach:创建 Activity 实例后,会调用 Activity 的 attach () 方法,将 Activity 与应用的运行环境进行绑定 。在 attach () 方法中,会设置 Activity 的一些属性,如所属的应用程序上下文、WindowManager 等,为 Activity 的正常运行做好准备 。 Activity 生命周期:完成 attach () 方法后,Activity 会依次执行 onCreate 和 onStart 方法 。在 onCreate 方法中,开发者通常会进行一些 Activity 的初始化操作,如设置布局、初始化视图等;在 onStart 方法中,Activity 会变得可见,但还没有获得焦点 。 首帧渲染:在 Activity 的相关初始化完成后,会进行首帧渲染 。这包括创建 DecorView,DecorView 是 Activity 界面的顶级视图,它包含了 Activity 的标题栏、状态栏等 。然后,启动绘制流程,将 Activity 的界面绘制到屏幕上,用户就可以看到应用的界面了 。
7.1.2 应用进程初始化
RuntimeInit 启动主线程:新创建的应用进程在继承了 Zygote 的相关资源后,会通过 RuntimeInit 类来启动主线程 。主线程是应用程序中负责处理用户界面交互和大多数任务的线程,它的启动是应用程序能够正常运行的关键步骤 。RuntimeInit 会进行一系列的初始化操作,为应用程序的运行环境做准备 。 ActivityThread 初始化:ActivityThread 是应用进程的核心类,它负责管理应用程序的主线程和与 AMS 进行通信 。在主线程启动后,ActivityThread 会进行初始化 。在初始化过程中,ActivityThread 会创建一些关键的数据结构和对象,用于管理应用程序的组件,如 Activity、Service 等 。同时,ActivityThread 还会建立与 AMS 的通信通道,通过 Binder 机制与 AMS 进行交互 。 加载应用的 Application 类:Application 类是应用程序的全局类,它在应用程序启动时会被加载 。ActivityThread 会负责加载应用的 Application 类,并创建其实例 。在 Application 类的 onCreate () 方法中,开发者可以进行一些全局的初始化操作,如初始化数据库、配置网络等 。
这些交互通过定义在 IActivityManager 接口中的方法实现,如 getPowerProfile () 和 getBatteryStats () 等。AMS 通过这些方法与其他服务进行通信和数据交换 。例如,AMS 调用 PowerManagerService 的 getPowerProfile () 方法来获取设备的电源配置文件,以便更好地管理应用程序与电源相关的行为;调用 BatteryStatsService 的 getBatteryStats () 方法来获取电池使用统计信息,从而优化应用程序的功耗 。
这种设计确保了 AMS 能够全面掌控系统资源,协调各项服务的运作。通过与其他服务的紧密交互,AMS 可以根据系统的整体状态和应用程序的需求,做出合理的决策,优化整体系统性能和用户体验。例如,在系统资源紧张时,AMS 可以结合 PowerManagerService、BatteryStatsService 等提供的信息,综合考虑各个应用程序的资源使用情况和优先级,采取相应的措施,如终止一些非关键的应用程序进程,以保证系统的稳定性和关键应用的正常运行 。同时,通过与 NotificationManagerService 和 PackageManagerService 的交互,AMS 能够更好地管理应用程序的通知和生命周期,为用户提供更加便捷和高效的使用体验 。
七、应用启动过程
7.1 冷启动流程
在 Android 系统的应用启动过程中,冷启动是一种关键的启动方式。当应用首次被启动,或者之前被系统彻底杀死后重新启动时,就会发生冷启动。冷启动涉及多个系统组件的协同工作,包括 Zygote 进程、ActivityManagerService(AMS)和应用进程本身 。
7.1.1 Zygote 进程孵化新应用进程
通过 fork () 系统调用创建新进程:Zygote 进程是 Android 系统中非常特殊的一个进程,它是所有应用进程的父进程。当需要启动一个新的应用进程时,Zygote 进程会通过 fork () 系统调用创建一个新的进程 。fork () 系统调用会创建一个与 Zygote 进程几乎完全相同的子进程,这个子进程就是新的应用进程的雏形 。 新进程继承 Zygote 的预加载类和资源:Zygote 进程在启动时会预加载一些常用的类和资源,这些类和资源对于大多数应用来说都是通用的。新创建的应用进程会继承 Zygote 进程预加载的这些类和资源,这大大减少了应用启动时的类加载和资源初始化的时间开销 。例如,一些 Android 系统的基础类库、常用的资源文件等都会被预加载并继承给新的应用进程 。 特殊化处理:在创建新进程后,还需要进行一些特殊化处理。这包括设置新进程的用户 ID(UID),以确保应用进程在系统中的权限隔离;加载应用特定的库,这些库可能是应用所依赖的第三方库或者自定义的功能库 。通过这些特殊化处理,新进程逐渐成为一个独立的、符合应用需求的进程 。
八、AMS 性能优化
8.1 启动优化
在 Android 系统的性能优化中,AMS 的启动过程优化对于提高系统响应速度和资源利用效率至关重要 。为了实现这一目标,Android 采用了多项优化技术 。
8.1.1 延迟加载
Android 引入了 Lazy Loading 机制,即延迟加载。在系统启动过程中,对于 AMS 服务,系统不会在一开始就立即加载和初始化它,而是仅在真正需要使用 AMS 服务时才进行加载和初始化操作 。这样做的好处是避免了在系统启动初期就进行大量的资源消耗 。例如,在系统刚启动时,用户可能并不会立即使用与 AMS 密切相关的功能,如启动新的应用程序等 。如果在系统启动时就加载 AMS,那么这部分资源就会被提前占用,而采用延迟加载机制,就可以将这部分资源用于其他更紧迫的任务,等到用户真正需要启动应用程序等操作时,再加载 AMS 服务,这样可以提高系统启动的整体速度 。
8.1.2 异步初始化
采用 Asynchronous Initialization 策略,也就是异步初始化 。在 AMS 的初始化过程中,系统会将部分初始化工作放到后台线程执行 。因为 AMS 的初始化涉及到很多复杂的操作,如与其他系统服务的交互、数据结构的初始化等,如果这些操作都在主线程中进行,会导致主线程阻塞,从而影响系统的启动速度和响应性 。通过将部分初始化工作放到后台线程执行,可以减少对主线程的阻塞 。例如,在初始化 AMS 与其他系统服务的连接时,可以在后台线程中进行,这样主线程可以继续执行其他任务,如加载系统的基本界面等 。当后台线程完成相关初始化工作后,再将结果返回给主线程,主线程再进行后续的处理 。这样,通过异步初始化的方式,能够有效地提高系统的启动速度,让用户更快地进入系统并开始使用 。
8.1.3 服务分离
在 Android 10 之后,系统引入了 ActivityTaskManagerService(ATMS) 。ATMS 专门负责管理 Activity 组件,将原本由 AMS 承担的部分与 Activity 相关的管理任务分离出来 。在引入 ATMS 之前,AMS 需要处理大量与 Activity 相关的事务,包括 Activity 的启动、任务栈管理、生命周期管理等,这使得 AMS 的负担较重,可能会影响其性能 。而引入 ATMS 后,AMS 的负担得到了减轻 。AMS 可以将更多的精力放在系统资源管理、进程管理等核心任务上,而 ATMS 则专注于 Activity 的管理 。这种服务分离的方式提高了整体性能,使得系统在处理 Activity 相关的操作时更加高效 。例如,在启动 Activity 时,ATMS 可以更专注地处理 Activity 的启动流程和任务栈的相关操作,
请继续
而 AMS 则可以更好地协调系统资源,确保 Activity 启动过程中资源的合理分配 。这样分工明确的设计,使得系统在处理复杂的 Activity 管理任务时更加流畅,提高了用户体验 。
这些优化措施共同作用,显著提升了系统的启动速度和稳定性 。通过延迟加载避免了不必要的资源浪费,异步初始化减少了启动阻塞,服务分离提高了系统的处理效率 。这些优化不仅让用户能够更快地启动和使用应用程序,还保证了系统在运行过程中的稳定性和流畅性 。无论是在日常使用中频繁启动应用,还是在系统资源紧张的情况下,经过优化的 AMS 启动过程都能让系统表现得更加出色,为用户提供更流畅的使用体验 。
8.2 内存管理优化
在 Android 系统的内存管理优化中,AMS 扮演着关键角色 。通过 CachedAppOptimizer 类,AMS 实现了对应用端内存的精细管理 。
8.2.1 监控 oom_adj 值变化
CachedAppOptimizer 类负责监控应用的 oom_adj 值变化 。如前文所述,oom_adj 值决定了进程在内存紧张时被终止的概率 。CachedAppOptimizer 会实时关注各个应用进程的 oom_adj 值 。当 oom_adj 值发生变化时,这往往意味着应用进程的状态或者系统内存状况发生了改变 。例如,如果一个应用从后台运行切换到前台运行,它的 oom_adj 值可能会降低,以表示它的重要性提升,更不容易被系统杀死 。CachedAppOptimizer 会捕捉到这种变化,并根据新的 oom_adj 值来调整对该应用的内存管理策略 。
8.2.2 触发内存回收优化
在特定条件下,当发现应用的 oom_adj 值达到一定阈值或者系统内存压力增大时,CachedAppOptimizer 会触发内存回收优化 。内存回收优化过程涉及两种主要策略,即匿名页回收和文件页回收,具体采用哪种策略取决于应用的实际内存使用情况 。
匿名页回收:匿名页是指那些没有与文件系统中的文件关联的内存页面,例如应用程序在运行过程中动态分配的堆内存 。当进行匿名页回收时,系统会检查应用中那些长时间未被访问的匿名页 。如果发现有这样的匿名页,系统会将其回收,释放出对应的内存空间 。例如,一个应用在运行过程中创建了一些临时的数据结构,这些数据结构占用了一定的堆内存,形成了匿名页 。如果这些数据结构在一段时间内没有被访问,CachedAppOptimizer 会认为这些匿名页可以被回收,从而释放出这部分内存,供其他更需要的应用或系统服务使用 。
文件页回收:文件页是与文件系统中的文件相关联的内存页面,比如应用程序加载的代码文件、资源文件等对应的内存页面 。在文件页回收时,系统会检查那些已经被缓存到内存中的文件页 。如果某个文件页对应的文件在一段时间内没有被再次访问,并且系统内存紧张,CachedAppOptimizer 会考虑回收这部分文件页 。不过,由于文件页可能还需要被重新读取,所以在回收文件页时,系统会根据文件的重要性和访问频率等因素进行综合判断 。例如,对于一些很少被访问的资源文件对应的文件页,系统可能会优先回收;而对于一些关键的代码文件对应的文件页,可能会在内存压力非常大时才会考虑回收 。
这种机制不仅提高了系统的内存利用效率,还能在内存紧张时快速释放非关键资源 。通过对应用的 oom_adj 值进行监控,并根据实际情况触发匿名页回收和文件页回收,Android 系统能够在资源受限的情况下维持良好的运行状态 。在内存紧张时,及时回收那些不必要的内存页面,保证系统有足够的内存来运行关键的应用和服务 。同时,这种主动的内存管理策略也避免了内存碎片的产生,提高了内存的整体利用率,为用户提供更流畅的使用体验 。无论是在多应用同时运行的场景下,还是在系统长时间运行后内存逐渐紧张的情况下,AMS 通过 CachedAppOptimizer 类实现的内存管理优化都能有效地保障系统的性能和稳定性 。
8.3 进程回收策略
在 Android 系统的进程管理中,AMS 的进程回收策略对于系统的性能和稳定性起着关键作用 。AMS 主要通过 trimApplications () 方法实现全局内存回收机制 。
8.3.1 trimApplications () 方法的作用
trimApplications () 方法会遍历整个应用程序列表,逐一检测不活动的应用程序 。这里的不活动应用程序是指那些在后台长时间没有被用户使用,并且其进程状态处于可以被回收的状态的应用 。一旦检测到这样的应用程序,AMS 会主动关闭它们,释放这些应用程序所占用的内存资源 。例如,当用户打开了多个应用程序,但在一段时间内只使用了其中一个应用,其他应用在后台处于闲置状态 。此时,AMS 的 trimApplications () 方法就会扫描这些后台应用程序,对于那些符合不活动条件的应用,会采取关闭其进程的操作,将它们占用的内存释放出来 。
8.3.2 结合 LMK 机制
这种进程回收机制结合了 LMK(Low Memory Killer)机制 。LMK 机制通过调整进程的 oom_adj 值来决定进程的存活概率 。在系统内存紧张时,LMK 会根据进程的优先级和系统内存状况,动态调整各个进程的 oom_adj 值 。例如,对于前台正在运行的应用程序进程,由于其直接与用户交互,对用户体验影响较大,LMK 会为其设置较低的 oom_adj 值,使它在内存紧张时不容易被杀死;而对于后台长时间闲置的应用程序进程,LMK 会为其设置较高的 oom_adj 值,使它在内存紧张时更容易被终止 。
AMS 的进程回收策略与 LMK 机制相互配合 。当 AMS 的 trimApplications () 方法遍历应用程序列表时,会参考 LMK 机制为每个进程设置的 oom_adj 值 。对于那些 oom_adj 值较高,也就是相对不太重要且占用内存的进程,AMS 会优先考虑将其关闭 。同时,AMS 也会根据系统的整体内存状况和资源需求,灵活调整进程回收的策略 。如果系统内存压力非常大,AMS 可能会加大进程回收的力度,关闭更多的不活动进程;而如果系统内存压力较小,AMS 则会相对保守地进行进程回收,以保证用户在切换回后台应用时能够快速恢复应用状态 。
这种策略确保了系统在资源紧张时能够维持关键进程的运行 。通过优先回收那些不活动且相对不重要的进程,系统可以释放出足够的内存资源来保证前台应用和关键系统服务的正常运行 。例如,在用户玩游戏时,如果系统内存紧张,AMS 会通过进程回收策略关闭一些后台的非关键应用程序,确保游戏进程有足够的内存和系统资源,避免游戏出现卡顿甚至崩溃的情况 。同时,这种策略也优化了整体性能和用户体验 。通过合理地回收进程,系统能够保持较高的资源利用率,避免内存泄漏和资源浪费,让用户在使用手机时感受到更流畅、稳定的系统性能 。无论是在日常使用中频繁切换应用,还是在运行大型应用程序时,AMS 的进程回收策略都能有效地保障系统的正常运行,为用户提供良好的使用环境 。