深入理解 Android:ActivityManagerService

Linux 设置进程优先级函数:

int setpriority(int which, int who, int prio);
  • 参数 whichwho 联合使用:

    • whichPRIO_PROGRESS 时,who 代表进程;

    • whichPRIO_PGROUP 时, who 代表进程组;

    • whichPRIO_USER 时,who 代表 uid

  • 参数 prio 为优先级,范围 [-20,19],值越大,被调用几率越小;

Linux 设置进程调度策略函数:

int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
  • 参数 pid 为进程 id;

  • 参数 policy 为调度策略,目前 Android 只支持前三种(非实时调度策略):

    • SCHED_OTHER: 默认值,标准的分时共享策略;

    • SCHED_BATCH: 针对批处理进程的调度策略;

    • SCHED_IDLE: 针对优先级非常低的适合在后台运行的策略;

    • SCHED_FIFO: 队列调度策略;

    • SCHED_RR: round-robin 循环调度策略;

  • 由于 Android 不支持实时调度策略,参数 param 必须为 NULL

oom_adj 与 lowmemorykiller:

  • Linux kernel 2.6.11 开始提供进程 OOM 控制机制:系统内存不足时,根据进程的 oom_adj 值选择杀死某些进程以回收资源;

  • oom_adj 取值范围 [-16,15],值越大该进程越容易被系统杀掉;

  • Linux 目前未提供设置进程 oom_adj 的函数,只能通过修改 /proc/进程id/oom_adj 文件中的值来实现;

  • Android 为 Linux kernel 新增的 lowmemorykiller 用于执行清理:

    • /sys/module/lowmemorykiller/parameters/minfree 文件描述不同级别内存阈值(单位 KB);

    • /sys/module/lowmemorykiller/parameters/adj 文件描述不同内存阈值对应的 oom_adj 值;

    • 若 minfree 文件内容为 1024, 2048, 3072, 4096, 5120, 6144, adj 文件内容为 0, 1, 2, 3, 4, 5,则表示剩余内存低于 1024 KB 时清理 oom_adj 大于 0 的进程;

    • Android 4.0 之前 lowmemorykiller 的参数配置在 init.rc 中由 init 进程设置(未考虑屏幕尺寸影响);现在则由 ProcessList 类综合考虑手机内存和屏幕尺寸后进行设置(该类还定义了各种进程的 oom_adj 值);

ActivityManagerService 概述:

  • ActivityManagerService 负责四大组件的启动/切换/调度、进程的管理/调度等;

  • ActivityManagerService 继承自 ActivityManagerNative 类,并实现了 Watchdog.MonitorBatteryStatsImpl.BatteryCallback 接口;而 ActivityManagerNative 继承自 Binder 类,并实现了 IActivityManager 接口;

  • 客户端使用的是 ActivityManager 类,其内部通过调用 ActivityManagerNative.getDefault() 得到一个 ActivityManagerProxy 对象,通过它与 ActivityManagerService 通信;

system_server 对 ActivityManagerService 的初始化:

  • 调用 ActivityManagerService.main() 方法,返回 Context 对象;

  • 调用 ActivityManagerService.setSytemProcess(),将 system_server 进程加入 ActivityManagerService,便于后者管理;

  • 调用 ActivityManagerService.installSystemproviders(),将 SettingsProvider 放到 system_server 进程中运行;

  • 调用 ActivityManagerService.self().setWindowManager(),在内部保存 WindowManagerService

  • 调用 ActivityManagerNative.getDefault().showBootMessage(),显示启动信息;

  • 调用 ActivityManagerService.self().systemReady(),在传入的 Runnable 对象的 run() 方法中:

    1. 调用 startSystemUi(),启动系统 UI;

    2. 调用 Battery、Network 等模块的 systemReady()

    3. 启动 Watchdog

ActivityManagerService::main():

  • 创建 AThread 线程对象:

    1. 设置线程优先级为 THREAD_PRIORITY_FOREGROUND

    2. 创建 ActivityManagerServive 对象:

      1. 创建 /data/system/ 目录;

      2. 创建 BatteryStatsServiceUsageStatsService

      3. 读取 OpenGL、及资源配置信息 Configuration

      4. 读取并解析 /proc/stat 文件中的 CPU 和内存信息、/data/system/packages-compact.xml 文件中的需要考虑屏幕尺寸的 APK 信息;

      5. 调用 Watchdog.getInstance().addMonitor() 将自己加入监控;

      6. 创建 mProcessStatsThread 线程,用于定时更新系统信息,和 mProcessStats 交互;

  • 调用 ActivityThread.systemMain() 方法返回 ActivityThread 对象:

    1. 调用 HardwareRenderer.disable(true) 禁用硬件渲染;

    2. 创建 ActivityThread 对象,并调用其 attach(true) 方法,

  • 调用 ActivityThread.getSystemContext() 得到 Context 对象;

  • 创建用于管理 Activity 启动和调度的核心类 ActivityStack 对象;

  • 调用 BatteryStatsServiceUsageStatsServicepublish() 方法;

  • 调用 ActivityManagerService.startRunning(),主要调用 systemReady()

ActivityThread:

  • ActivityThread 代表一个应用进程的主线程(其 main 方法由所在进程的主线程执行),其职责为调度和执行运行在主线程的四大组件;

  • 通过 ActivityThread 可以把 Android 系统提供的组件之间的交互机制和接口(如 Context )也扩展到 system_server 中使用;实际上 system_server 可以看作一个特殊的应用进程(framework-res.apk 和 SettingsProvider.apk 都运行在该进程中);

  • attach(true) 对系统进程的处理:

    1. 创建 Instrumentation 工具类对象,它通过 AndroidManifest.xml 中的标签描述,用于监控与其他组件的交互;

    2. 创建 ContextImpl 对象,并调用其 init() 方法;Context 是一个可以操作 Application 及其中四大组件的接口;

    3. 调用 Instrumentation.newApplication() 创建 Application 对象;它是可以看作一个四大组件的容器,ActivityManagerService 内部通过 mAllApplications 保存所有 Application

    4. 调用 Application.onCreate()

    5. 调用 ViewRootImpl.addConfigCallback(),响应 onConfigurationChanged()onLowMemory()onTrimMemory() 等方法;

  • getSystemContext()

    1. 调用 ContextImpl.createSystemContext() 创建 ContextImpl 对象;

    2. 创建 LoadedApk 对象,传入的 package 参数为 "android",即代表 framework-res.apk,相当于读取系统资源;

    3. 调用 ContextImpl.init() 方法,并传入上面的 LoadedApk 对象,相当于加载系统资源;

    4. 调用 ContextImpl.getResources().updateConfiguration(),初始化屏幕等配置信息;

IApplicationThread 和 ActivityThread:

  • IApplication 定义了 ActivityManagerService 和其他应用进程进行 Binder 通信的接口: scheduleLaunchActivity()schedulePauseActivity()scheduleStopActivity() 等;

  • ActivityThread 通过成员变量 mAppThread 指向其内部类 ApplicationThread,而它继承自 IApplicationThread 的实现类 ApplicationThreadNative

  • ActivityManagerService 通过 IApplication 定义的接口向 ActivityThread 所在线程发消息,进而控制 Activity 执行相关回调;

Context 家族:

  • Context: 抽象类,提供了一组通用的 API;

  • ContextIml: 实现了 Context 类的功能, 大部分功能都是直接调用其属性 mPackageInfo 去完成;

  • ContextWrapper: 对 Context 类的包装,该类的构造函数包含一个的 Context 引用,即 ContextIml 对象;

  • ContextThemeWrapper: 该类内部包含 Theme 相关的接口,即 android:theme 属性指定的。只有 Activity 需要主题,ServiceApplication 不需要主题,所以 Service / Application 直接继承于 ContextWrapper 类;

  • Context 实例个数 = Service 个数 + Activity 个数 + 1(Application 对应的 Context 实例);

ActivityManagerService::setSystemProcess():

  • 调用 ServiceManager.addService() 注册几个服务:

    1. ActivityManagerService

    2. MemBinder:用于打印内存信息;

    3. GraphicsBinder:用于输出应用进程使用硬件显示加速的信息,Android 4.0 新增的服务;

    4. CpuBinder:CPU 信息;

    5. PermissionController:权限管理服务;

  • 调用 context.getPackageManager().getApplicationInfo() 查询包名为 androidApplicationInfo 对象;

  • 调用 ActivityThread.installSystemApplicationInfo() 注册上面查询到的 ApplicationInfo 对象:

    1. 调用 ActivityThread.getSystemContext() 返回之前初始化过的 Context 对象;

    2. 调用 context.init(new LoadedApk()) 再次初始化;注意之前初始化传入的最后一个参数为 null,这次传入的是上面查询到的包名为 androidApplicationInfo 对象;

    3. 创建 Profiler 对象,用于性能统计;

  • 调用 ActivityManagerService.newProcessRecordLocked() 创建用于保存进程信息的 ProcessRecord 对象:

    1. 获取 BatteryStatsService 对象,并创建一个耗电量统计项;

    2. 创建 ProcessRecord 对象:

      1. 初始化 BatteryStatsServiceApplicationInfoProcessNameIApplicationThread 等成员变量;

      2. 初始化 maxAdjhiddenAdjcurRawAdjcurAdj 等和进程调度和内存管理相关的变量;

      3. 对于 system_server 进程,ActivityManagerService 还进行了特殊处理:

        1. 将其 persisten 设为 true,被 kill 后会重建;

        2. pid 设为 MY_PID,即 system_server 进程号;

        3. processName 设置为 system

        4. maxAdj 设置为最大值 SYSTEM_ADJ

  • ActivityManagerService 内部通过 mProcessNames 保存所有进程名,调用 put() 保存上面创建的 ProcessRecord

  • 调用 ActivityManagerService.updateLruProcessLocked(),根据系统当前状态调整进程调度优先级和 OOM_Adj;

ActivityManagerService::installSystemProviders():

  • mProcessNames 取出 processName 为 system 且 uid 为 SYSTEM_UIDProcessRecord,即 system_server 对应的进程;

  • 调用 ActivityManagerService.generateApplicationProvidersLocked() 返回 List<ProviderInfo> 对象:

    1. 根据进程名和 uid,调用 PackageManagerService.queryContentProviders() 查询符合条件的 List<ProviderIndo>

    2. 遍历 List<ProviderInfo> 根据包名和 ApplicationInfo 查询(如果不存在则构造)并保存 ContentProviderRecord

    3. 调用 ensurePackageDexOpt() 执行 dex 优化;

  • providers 中去除非系统 Provider;

  • 调用 ActivityThread.installSystemProviders(),将 providers 安装到 system_server 进程:

    1. 调用 installProvider() 得到一个 IContentProvider 对象;

      1. 找到 Provider 对应的 Context,并调用 Context.getClassLoader()、通过反射生成 ContentProvider 实例;

      2. 调用 IContentProvider.asBinder.linkToDeath()

      3. 创建 ProviderClientRecord 对象,并保存到 mLocalProviders

    2. 创建 ContentProviderRefCount 对象对 ContentProvider 进行引用计数控制,引用数为 0 则从系统注销;

    3. 调用 ActivityManagerService.publishContentProviders()

      1. 根据调用者的 pid 找到对应的 ProcessRecord

      2. ProcessRecordpubProviders 中找到对应的 ContentProviderRecord,如果找到则以 authority 为 key 保存;

      3. 移除 mLaunchingProviders 中保存的处于启动状态的 Provider,并调用 notifyAll() 通知等待它们启动的进程;

      4. 调用 updateOomAdjLocked() 调整 oom_adj;

  • 创建 CoreSettingsObserver 对象,监听 Settings 数据库 secure 表的变化;

  • 调用 UsageStatsService.monitorPackages()

ContentProvider:

  • ContentProvider 本身只是一个容器,跨进程调用的支持是通过 Transport 实现的;TransporBinder 的子类 ContentProviderNative 派生;

  • ContentProviderNative 实现了 IContentProvider 接口,其内部类 ContentProviderProxy 供客户端使用;

  • ContentProvidergetIContentProvider() 返回 Transport 对象;

  • 系统提供 ComponentName 和 authority 两种方式找到 ContentProvider,所以 ActivityManagerService 存在对应的两个变量:mProvidersByClassmProvidersByName

ContentProviderRecord:

  • ContentProviderRecord 继承自 ContentProviderHolder,内部保存了 ProviderInfo、该 Provider 驻留进程的 ProcessRecord、以及使用该 Provider 的客户端所在进程的 ProcessRecord

  • ActivityManagerServicemProviderByClass 成员和 ProcessRecordpubProviders 成员均以 ComponentName 为 key 来保存对应的 ContentProviderRecord

ProviderClientRecord:

  • ProviderClientRecordActivityThread 提供的用于保存 ContentProvider 信息的结构;

  • 内部主要成员:

    1. mLocalProvider 用于保存 ContentProvider 对象;

    2. mProvider 用于保存 IContentProvider 对象(即 Transport 对象);

    3. mName 用于保存该 ContentProvider 的一个 authority;

ActivityManagerService::systemReady():

  • 准备 PRE_BOOT_COMPLETED 广播,向 PackageManagerService 查询接收者,为最后一个接收者注册回调(用来显示启动消息等),最后发送广播;

  • 杀掉那些在 ActivityManagerService 还未启动完成就已经先启动的应用进程(一般 Native 进程是不会向它注册的);

  • 从 Settings 数据库获取配置信息:

    • debug_app: 需要 debug 的 APP 名称;

    • wait_for_debugger: 1 表示需要等待调试器,否则直接启动;

    • always_finish_activities: 当一个 Activity 不再有地方使用时是否立即执行 destroy;

    • font_scale: 控制字体放大倍数(Android 4.0 新增);

  • 调用传入的 Runnable 类型的 goingCallback 参数的 run()

    1. 调用 startSystemUi(),启动 SystemUIService(实现了系统状态栏);

    2. 调用 Battery、Network 等其他模块的 systemReady(),启动 Watchdog

  • 启动 persistent1 的 APK 进程(排除掉包名为 android 的 framework-res.apk,因为它之前已经被启动);

  • 调用 startHomeActivityLocked() 启动 Home 界面;

  • 调用 finishBooting()

    1. 注册 PACKAGE_RESTART 的 BroadcastReceiver 处理包重启;

    2. 启动那些等待启动的进程;

    3. 每隔 15 分钟检查一次各应用进程用电情况,杀掉使用 Wakelock 时间过长的进程;

    4. 调用 SytemProperties.set() 设置 sys.boot_completed 属性为 1

    5. 发送 ACTION_BOOT_COMPLETED 广播;

ActivityStack、ActivityRecord、TaskRecord:

  • ActivityRecordtask 变量指向该 Activity 所在的 Task; state 变量表示 Activity 状态;

  • ActivityStackmMainStack 表示是否是主 Stack,由于目前只有一个 ActivityStack,所以该变量值为 true

  • ActivityStackmHistory 成员是 ArrayList 类型,用于保存系统中所有 ActivityRecord

  • ActivityStack 没有变量保存所有 TaskRecord

ActivityStack::startActivityMayWait():

  • PackageManagerService 查询匹配传入的 IntentActivityInfo

  • 获取 Binder 调用方 uid 和 pid;

  • 调用 startActivityLocked() 返回启动结果 res

    1. 如果调用者不为空,则调用 ActivityManagerService.getRecordForAppLocked() 得到它的 ProcessRecord;如果 ProcessRecord 为空(该进程没有在 ActivityManagerService 注册),则返回 START_PERMISSION_DENIED 错误;

    2. 声明两个 ActivityRecord 类型的变量 sourceRecord(启动目标 Activity 的那个 Activity)和 resultRecord(接收启动结果的 Activity,即处理 onActivityResultActivity);一般情况下,二者指向同一个 Activity

    3. 读取 Intentflags,检查 err 是否为 0,检查权限信息;

    4. ActivityManagerService 设置一个 IActivityController 类型的监听者(主要用于 Monkey 测试);

    5. 创建 ActivityRecord 对象;

    6. 调用 ActivityManagerService.checkAppSwitchAllowedLocked() 检查调用建成是否有权限切换应用,如果没有权限,则保存到 ActivityManagerServicemPendingActivityLaunches 变量;

    7. 调用 ActivityManagerService.doPendingActivityLaunchesLocked() 启动处于 pending 状态的 Activity

    8. 调用 startActivityUncheckedLocked() 完成本次启动请求;

  • 如果 Configuration 有变化,调用 ActivityManagerService.updateConfigurationLocked()

  • 处理启动结果;

ActivityStack::startActivityUncheckedLocked():

  • 判断是否需要创建新的 Task,以下两种情况需要在 Intentflags 附加 Intent.FLAG_ACTIVITY_NEW_TASK

    • 发起请求的 sourceRecord 为空,或者为单例(独占一个 Task);

    • 待启动的 Activity 设置了 SingleTaskSingleInstance

  • 调用 findTaskLocked()findActivityLocked()mHistory 中得到 ActivityRecord 类型的 taskTop 对象;

  • 调用 topRunningNonDelayedActivityLocked() 判断是否处于栈顶,决定是否创建新的 Activity

  • ActivityRecord 设置 TaskRecord

  • 调用 ActivityManagerService.grantUriPermissionFromIntentLocked() 授权;

  • 调用 stackActivityLocked() 完成启动:

    1. 如果不是新 Task,则从 mHistory 中找到对应的 ActivityRecord 位置;否则,将其添加到 mHistory 末尾;

    2. 设置 ActivityRecordinHistorytrue,表示已经存在与 mHistory 中;

    3. 判断是否显示 Activity 切换动画,需要与 WindowManagerService 交互;

    4. 调用 resumeTopActivityLocked()

ActivityStack::resumeTopActivityLocked():

  • 调用 topRunningActivityLocked()mHistory 中找到第一个需要启动的 ActivityRecord,如果没有则启动 Home 页面;

  • 将该 ActivityRecordmStoppingActivitiesmGoingToSleepActivitiesmWaitingVisibleActivities 中移除;

  • 如果当前正在 pause 一个 Activity,需要先等待 pause 完毕,然后系统重新调用 resumeTopActivityLocked()

  • mResumedActivity 指向上次启动的 Activity,即当前显示的 Activity;如果它不为空,调用 startPausingLocked() 中止,并返回;

  • 如果传入的 prev 页面不为空,则需要通知 WindowManagerService 进行与页面切换相关的工作(停止绘制等);

  • 如果该 ActivityRecord 对应的进程已存在,则只需要重启该 Activity

  • 如果不存在,通知 WindowManagerService 显示启动页面,并调用 startSpecificActivityLocked():

    1. 调用 ActivityManagerService.getProcessRecordLocked() 根据进程名和uid查找进程;

    2. 设置启动时间等信息;

    3. 如果该进程存在,并已经向 ActivityManagerService 注册,调用 realStartActivityLocked() 启动目标 Activity

    4. 如果该进程不存在,调用 ActivityManagerService.satrtProcessLocked() 启动进程;

ActivityManagerService::startProcessLocked():

  • 处理 FLAG_FROM_BACKGROUND 标志和 BadProcess

    1. 一个进程如果连续崩溃超过两次,ActivityManagerService 会将其 ProcessRecord 加入 mBadProcesses

    2. 由于进程崩溃会弹框,所以一般禁止启动处于后台的 BadProcess;但如果是用户触发的(比如点击 button 跳到后台页面),则会把该进程从 mBadProcesses 移除,给它“重新做人”的机会;

  • 创建 ProcessRecord 对象,并保存到 mProcessNames

  • mProcessesOnHold 移除该 ProcessRecord,它用于保存在系统还未准备好就发送启动请求的 ProcessRecord

  • 更新 CPU 信息,从 PackageManagerService 查询该进程的 gid;

  • 调用 Process.start(),让 Zygote 派生子进程,该子进程执行 ActivityThread.main() :

    1. 调用 Process.setArgV0() 设置进程名为 pre-initialized

    2. 创建 ActivityThread 对象;

    3. 调用 ActivityThread.attach(false) 处理应用进程:

      1. 设置在 DropBoxManagerService 日志系统中看到的进程名为 pre-initialized

      2. 调用 RuntimeInit.setApplicationObject(mAppThread.asBinder())

      3. 调用 ActivityManagerService.attachApplicationLocked(mAppThread)

  • 执行电量统计;

  • 如果该进程为 persistent,通知 Watchdog

  • 以 pid 为 key,将该进程的 ProcessRecord 保存到 mPidsSelfLocked

  • 发送 PROC_START_TIMEOUT_MSG 消息,如果新进程 10s 没有和 ActivityManagerService 交互,则认为新进程启动失败;

ActivityManagerService::attachApplicationLocked():

  • 根据 pid 查找对应的 ProcessRecord;如果为空(未向 ActivityManagerService 注册):

    1. 如果 pid 大于 0 且不是 system_server 进程,调用 Process.killProcessQuiet() 杀掉该进程;

    2. 否则调用 IApplicationThread.sheduleExit() 退出;

  • 如果该 ProcessRecord.thread 对象不为空,表示该进程为旧的未被杀死的进程,系统不会重用,而是调用 handleAppDiedLocked() 处理;

  • 创建应用死亡讣告对象 AppDeathRecipient,并调用 thread.asBinder().linkToDeath()

  • 设置该进程的调度优先级以及 oom_adj 相关变量;

  • 通过 PackageManagerService 查询运行在该进程中的 ContentProvider 对象;

  • 对相关 Package 进行 Dex 优化;

  • 调用 ApplicationThread.bindApplication()

    1. 调用 ServiceManager.initServiceCache() 保存 ActivityManagerService 传递过来的 Service 信息;

    2. 调用 setCoreSettings() 向主线程消息队列添加 SET_CORE_SETTINGS 消息;

    3. 创建 AppBindData 对象,用于保存 processNameappInfo 等参数信息;

    4. 初始化性能统计对象 Profiler

    5. 调用 Process.setArgV0()DdmHandleAppName.setAppname() 设置正式进程名;

    6. 对于 persistent 进程,在低内存设备上,调用 HardwareRenderer.disable(false) 禁用硬件加速;

    7. 初始化 AsyncTask 的线程池;

    8. 设置时区、语言、资源、兼容模式;

    9. 根据传过来的 ApplicationInfo 创建一个对应的 LoadedApk 对象;

    10. StrictMode 和 DebugMode 相关处理;

    11. 设置 HTTP 代理信息;

    12. 如果 Package 声明了 FLAG_LARGE_HEAP,调用 VMRuntime.getRuntime().clearGrowthLimit() 清除内存限制;

    13. 根据 LoadedApk 对象,并利用反射,生成 Manifest 文件中声明的 Application 对象;用 mInitialApplication 保存该进程中创建的第一个 Application

    14. 调用 installContentProviders() 安装本 Package 下的 ContentProvider

    15. 调用 mInstrumentation.callApplicationOnCreate() 执行 Application 对象的 onCreate() 方法;

  • 调用 updateLruProcessLocked()

  • 调用 ActivityStack.topRunningActivitylLocked() 获取 ActivityStack 中的第一个需要运行的 ActivityRecord

  • 根据 processNameuid 确定该 ActivityRecord 和目标进程有关,否则调用 ActivityStack.ensureActivitiesVisibleLocked() 处理;

  • 调用 ActivityStack.realStartActivityLocked() 启动该 ActivityRecord

  • 对于 mPendingServices 中处于 pending 状态的 ServiceRecord

    1. 如果根据 processNameuid 判断和目标进程无关,则不作处理;

    2. 否则调用 realStartService() 启动该 ServiceRecord

  • 如果上面几个组件初始化有错误,调用 handleAppDiedLocked() 处理;

  • 调用 updateOomAdjLocked() 根据该进程中的组建情况调节 oom_adj 值(组件越多越不易被杀死回收);

ActivityStack::realStartActivityLocked():

  • 调用 ActivityManagerService.updateConfigurationLocked() 处理 Config 变化;

  • ActivityRecord 加入到 ProcessRecordactivities 中保存;

  • 调用 ActivityManagerService.updateLruProcessLocked() 更新进程优先级;

  • 调用 ProcessRecord.threadActivityThread 类型)的 scheduleLaunchActivity() 通知应用的主进程启动 Activity:

    1. 调用 performLaunchActivity():

      1. 通过反射机制创建目标 Activity 对象;

      2. 调用 ActivityonCreate()onStart() 方法;

    2. 调用 handleResumeActivity()

      1. 调用 performResumeActivity() 执行 ActivityonResume() 方法;

      2. 将上面完成 onResume()Activity 保存到 mNewActivities 中;

      3. 调用 Looper.myQueue().addIdleHandler() 向消息队列添加一个 Idler 对象:

        • MessageQueue 对 Idle 消息会最后处理;

        • 这里的 Idler 对象内部会调用 ActivityManagerService.activityIdle()

    3. 如果启动失败,调用 ActivityManagerService.finishActivity()

  • 设置 mResumedActivity (最近启动的 Activity) 为当前 ActivityRecord

  • 调用 ActivityManagerService.addRecentTaskLocked() 将该 ActivityRecord.task 加入到最近任务列表;

  • 调用 completeResumeLocked(),发送消息处理上面的 Idler 对象,进而执行 ActivityManagerService.activityIdle():

    1. 释放 WakeLock 类型的 mLaunchingActivity,它能防止启动 Activity 过程中掉电;

    2. 调用 processStoppingActivitiesLocked() 得到因本次启动而被 pause 的 Activity

      1. 如果他们处于 finishing 状态,则调用其 onDestroy()

      2. 否则调用其 onStop()

    3. 如果当前处于启动过程中(启动 Home 页面时),发送 ACTION_BOOT_COMPLETED 广播;

  • 调用 checkReadyForSleepLocked() 检查调用过程中是否有休眠请求(比如用户按了电源键);

  • 调用 ActivityManagerService.startSetupActivityLocked() 启动系统设置向导页面(初次使用时);

ActivityStack::startPausingLocked():

  • 处理页面跳转前,ActivityManagerService 会首先调用本方法处理当前活动的页面;

  • 保存当前显示的 Activity,并设置其 stateActivityState.PAUSING

  • 调用当前 Activity 所在进程的 schedulePauseActivity(),内部调用 handlePauseActivity():

    1. 调用 ActivityonUserLeaving()onPause()

    2. 设置 ActivitystateActivityState.PAUSED

    3. 将暂停的 Activity 加入到 mStoppingActivities 中;

    4. mStoppingActivities 数目大于 3,调用 scheduleIdleLocked(),进而执行 ActivityManagerService.activityIdle()

    5. 调用 resumeTopActivityLocked() 启动目标 Activity

  • 调用 WakeLock 类型变量 mLaunchingActivity.acquire()

  • 调用当前 ActivitypauseKeyDispatchingLocked() 停止事件分发;

BroadcastReceiver 与 PendingResult 和 IIntentReceiver:

  • PendingResult 是 Android 2.3 新增的 BroadcastReceiver 内部类,用于异步处理广播消息:

    1. 先调用 BroadcastReceiver.goAsync() 得到一个 PendingResult 对象;

    2. PendingResult 对象放到工作线程处理,使得 onReceive() 不会阻塞;

    3. 工作线程执行完后,需要调用 PendingResult.finish() 来完成整个广播的处理流程;

  • IIntentReceiver 用于广播相关的跨进程 Binder 通信;

ContextImpl::registerReceiverInternal():

  • 如果没有传入 Handler 参数,调用 mMainThread.getHandler() 获取主线程 Handler

  • 如果传入的 mPackageInfo 参数非空,调用 mPackageInfo.getReceiverDispatcher() 得到 IIntentReceiver 对象;

  • 否则创建一个 LoadedApk.ReceiverDispatcher 对象;

  • 调用 ActivityManagerService.registerReceiver() 方法:

    1. 调用 getRecordForAppLocked()

    2 .检查 callerPackage 是否在 callearApp.pkgList 中,否则抛出 SecurityException

    1. 查询符合 IntentFilter 条件的 Sticky Intent,并返回第一个;

    2. 通过 mRegisteredReceiversIIntentReceiver 得到 ReceiverList 对象:

      • 一个 BroadcastReceiver 可设置多个过滤条件,也可以多次调用 registerReceiver() 使用不同条件,所以采用 ReceiverList 保存这种一对多关系;它继承自 ArrayList<BroadcastFilter>

      • ReceiverListreceiver 成员指向 IIntnetReceiver 对象;

      • ActivityManagerServicemRegisteredReceivers 保存所有 IIntentReceiver 和它对应的 ReceiverList

    3. 如果是首次调用,上面返回的 ReceiverList 对象为空,则创建该类型对象;

    4. 调用 IIntentReceiver.asBinder().linkToDeath() 监听广播接收者所在进程的死亡事件;

    5. 将上面的 ReceiverList 对象保存到 mRegisteredReceivers 中;

    6. 创建 IntentFilter 的子类 BroadcastFilter 对象,并调用 mReceiverResolver.addFilter()

ContextImpl::sendBroadcast():

内部调用 ActivityManagerService.broadcastIntentLocked():

  1. 如果是 Sticky 广播:

    1. 检查发送进程是否有 BROADCAST_STICKY 权限;

    2. 发送 Sticky 广播不能携带权限信息,也不能指定特定的接收对象;

    3. 将该 Intent 保存到 mStickyBrodcasts 中,如果存在则替换;

  2. 定义变量 receivers (用于保存所有广播接收者)和 registeredReceivers (用于保存动态注册的接收者);

  3. 如果通过 IntentComponent 指定了接收者,则从 PackageManagerService 查询接收者其信息;

  4. 通过 PackageManagerService 查询 Manifest 文件中声明的(静态)接收者,保存到 receivers

  5. 通过 ActivityManagerServicemReceiverResolver 对象查询所有动态注册的接收者,保存到 registeredReceivers

  6. 处理动态注册的接收者:

    1. 如果不是 Ordered 广播,直接创建 BroadcastRecord

    2. 如果没有被替换,保存到 mParallelBroadcasts

    3. 调用 ActivityManagerService.scheduleBroadcastsLocked() 发送广播;

  7. 将动态注册者 registeredReceivers 的成员合并到 receivers 中;

  8. 创建 BroadcastRecord 对象,如果没有替换,保存到 mOrderedBroadcasts (不区分是否 Ordered )中,并调用 ActivityManagerService.scheduleBroadcastsLocked()

ActivityManagerService::processNextBroadcast():

  • 调用 updateCpuStats() 更新 CPU 信息;

  • 处理 mParallelBroadcasts 中的所有 BroadcastRecord:

    1. 对于 BroadcastRecord 的每个 IIntentReceiver,调用 deliverToRegisteredReceiverLocked():

      1. 检查发送进程是否有 BroadcastFilter 要求的权限;

      2. 检查接收者是否有发送者要求的权限;

      3. 如果接收者所在进程不为空,则调用 ActivityThread.scheduleRegisteredReceiver()

      4. 否则调用 IIntentReceiver.performReceive()

    2. 调用 addBroadcastToHistoryLocked() 将处理过的 BroadcastRecord 加入 mHistoryBrodcast 供调试使用;

  • 处理 mOrderedBroadcasts 中的所有 BroadcastRecord

    1. 如果处于 pending 状态的广播所在进程 pid 不为空(还未处理完),则继续等待;

    2. 调用 updateOomAdjLocked() 更新 oom_adj;

    3. 判断处理广播是否超时,如果超时则调用 broadcastTimeoutLocked()

    4. 将该广播的处理结果传给设置了 resultTo 的接收者;

    5. 调用 cancelBroadcastTimeoutLocked() 取消超时处理;

    6. 调用 addBroadcastToHistoryLocked() 保存广播记录;

    7. mOrderedBroadcasts 中移除该广播;

  • 记录本广播第一次处理的时间,并设置超时;

  • 如果是动态接收者,直接调用前面的 deliverToRegisteredReceiverLocked() 处理;

  • 检查权限;如果当前 app 所在进程 crash 了,重新调用一次 scheduleBroadcastsLocked()

  • 设置 BroadcastRecordstatecurComponentcurReceiver

  • 调用 PackageManagerService.setPackageStoppedState() 将 Package Stopped 状态设为 fasle

  • 如果接收者所在进程已经启动,调用应用进程的 scheduleReceiver()

ActivityThread::scheduleRegisteredReceiverLocked():

内部调用 LoadedApk.ReceiverDispatcher.performReceive():

  1. 创建 Args 对象,它实现了 Runnable 接口;

  2. 调用 mActivityThread.post(args),进而执行 Args.run():

    1. 获得 ClassLoader 对象,并传递给 Intent

    2. 调用接收者的 onReceive() 方法;

    3. 调用 ActivityManagerService.finishReceiver()

      1. 调用 finishReceiverLocked() 判断是否需要继续调度后续广播;

      2. 如果需要继续调度,调用 processNextBroadcast()

  3. 如果 post() 调用失败则调用 Args.sendFinished(),传入参数为 ActivityManagerService

ActivityManagerService::updateLruProcessLocked():

  • 获取该 ProcessRecordmLruProcesses (其内部成员是按照 lruWeight 排序的) 中的索引 lrui;如果大于 0,则从 mLruProcesses 中移除该进程;

  • ProcessRecord.lastActivityTime 设置为当前时间戳;

  • 设置 ProcessRecord.lruWeight:

    1. 如果该进程包含 Activity,将 lruWeight 设置为 lastActivityTime (即刚刚设置的时间戳)

    2. 如果该进程包含 ContentProvider,将 lruWeight 设为 lastActivityTime - ProcessList.CONTENT_APP_IDLE_OFFSET

    3. 否则将 lruWeight 设为 lastActivityTime - ProcessList.EMPTY_APP_IDLE_OFFSET

  • mLruProcesses 最后一个元素开始,通过比较 lruWeight 值,将当前 ProcessRecord 调整到合适的位置;

  • 如果没找到合适的位置,则将该 ProcessRecord 添加为 mLruProcesses 第一个元素;

  • 如果 ProcessRecord.connections 不为空(即绑定了 Service),则调整所有绑定的 Service 所在进程的 lruWeight

  • 如果 ProcessRecord.conProviders 不为空,也更新他们所在进程的 lruWeight

ActivityManagerService::updateOomAdjLocked():

  • 调用 resumedActivityLock() 获取当前处于前台的 Activity,并得到对应的 ProcessRecord 对象;

  • 根据 ProcessList 中定义的不可见进程的 oom_adjHIDDEN_APP_MAX_ADJHIDDEN_APP_MIN_ADJ 确定等级数(numSlots);

  • 根据 mLruProcesses 成员个数计算平均落在每个等级的进程数(factor 值);

  • 从末尾遍历 mLruProcesses 中的每个成员:

    1. 调用 computeOomAdjLocked(),根据当前进程状态(是否前台、是否正在接收广播、是否正在运行服务等)以及 ProcessList 定义的 ADJ 阈值,更新进程的 curRawAdj 值;

    2. 统计电量;

    3. 调用 Process.setOomAdj() 更新该进程的 oom_adj

    4. 如果 ProcessRecordsetSchedGroupcurSchedGroup 不同,更新 setSchedGroupcurSchedGroup;并且:

      1. 如果 setSchedGroup 值为 THREAD_GROUP_BG_NONINTERACTIVE (后台非活动),调用 Process.killProcessQuiet() 杀掉该进程;

      2. 否则,调用 Process.setProcessGroup() 更新调度策略;

    5. 当某一个 adj 等级的进程处理数超过均值后,跳到下一等级处理;

    6. 如果后台进程数超过限制,调用 Process.killProcessQuiet() 杀掉;

  • 处理 ComponentCallback2 相关逻辑:

    • 它是 Android 4.0 新增的接口,用于通知应用进程进行内存清理;

    • 它内部定义了 onTrimMemory(int level) 接口,四大组件除了 BroadcastReceiver 以外均实现了该接口;

    • 如果 hidden 状态的进程数超过了 ProcessList.MAX_HIDDEN_APPS 值得一半,则调用 ActivityThread.scheduleTrimMemory()

  • 如果开启了 mAlwaysFinishActivities (始终销毁后台 Activity, Android 4.0 新增特性),调用 ActivityStack.destroyActivitiesLocked()

应用进程的 Crash 处理:

  • Zygote 在 fork 应用进程后会调用 Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler()) 处理未捕获异常;

  • UncaughtHandler 实现了 Thread.UncaughtExceptionHandler 接口,对未捕获异常的处理主要是 uncaughtException() 方法:

    1. 调用 ActivityManagerService.handleApplicationCrash() 处理应用 Crash:

      1. 调用 findAppProcess() 找到 Crash 进程的 ProcessRecord

      2. 通知 DropBoxManagerService 记录 Crash 日志;

      3. 生成 app.crashReport,并从 PakcageManagerService 查询 APP_ERROR 的处理进程,如果返回 false 则处理结束;

      4. mHandler 发送 SHOW_ERROR_MSG 消息,默认处理是弹框提示;

      5. 启动一个 actionAPP_ERRORActivity 处理错误报告;

    2. 调用 Process.killProcess()System.exit() 想方设法让进程结束 Java 世界;

  • Crash 进程退出后,ActivityManagerService 还会调用 appDiedLocked() 处理为它设置的 AppDeathRecipient

    1. 如果该进程有打开的对话框(crash、anr、wait 等),关闭它们;

    2. 调用 killServicesLocked() 处理该进程中驻留的 Service 或与其他进程 Service 建立的 Connection;

    3. 如果有客户端在等待该进程中的 ContentProvider,则尝试重启该进程;否则调用 removeDyingProvidersLocked()

    4. 调用 removeReceiverLocked() 移除该进程中的 BroadcastReceiver

    5. 如果需要重启进程,则调用 startProcessLocked()

    6. mLruProcesses 中移除该进程对应的 ProcessRecord

    7. 遍历 mLruProcesses,找出 oom_adj 不小于 ProcessList.HIDDEN_APP_MIN_ADJ 的进程,并加入 mProcessesToGc

    8. 发送 GC_BACKGROUND_PROCESSES_MSGmHandler,进而调用应用进程的 scheduleLowMemory()processInBackground()


参考:

《深入理解 Android: 卷 II》