深入理解 Android:ActivityManagerService
Linux 设置进程优先级函数:
int setpriority(int which, int who, int prio);
参数
which
和who
联合使用:which
为PRIO_PROGRESS
时,who
代表进程;which
为PRIO_PGROUP
时,who
代表进程组;which
为PRIO_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.Monitor
和BatteryStatsImpl.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()
方法中:调用
startSystemUi()
,启动系统 UI;调用 Battery、Network 等模块的
systemReady()
;启动
Watchdog
;
ActivityManagerService::main():
创建
AThread
线程对象:设置线程优先级为
THREAD_PRIORITY_FOREGROUND
;创建
ActivityManagerServive
对象:创建 /data/system/ 目录;
创建
BatteryStatsService
和UsageStatsService
;读取 OpenGL、及资源配置信息
Configuration
;读取并解析 /proc/stat 文件中的 CPU 和内存信息、/data/system/packages-compact.xml 文件中的需要考虑屏幕尺寸的 APK 信息;
调用
Watchdog.getInstance().addMonitor()
将自己加入监控;创建
mProcessStatsThread
线程,用于定时更新系统信息,和mProcessStats
交互;
调用
ActivityThread.systemMain()
方法返回ActivityThread
对象:调用
HardwareRenderer.disable(true)
禁用硬件渲染;创建
ActivityThread
对象,并调用其attach(true)
方法,
调用
ActivityThread.getSystemContext()
得到Context
对象;创建用于管理
Activity
启动和调度的核心类ActivityStack
对象;调用
BatteryStatsService
和UsageStatsService
的publish()
方法;调用
ActivityManagerService.startRunning()
,主要调用systemReady()
;
ActivityThread:
ActivityThread
代表一个应用进程的主线程(其main
方法由所在进程的主线程执行),其职责为调度和执行运行在主线程的四大组件;通过
ActivityThread
可以把 Android 系统提供的组件之间的交互机制和接口(如Context
)也扩展到system_server
中使用;实际上system_server
可以看作一个特殊的应用进程(framework-res.apk 和 SettingsProvider.apk 都运行在该进程中);attach(true)
对系统进程的处理:创建
Instrumentation
工具类对象,它通过 AndroidManifest.xml 中的标签描述,用于监控与其他组件的交互;创建
ContextImpl
对象,并调用其init()
方法;Context
是一个可以操作Application
及其中四大组件的接口;调用
Instrumentation.newApplication()
创建Application
对象;它是可以看作一个四大组件的容器,ActivityManagerService
内部通过mAllApplications
保存所有Application
;调用
Application.onCreate()
;调用
ViewRootImpl.addConfigCallback()
,响应onConfigurationChanged()
、onLowMemory()
、onTrimMemory()
等方法;
getSystemContext()
:调用
ContextImpl.createSystemContext()
创建ContextImpl
对象;创建
LoadedApk
对象,传入的package
参数为"android"
,即代表 framework-res.apk,相当于读取系统资源;调用
ContextImpl.init()
方法,并传入上面的LoadedApk
对象,相当于加载系统资源;调用
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
需要主题,Service
和Application
不需要主题,所以Service
/Application
直接继承于ContextWrapper
类;总
Context
实例个数 =Service
个数 +Activity
个数 + 1(Application
对应的Context
实例);
ActivityManagerService::setSystemProcess():
调用
ServiceManager.addService()
注册几个服务:ActivityManagerService
;MemBinder
:用于打印内存信息;GraphicsBinder
:用于输出应用进程使用硬件显示加速的信息,Android 4.0 新增的服务;CpuBinder
:CPU 信息;PermissionController
:权限管理服务;
调用
context.getPackageManager().getApplicationInfo()
查询包名为android
的ApplicationInfo
对象;调用
ActivityThread.installSystemApplicationInfo()
注册上面查询到的ApplicationInfo
对象:调用
ActivityThread.getSystemContext()
返回之前初始化过的Context
对象;调用
context.init(new LoadedApk())
再次初始化;注意之前初始化传入的最后一个参数为null
,这次传入的是上面查询到的包名为android
的ApplicationInfo
对象;创建
Profiler
对象,用于性能统计;
调用
ActivityManagerService.newProcessRecordLocked()
创建用于保存进程信息的ProcessRecord
对象:获取
BatteryStatsService
对象,并创建一个耗电量统计项;创建
ProcessRecord
对象:初始化
BatteryStatsService
、ApplicationInfo
、ProcessName
、IApplicationThread
等成员变量;初始化
maxAdj
、hiddenAdj
、curRawAdj
、curAdj
等和进程调度和内存管理相关的变量;对于
system_server
进程,ActivityManagerService
还进行了特殊处理:将其
persisten
设为true
,被 kill 后会重建;pid
设为MY_PID
,即system_server
进程号;processName
设置为system
;maxAdj
设置为最大值SYSTEM_ADJ
;
ActivityManagerService
内部通过mProcessNames
保存所有进程名,调用put()
保存上面创建的ProcessRecord
;调用
ActivityManagerService.updateLruProcessLocked()
,根据系统当前状态调整进程调度优先级和 OOM_Adj;
ActivityManagerService::installSystemProviders():
从
mProcessNames
取出 processName 为system
且 uid 为SYSTEM_UID
的ProcessRecord
,即system_server
对应的进程;调用
ActivityManagerService.generateApplicationProvidersLocked()
返回List<ProviderInfo>
对象:根据进程名和 uid,调用
PackageManagerService.queryContentProviders()
查询符合条件的List<ProviderIndo>
;遍历
List<ProviderInfo>
根据包名和ApplicationInfo
查询(如果不存在则构造)并保存ContentProviderRecord
;调用
ensurePackageDexOpt()
执行 dex 优化;
从
providers
中去除非系统 Provider;调用
ActivityThread.installSystemProviders()
,将providers
安装到system_server
进程:调用
installProvider()
得到一个IContentProvider
对象;找到
Provider
对应的Context
,并调用Context.getClassLoader()
、通过反射生成ContentProvider
实例;调用
IContentProvider.asBinder.linkToDeath()
;创建
ProviderClientRecord
对象,并保存到mLocalProviders
;
创建
ContentProviderRefCount
对象对ContentProvider
进行引用计数控制,引用数为 0 则从系统注销;调用
ActivityManagerService.publishContentProviders()
;根据调用者的 pid 找到对应的
ProcessRecord
;从
ProcessRecord
的pubProviders
中找到对应的ContentProviderRecord
,如果找到则以 authority 为 key 保存;移除
mLaunchingProviders
中保存的处于启动状态的 Provider,并调用notifyAll()
通知等待它们启动的进程;调用
updateOomAdjLocked()
调整 oom_adj;
创建
CoreSettingsObserver
对象,监听 Settings 数据库 secure 表的变化;调用
UsageStatsService.monitorPackages()
;
ContentProvider:
ContentProvider
本身只是一个容器,跨进程调用的支持是通过Transport
实现的;Transpor
从Binder
的子类ContentProviderNative
派生;ContentProviderNative
实现了IContentProvider
接口,其内部类ContentProviderProxy
供客户端使用;ContentProvider
的getIContentProvider()
返回Transport
对象;系统提供 ComponentName 和 authority 两种方式找到
ContentProvider
,所以ActivityManagerService
存在对应的两个变量:mProvidersByClass
和mProvidersByName
;
ContentProviderRecord:
ContentProviderRecord
继承自ContentProviderHolder
,内部保存了ProviderInfo
、该 Provider 驻留进程的ProcessRecord
、以及使用该 Provider 的客户端所在进程的ProcessRecord
;ActivityManagerService
的mProviderByClass
成员和ProcessRecord
的pubProviders
成员均以 ComponentName 为 key 来保存对应的ContentProviderRecord
;
ProviderClientRecord:
ProviderClientRecord
是ActivityThread
提供的用于保存ContentProvider
信息的结构;内部主要成员:
mLocalProvider
用于保存ContentProvider
对象;mProvider
用于保存IContentProvider
对象(即Transport
对象);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()
:调用
startSystemUi()
,启动SystemUIService
(实现了系统状态栏);调用 Battery、Network 等其他模块的
systemReady()
,启动Watchdog
;
启动
persistent
为1
的 APK 进程(排除掉包名为android
的 framework-res.apk,因为它之前已经被启动);调用
startHomeActivityLocked()
启动 Home 界面;调用
finishBooting()
:注册 PACKAGE_RESTART 的
BroadcastReceiver
处理包重启;启动那些等待启动的进程;
每隔 15 分钟检查一次各应用进程用电情况,杀掉使用
Wakelock
时间过长的进程;调用
SytemProperties.set()
设置sys.boot_completed
属性为1
;发送
ACTION_BOOT_COMPLETED
广播;
ActivityStack、ActivityRecord、TaskRecord:
ActivityRecord
的task
变量指向该Activity
所在的 Task;state
变量表示Activity
状态;ActivityStack
的mMainStack
表示是否是主 Stack,由于目前只有一个ActivityStack
,所以该变量值为true
;ActivityStack
的mHistory
成员是ArrayList
类型,用于保存系统中所有ActivityRecord
;ActivityStack
没有变量保存所有TaskRecord
;
ActivityStack::startActivityMayWait():
从
PackageManagerService
查询匹配传入的Intent
的ActivityInfo
;获取
Binder
调用方 uid 和 pid;调用
startActivityLocked()
返回启动结果res
:如果调用者不为空,则调用
ActivityManagerService.getRecordForAppLocked()
得到它的ProcessRecord
;如果ProcessRecord
为空(该进程没有在ActivityManagerService
注册),则返回START_PERMISSION_DENIED
错误;声明两个
ActivityRecord
类型的变量sourceRecord
(启动目标Activity
的那个Activity
)和resultRecord
(接收启动结果的Activity
,即处理onActivityResult
的Activity
);一般情况下,二者指向同一个Activity
;读取
Intent
的flags
,检查err
是否为0
,检查权限信息;为
ActivityManagerService
设置一个IActivityController
类型的监听者(主要用于 Monkey 测试);创建
ActivityRecord
对象;调用
ActivityManagerService.checkAppSwitchAllowedLocked()
检查调用建成是否有权限切换应用,如果没有权限,则保存到ActivityManagerService
的mPendingActivityLaunches
变量;调用
ActivityManagerService.doPendingActivityLaunchesLocked()
启动处于 pending 状态的Activity
;调用
startActivityUncheckedLocked()
完成本次启动请求;
如果
Configuration
有变化,调用ActivityManagerService.updateConfigurationLocked()
;处理启动结果;
ActivityStack::startActivityUncheckedLocked():
判断是否需要创建新的 Task,以下两种情况需要在
Intent
的flags
附加Intent.FLAG_ACTIVITY_NEW_TASK
:发起请求的
sourceRecord
为空,或者为单例(独占一个 Task);待启动的
Activity
设置了SingleTask
或SingleInstance
;
调用
findTaskLocked()
和findActivityLocked()
从mHistory
中得到ActivityRecord
类型的taskTop
对象;调用
topRunningNonDelayedActivityLocked()
判断是否处于栈顶,决定是否创建新的Activity
;为
ActivityRecord
设置TaskRecord
;调用
ActivityManagerService.grantUriPermissionFromIntentLocked()
授权;调用
stackActivityLocked()
完成启动:如果不是新 Task,则从
mHistory
中找到对应的ActivityRecord
位置;否则,将其添加到mHistory
末尾;设置
ActivityRecord
的inHistory
为true
,表示已经存在与mHistory
中;判断是否显示
Activity
切换动画,需要与WindowManagerService
交互;调用
resumeTopActivityLocked()
;
ActivityStack::resumeTopActivityLocked():
调用
topRunningActivityLocked()
从mHistory
中找到第一个需要启动的ActivityRecord
,如果没有则启动 Home 页面;将该
ActivityRecord
从mStoppingActivities
、mGoingToSleepActivities
和mWaitingVisibleActivities
中移除;如果当前正在 pause 一个
Activity
,需要先等待 pause 完毕,然后系统重新调用resumeTopActivityLocked()
;mResumedActivity
指向上次启动的Activity
,即当前显示的Activity
;如果它不为空,调用startPausingLocked()
中止,并返回;如果传入的
prev
页面不为空,则需要通知WindowManagerService
进行与页面切换相关的工作(停止绘制等);如果该
ActivityRecord
对应的进程已存在,则只需要重启该Activity
;如果不存在,通知
WindowManagerService
显示启动页面,并调用startSpecificActivityLocked()
:调用
ActivityManagerService.getProcessRecordLocked()
根据进程名和uid查找进程;设置启动时间等信息;
如果该进程存在,并已经向
ActivityManagerService
注册,调用realStartActivityLocked()
启动目标Activity
;如果该进程不存在,调用
ActivityManagerService.satrtProcessLocked()
启动进程;
ActivityManagerService::startProcessLocked():
处理
FLAG_FROM_BACKGROUND
标志和BadProcess
:一个进程如果连续崩溃超过两次,
ActivityManagerService
会将其ProcessRecord
加入mBadProcesses
;由于进程崩溃会弹框,所以一般禁止启动处于后台的 BadProcess;但如果是用户触发的(比如点击 button 跳到后台页面),则会把该进程从
mBadProcesses
移除,给它“重新做人”的机会;
创建
ProcessRecord
对象,并保存到mProcessNames
;从
mProcessesOnHold
移除该ProcessRecord
,它用于保存在系统还未准备好就发送启动请求的ProcessRecord
;更新 CPU 信息,从
PackageManagerService
查询该进程的 gid;调用
Process.start()
,让 Zygote 派生子进程,该子进程执行ActivityThread.main()
:调用
Process.setArgV0()
设置进程名为pre-initialized
;创建
ActivityThread
对象;调用
ActivityThread.attach(false)
处理应用进程:设置在
DropBoxManagerService
日志系统中看到的进程名为pre-initialized
;调用
RuntimeInit.setApplicationObject(mAppThread.asBinder())
;调用
ActivityManagerService.attachApplicationLocked(mAppThread)
;
执行电量统计;
如果该进程为
persistent
,通知Watchdog
;以 pid 为 key,将该进程的
ProcessRecord
保存到mPidsSelfLocked
;发送
PROC_START_TIMEOUT_MSG
消息,如果新进程 10s 没有和ActivityManagerService
交互,则认为新进程启动失败;
ActivityManagerService::attachApplicationLocked():
根据
pid
查找对应的ProcessRecord
;如果为空(未向ActivityManagerService
注册):如果
pid
大于 0 且不是system_server
进程,调用Process.killProcessQuiet()
杀掉该进程;否则调用
IApplicationThread.sheduleExit()
退出;
如果该
ProcessRecord.thread
对象不为空,表示该进程为旧的未被杀死的进程,系统不会重用,而是调用handleAppDiedLocked()
处理;创建应用死亡讣告对象
AppDeathRecipient
,并调用thread.asBinder().linkToDeath()
;设置该进程的调度优先级以及 oom_adj 相关变量;
通过
PackageManagerService
查询运行在该进程中的ContentProvider
对象;对相关 Package 进行 Dex 优化;
调用
ApplicationThread.bindApplication()
:调用
ServiceManager.initServiceCache()
保存ActivityManagerService
传递过来的Service
信息;调用
setCoreSettings()
向主线程消息队列添加SET_CORE_SETTINGS
消息;创建
AppBindData
对象,用于保存processName
、appInfo
等参数信息;初始化性能统计对象
Profiler
;调用
Process.setArgV0()
和DdmHandleAppName.setAppname()
设置正式进程名;对于 persistent 进程,在低内存设备上,调用
HardwareRenderer.disable(false)
禁用硬件加速;初始化
AsyncTask
的线程池;设置时区、语言、资源、兼容模式;
根据传过来的
ApplicationInfo
创建一个对应的LoadedApk
对象;StrictMode 和 DebugMode 相关处理;
设置 HTTP 代理信息;
如果 Package 声明了
FLAG_LARGE_HEAP
,调用VMRuntime.getRuntime().clearGrowthLimit()
清除内存限制;根据
LoadedApk
对象,并利用反射,生成 Manifest 文件中声明的Application
对象;用mInitialApplication
保存该进程中创建的第一个Application
;调用
installContentProviders()
安装本 Package 下的ContentProvider
;调用
mInstrumentation.callApplicationOnCreate()
执行Application
对象的onCreate()
方法;
调用
updateLruProcessLocked()
;调用
ActivityStack.topRunningActivitylLocked()
获取ActivityStack
中的第一个需要运行的ActivityRecord
;根据
processName
和uid
确定该ActivityRecord
和目标进程有关,否则调用ActivityStack.ensureActivitiesVisibleLocked()
处理;调用
ActivityStack.realStartActivityLocked()
启动该ActivityRecord
;对于
mPendingServices
中处于 pending 状态的ServiceRecord
:如果根据
processName
和uid
判断和目标进程无关,则不作处理;否则调用
realStartService()
启动该ServiceRecord
;
如果上面几个组件初始化有错误,调用
handleAppDiedLocked()
处理;调用
updateOomAdjLocked()
根据该进程中的组建情况调节 oom_adj 值(组件越多越不易被杀死回收);
ActivityStack::realStartActivityLocked():
调用
ActivityManagerService.updateConfigurationLocked()
处理 Config 变化;将
ActivityRecord
加入到ProcessRecord
的activities
中保存;调用
ActivityManagerService.updateLruProcessLocked()
更新进程优先级;调用
ProcessRecord.thread
(ActivityThread
类型)的scheduleLaunchActivity()
通知应用的主进程启动Activity
:调用
performLaunchActivity()
:通过反射机制创建目标
Activity
对象;调用
Activity
的onCreate()
和onStart()
方法;
调用
handleResumeActivity()
:调用
performResumeActivity()
执行Activity
的onResume()
方法;将上面完成
onResume()
的Activity
保存到mNewActivities
中;调用
Looper.myQueue().addIdleHandler()
向消息队列添加一个Idler
对象:MessageQueue
对 Idle 消息会最后处理;这里的
Idler
对象内部会调用ActivityManagerService.activityIdle()
;
如果启动失败,调用
ActivityManagerService.finishActivity()
;
设置
mResumedActivity
(最近启动的Activity
) 为当前ActivityRecord
;调用
ActivityManagerService.addRecentTaskLocked()
将该ActivityRecord.task
加入到最近任务列表;调用
completeResumeLocked()
,发送消息处理上面的Idler
对象,进而执行ActivityManagerService.activityIdle()
:释放
WakeLock
类型的mLaunchingActivity
,它能防止启动Activity
过程中掉电;调用
processStoppingActivitiesLocked()
得到因本次启动而被 pause 的Activity
:如果他们处于 finishing 状态,则调用其
onDestroy()
;否则调用其
onStop()
;如果当前处于启动过程中(启动 Home 页面时),发送
ACTION_BOOT_COMPLETED
广播;
调用
checkReadyForSleepLocked()
检查调用过程中是否有休眠请求(比如用户按了电源键);调用
ActivityManagerService.startSetupActivityLocked()
启动系统设置向导页面(初次使用时);
ActivityStack::startPausingLocked():
处理页面跳转前,
ActivityManagerService
会首先调用本方法处理当前活动的页面;保存当前显示的
Activity
,并设置其state
为ActivityState.PAUSING
;调用当前
Activity
所在进程的schedulePauseActivity()
,内部调用handlePauseActivity()
:调用
Activity
的onUserLeaving()
和onPause()
;设置
Activity
的state
为ActivityState.PAUSED
;将暂停的
Activity
加入到mStoppingActivities
中;当
mStoppingActivities
数目大于 3,调用scheduleIdleLocked()
,进而执行ActivityManagerService.activityIdle()
;调用
resumeTopActivityLocked()
启动目标Activity
;
调用
WakeLock
类型变量mLaunchingActivity.acquire()
;调用当前
Activity
的pauseKeyDispatchingLocked()
停止事件分发;
BroadcastReceiver 与 PendingResult 和 IIntentReceiver:
PendingResult
是 Android 2.3 新增的BroadcastReceiver
内部类,用于异步处理广播消息:先调用
BroadcastReceiver.goAsync()
得到一个PendingResult
对象;将
PendingResult
对象放到工作线程处理,使得onReceive()
不会阻塞;工作线程执行完后,需要调用
PendingResult.finish()
来完成整个广播的处理流程;
IIntentReceiver
用于广播相关的跨进程 Binder 通信;
ContextImpl::registerReceiverInternal():
如果没有传入
Handler
参数,调用mMainThread.getHandler()
获取主线程Handler
;如果传入的
mPackageInfo
参数非空,调用mPackageInfo.getReceiverDispatcher()
得到IIntentReceiver
对象;否则创建一个
LoadedApk.ReceiverDispatcher
对象;调用
ActivityManagerService.registerReceiver()
方法:- 调用
getRecordForAppLocked()
;
2 .检查
callerPackage
是否在callearApp.pkgList
中,否则抛出SecurityException
;查询符合
IntentFilter
条件的 StickyIntent
,并返回第一个;通过
mRegisteredReceivers
和IIntentReceiver
得到ReceiverList
对象:一个
BroadcastReceiver
可设置多个过滤条件,也可以多次调用registerReceiver()
使用不同条件,所以采用ReceiverList
保存这种一对多关系;它继承自ArrayList<BroadcastFilter>
;ReceiverList
的receiver
成员指向IIntnetReceiver
对象;ActivityManagerService
用mRegisteredReceivers
保存所有IIntentReceiver
和它对应的ReceiverList
;
如果是首次调用,上面返回的
ReceiverList
对象为空,则创建该类型对象;调用
IIntentReceiver.asBinder().linkToDeath()
监听广播接收者所在进程的死亡事件;将上面的
ReceiverList
对象保存到mRegisteredReceivers
中;创建
IntentFilter
的子类BroadcastFilter
对象,并调用mReceiverResolver.addFilter()
;
- 调用
ContextImpl::sendBroadcast():
内部调用 ActivityManagerService.broadcastIntentLocked()
:
如果是 Sticky 广播:
检查发送进程是否有
BROADCAST_STICKY
权限;发送 Sticky 广播不能携带权限信息,也不能指定特定的接收对象;
将该
Intent
保存到mStickyBrodcasts
中,如果存在则替换;
定义变量
receivers
(用于保存所有广播接收者)和registeredReceivers
(用于保存动态注册的接收者);如果通过
Intent
的Component
指定了接收者,则从PackageManagerService
查询接收者其信息;通过
PackageManagerService
查询 Manifest 文件中声明的(静态)接收者,保存到receivers
;通过
ActivityManagerService
的mReceiverResolver
对象查询所有动态注册的接收者,保存到registeredReceivers
;处理动态注册的接收者:
如果不是 Ordered 广播,直接创建
BroadcastRecord
;如果没有被替换,保存到
mParallelBroadcasts
;调用
ActivityManagerService.scheduleBroadcastsLocked()
发送广播;
将动态注册者
registeredReceivers
的成员合并到receivers
中;创建
BroadcastRecord
对象,如果没有替换,保存到mOrderedBroadcasts
(不区分是否 Ordered )中,并调用ActivityManagerService.scheduleBroadcastsLocked()
;
ActivityManagerService::processNextBroadcast():
调用
updateCpuStats()
更新 CPU 信息;处理
mParallelBroadcasts
中的所有BroadcastRecord
:对于
BroadcastRecord
的每个IIntentReceiver
,调用deliverToRegisteredReceiverLocked()
:检查发送进程是否有
BroadcastFilter
要求的权限;检查接收者是否有发送者要求的权限;
如果接收者所在进程不为空,则调用
ActivityThread.scheduleRegisteredReceiver()
;否则调用
IIntentReceiver.performReceive()
;
调用
addBroadcastToHistoryLocked()
将处理过的BroadcastRecord
加入mHistoryBrodcast
供调试使用;
处理
mOrderedBroadcasts
中的所有BroadcastRecord
:如果处于 pending 状态的广播所在进程 pid 不为空(还未处理完),则继续等待;
调用
updateOomAdjLocked()
更新 oom_adj;判断处理广播是否超时,如果超时则调用
broadcastTimeoutLocked()
;将该广播的处理结果传给设置了
resultTo
的接收者;调用
cancelBroadcastTimeoutLocked()
取消超时处理;调用
addBroadcastToHistoryLocked()
保存广播记录;从
mOrderedBroadcasts
中移除该广播;
记录本广播第一次处理的时间,并设置超时;
如果是动态接收者,直接调用前面的
deliverToRegisteredReceiverLocked()
处理;检查权限;如果当前 app 所在进程 crash 了,重新调用一次
scheduleBroadcastsLocked()
;设置
BroadcastRecord
的state
、curComponent
、curReceiver
;调用
PackageManagerService.setPackageStoppedState()
将 Package Stopped 状态设为fasle
;如果接收者所在进程已经启动,调用应用进程的
scheduleReceiver()
;
ActivityThread::scheduleRegisteredReceiverLocked():
内部调用 LoadedApk.ReceiverDispatcher.performReceive()
:
创建
Args
对象,它实现了Runnable
接口;调用
mActivityThread.post(args)
,进而执行Args.run()
:获得
ClassLoader
对象,并传递给Intent
;调用接收者的
onReceive()
方法;调用
ActivityManagerService.finishReceiver()
:调用
finishReceiverLocked()
判断是否需要继续调度后续广播;如果需要继续调度,调用
processNextBroadcast()
;
如果
post()
调用失败则调用Args.sendFinished()
,传入参数为ActivityManagerService
;
ActivityManagerService::updateLruProcessLocked():
获取该
ProcessRecord
在mLruProcesses
(其内部成员是按照lruWeight
排序的) 中的索引lrui
;如果大于 0,则从mLruProcesses
中移除该进程;将
ProcessRecord.lastActivityTime
设置为当前时间戳;设置
ProcessRecord.lruWeight
:如果该进程包含
Activity
,将lruWeight
设置为lastActivityTime
(即刚刚设置的时间戳)如果该进程包含
ContentProvider
,将lruWeight
设为lastActivityTime - ProcessList.CONTENT_APP_IDLE_OFFSET
;否则将
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_adj
值HIDDEN_APP_MAX_ADJ
和HIDDEN_APP_MIN_ADJ
确定等级数(numSlots
);根据
mLruProcesses
成员个数计算平均落在每个等级的进程数(factor
值);从末尾遍历
mLruProcesses
中的每个成员:调用
computeOomAdjLocked()
,根据当前进程状态(是否前台、是否正在接收广播、是否正在运行服务等)以及ProcessList
定义的 ADJ 阈值,更新进程的curRawAdj
值;统计电量;
调用
Process.setOomAdj()
更新该进程的oom_adj
;如果
ProcessRecord
的setSchedGroup
和curSchedGroup
不同,更新setSchedGroup
为curSchedGroup
;并且:如果
setSchedGroup
值为THREAD_GROUP_BG_NONINTERACTIVE
(后台非活动),调用Process.killProcessQuiet()
杀掉该进程;否则,调用
Process.setProcessGroup()
更新调度策略;
当某一个 adj 等级的进程处理数超过均值后,跳到下一等级处理;
如果后台进程数超过限制,调用
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()
方法:调用
ActivityManagerService.handleApplicationCrash()
处理应用 Crash:调用
findAppProcess()
找到 Crash 进程的ProcessRecord
;通知
DropBoxManagerService
记录 Crash 日志;生成
app.crashReport
,并从PakcageManagerService
查询APP_ERROR
的处理进程,如果返回false
则处理结束;给
mHandler
发送SHOW_ERROR_MSG
消息,默认处理是弹框提示;启动一个
action
是APP_ERROR
的Activity
处理错误报告;
调用
Process.killProcess()
和System.exit()
想方设法让进程结束 Java 世界;
Crash 进程退出后,
ActivityManagerService
还会调用appDiedLocked()
处理为它设置的AppDeathRecipient
:如果该进程有打开的对话框(crash、anr、wait 等),关闭它们;
调用
killServicesLocked()
处理该进程中驻留的Service
或与其他进程Service
建立的 Connection;如果有客户端在等待该进程中的
ContentProvider
,则尝试重启该进程;否则调用removeDyingProvidersLocked()
;调用
removeReceiverLocked()
移除该进程中的BroadcastReceiver
;如果需要重启进程,则调用
startProcessLocked()
;从
mLruProcesses
中移除该进程对应的ProcessRecord
;遍历
mLruProcesses
,找出 oom_adj 不小于ProcessList.HIDDEN_APP_MIN_ADJ
的进程,并加入mProcessesToGc
;发送
GC_BACKGROUND_PROCESSES_MSG
给mHandler
,进而调用应用进程的scheduleLowMemory()
和processInBackground()
;
参考: