Adnroid 四大组件的工作过程

四大组件的运行状态

  • Activity 是一种展示型组件,用于向用户直接地展示一个界面,并且可以接收用户的输入信息从而进行交互。
  • Service 是一种计算型组件,用于后台执行一系列计算任务。
  • BroadcastReceiver 是一种消息型组件,用于在不同的组件乃至不同的应用之间传递消息。
  • ContentProvider 是一种数据共享型组件,用于向其他组件乃至其他应用共享数据。

根 Activity 的启动过程

根 Activity 的启动过程一般情况下也可以理解为应用程序的启动过程。

Launcher 请求 AMS 过程

当点击应用程序的快捷图标时,会调用 Launcher.java 的 startActivitySafely 方法。

  • startActivitySafely
  • 先将 Flag 设置为 Intent.FLAG_ACTIVITY_NEY_TASK,使根 Activity 在新的任务栈中启动。
  • 其次,调用 startActivity 方法,此方法在 Activity.java 中实现。
  • startActivity
    在 startActivity 方法中会调用 startActivityForResult 方法。
  • startActivityForResult
    其中,调用 Instrumentation(主要用来监控应用程序和系统的交互) 的 execStartActivity 方法。
  • execStartActivity
    调用 ActivityManager.java 的 getService 方法获取 AMS 的代理对象,接着调用它的 startActivity 方法。
  • Android 8.0 之前,通过ActivityManagerNative 的 getDefault 来获取 AMS 的代理对象。
  • 现在,这个逻辑封装到了 ActivityManager 中。

AMS 到 ApplicationThread 的调用过程

Launcher 请求 AMS 后,代码逻辑已经进入 AMS 中。

  • AMS 的 startActivity
  • 其中,return startActivityAsUser()。
  • startActivityAsUser
  • 判断调用者进程是否被隔离。
  • 根据调用者的 UserId,检查其是否有权限。
  • 调用 ActivityStarter(7.0新加入的类,它是加载 Activity 的控制类,会收集所有的逻辑来决定如何将 Intent 和 Flag 转换 为 Activity,并将 Activity 和 Task 以及 Stack 相关联) 的 startActivityMayWait。
  • startActivityMayWait
  • 其中,调用了 startActivityLocked 方法。
  • startActivityLocked
  • 其中,调用了 startActivity 方法。
  • startActivity
  • 判断 IApplicationThread 类型的 caller(它指的是 Launcher 所在的应用程序进程的 ApplicationThread 对象) 是否为 null。
  • 调用 AMS 的 getRecordForAppLocked 方法得到代表 Launcher 进程的 callerApp 对象(它是 ProcessRecord 类型的,ProcessRecord 用于描述一个应用程序进程)。
  • 创建即将要启动的 Activity 的描述类 ActivityRecord(它用来记录一个 Activity 的所有信息),并将它赋值给 ActivityRecord[] 类型的 outActivity,这个 outActivity 会作为接下来的 startActivity 方法的参数传递下去。
  • startActivity 方法紧接着调用了 startActivityUnchecked 方法。
  • startActivityUnchecked
    主要处理与栈管理相关的逻辑。
  • 执行 setTaskFromReuseOrCreateNewTask 方法,其内部会创建一个新的 TaskRecord ,用来描述一个 Activity 任务栈。
  • 调用 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLocked 方法。
  • resumeFocusedStackTopActivityLocked
  • 调用 ActivityStack 的 topRunningActivityLocked 方法获取要启动的 Activity 所在栈的栈顶的不是处于停止状态的 ActivityRecord。
  • 调用 ActivityStack 的 resumeTopActivityUncheckedLocked 方法。
  • resumeTopActivityUncheckedLocked
  • 调用 ActivityStack 的 resumeTopActivityInnerLocked 方法。
  • resumeTopActivityInnerLocked
  • 调用 ActivityStackSupervisor 的 startSpecificActivityLocked 方法。
  • startSpecificActivityLocked
  • 获取即将启动的 Activity 所在的应用程序进程。
  • 判断要启动的 Activity 所在的应用程序进程如果已经运行,则调用 realStartActivityLocked 方法。
  • realStartActivityLocked
  • 其中的 app.thread 指的是 IApplicationThread,它的实现是 ActivityThread 的内部类 ApplicationThread(它继承了 IAppliactionThread.Stub)。
  • app 指的是传入的要启动的 Activity 所在的应用程序进程。
  • 因此,app.thread.scheduleLaunchActivity() 指的就是要在目标应用程序进程启动 Activity。
  • 当前代码逻辑运行在 AMS 所在的进程(SystemServer 进程)中,通过 ApplicationThread 来与应用程序进程进行 Binder 通信,换句话说,ApplicationThread 是 AMS 所在进程和应用程序进程的通信桥梁。

ActivityThread 启动 Activity的过程


Activity 的工作过程

Activity 的 startActivity() 有好几种重载方式,但最终都会调用 startActivityForResult()。

  • startActivityForResult()
    调用 Instrumentation 的 execStartActivity()。
    mMainThread.getApplicationThread() 这个参数的类型是 ApplicationThread(是 ActivityThread 的一个内部类)。
  • execStartActivity()
    启动 Activity 真正的实现由 ActivityManagerNative.getDefault()(IActivityManager 类型的 Binder 对象,具体实现是 ActivityManagerService) 的 startActivity() 完成。
    checkStartActivityResult() 的作用是检查启动 Activity 的结果。
  • startActivity()
    由于 ActivityManagerNative.getDefault() 实际上是 AMS,因此启动过程转移到了 AMS 中,来看 AMS 的 startActivity()。
    将启动过程转移到了 ActivityStackSupervisor 的 startActivityMayWait(),又经过一些列的调用过程,又将启动过程转移到了 ActivityStack 的 resumeTopActivitiesLocked()。
  • resumeTopActivitiesLocked()
    调用了 resumeTopActivityInnerLocked() –> ActivityStackSupervisor 的 startSpecificActivityLocked() –> realStartActivityLocked()。
  • realStartActivityLocked()
    一段重要代码,app.thread.scheduleLaunchActivity()。其中 app.thread 的类型位 IApplicationThread。
  • IApplicationThread
    它继承了 IInterface 接口,是一个 Binder 类型的接口。其实现者完成了大量和 Activity 以及 Service 的启动/停止相关功能。
    实现者是 ActivityThread 中的内部类 AppliactionThread。
  • AppliactionThread
    它继承了 ApplicationThreadNative。而 ApplicationThreadNative 继承了 Binder 并实现了 IApplicationThread 接口,其内部还有一个 ApplicationThreadProxy 类。
    ApplicationThreadNative 是 IApplcationThread 的实现者,由于 ApplicationThreadNative 被系统定义为抽象类,所以 AppliactionThread 就成了 IApplicationThread 最终的实现者。
    到此,Activity 的启动过程最终回到了 AppliactionThread 中,AppliactionThread 通过 scheduleLaunchActivity() 来启动 Activity。
  • scheduleLaunchActivity()
    会发送一个启动 Activity 的消息交由 Handler(名字叫 H) 处理。
  • H
    从对 “LAUNCH_ACTIVITY” 这个消息的处理可知道,启动过程由 ActivityThread 的 handleLaunchActivity() 来实现,其又调用 performLaunchActivity()。
  • performLaunchActivity()
    最终完成了 Activity 对象的创建和启动过程,并且 ActivityThread 通过 handleResumeActivity() 来调用被启动 Activity 的 onResume 这一生命周期方法。它主要完成了如下几件事:
  • 从 ActivityClientRecord 中获取待启动的 Activity 的组件信息
  • 通过 Instrumentation 的 newActivity() 使用类加载器创建 Activity 对象
  • 通过 LoadedApk 的 makeApplication() 来尝试创建 Application 对象
  • 创建 ContextImpl 对象并通过 Activity 的 attach() 来完成一些重要数据的初始化
  • 调用 Activity 的 onCreate()

Service 的工作过程

使用一个 Service 分为两种工作状态,并且是可共存的:

  • 启动状态:主要用于执行后台计算
  • 绑定状态:主要用于其他组件和 Service 的交互

Service 的启动过程

Service 的启动过程从 ContextWrapper 的 startService 开始:

  • startService()
    调用了 mBase.startService()。mBase 的类型是 ContextImpl 对象,其实现了 ContextWrapper 的大部分操作(桥接模式)。
  • startService()
    调用了 startServiceCommon() –> ActivityManagerNative.getDefault() 这个对象来启动一个服务(实际上是通过 AMS 来启动服务,这是一个远程过程调用)。
    AMS 会通过 mServices 这个对象(类型是 ActivityServices,用以辅助 AMS 进行 Service 管理的类)来完成 Service 后续的启动过程,mServices.startServiceLocked() –> startServiceInnerLocked()。
  • startServiceInnerLocked()
    ServiceRecord 一直贯穿着整个 Service 的启动过程,描述的是一个 Service 记录。
    其把启动的后续工作交给了 bringUpServiceLocked() –> realStartServiceLocked()。
  • realStartServiceLocked()
    首先通过 app.thread 的 scheduleCreateService() 创建 Service 对象并调用其 onCreate(),接着再通过 sendServiceArgsLocked() 调用 Service 的其他方法。这两个过程均是进程间通信。
    接着看 app.thread 对象的具体实现 ApplicationThread 对 Service 启动过程的处理,对应着 scheduleCreateService()。
  • scheduleCreateService()
    发功消息给 Handler H,H 处理 CREATE_SERVICE 消息,并通过 ActivityThread 的 handleCreateService() 完成 Service 的最终启动。
  • handleCreateService()
    其主要完成了如下几件事:
  • 通过类加载器创建 Service 的实例
  • 创建 Application 对象并调用其 onCreate,此过程只一次
  • 创建 ContextImpl 对象并通过 Service 的 attach() 建立二者之间的关系。、
  • 调用 Service 的 onCreate() 并将 Service 对象存储到 ActivityThread 中的一个列表中

Service 的绑定过程

从 ContextWrapper 的 bindService() 开始:

  • bindService()
    mBase.bindService() –> 最终会调用自己的 bindServiceCommon()。
  • bindServiceCommon()
    主要完成两件事:
  • 首先将客户端的 ServiceConnection 对象转化为 ServiceDispatcher.InnerConnection 对象
  • 接着通过 AMS 来完成 Service 的具体绑定过程
  • AMS 的 bindService()
    调用 ActiveServices 的 bingServiceLocked() –> … –> realStartServiceLocked()。
  • realStartServiceLocked()
    最终通过 ApplicationThread 完成 Service 实例的创建并执行其 onCreate()。
    与启动 Service 不同,绑定过程会调用 app.thread 的 scheduleBindService(),方法位于 ActiveServices 的 requestServiceBindingLocked() 中。
  • scheduleBindService()
    通过 Handler H 来中转,在 H 内部,接收到 BIND_SERVICE 这类消息时,会交给 ActivityThread 的 handleBindService() 处理。
  • handleBindService()
    首先根据 Service 的 token 取出 Service 对象,然后调用 Service 的 onBind()(会返回一个 Binder 对象给客户端使用)。当多次绑定同一个 Service 时,onBind() 只会执行一次,除非 Service 被终止了。
    由于 onBing 是 Service 的方法,客户端并不知道已经成功连接 Service 了,还需调用客户端的 ServiceConnection 中的 onServiceConnected(),这个过程由 ActivityManagerNative.getDefault() 的 publishService() 来完成的。
  • publishService()
    将具体工作交给了 ActiveServices 类型的 mServices 对象来处理,mServices.publishServiceLocked()。
  • publishServiceLocked()
    核心代码,c.conn.connected(r.name, service)。其中,c 的类型是 ConnectionRecord,c.conn 的类型是 ServiceDispatcher.InnerConnection,service 就是 onBind() 返回的 Binder 对象。
  • ServiceDispatcher.InnerConnection
    它的 connected() 调用了 ServiceDispatcher 的 connected()。
  • connected()
    ServiceDispatcher 的 mActivityThread 是一个 Handler,也就是 ActivityThread 中的 H。mActivityThread.post(new RunConnection(name,service,0))。
    RunConnection 经由 H 的 post() 运行在主线程中,因此,客户端 ServiceConnection 中的方法是在主线程被回调的。
  • RunConnection
    最终调用 ServiceConnection 对象的 onServiceConnected() 完成绑定过程。至于 Service 的停止和解除绑定过程,系统的执行过程是类似的。

BroadcastReceiver 的工作过程

广播的注册过程

广播的注册分为静态注册和动态注册,其中静态注册的广播在应用安装时由系统自动完成注册,具体来说是由 PMS(PackageManagerService)来完成整个注册过程的,除了广播以外,其它三大组件也都是在应用安装时由 PMS 解析并注册的。

动态注册的过程是从 ContextWrapper 的 registerReceiver() 开始的:

  • registerReceiver()
    mBase.registerReceiver() –> ContextImpl 又调用了自己的 registerReceiverInternal()
  • registerReceiverInternal()
    系统首先从 mPackageInfo 获取 IIntentReceiver 对象,然后再采用跨进程的方式向 AMS 发送广播注册的请求。注册过程是一个进程间通信的过程。
    IIntentReceiver 是一个 Binder 接口,具体实现是 LoadedApk.ReceiverDispatcher.InnerReceiver。
    ReceiverDispatcher 在构造方法中同时保存了 BroadcastReceiver 和 InnerReceiver,这样当接收到广播时,ReceiverDispatcher 可以方便地调用 BroadcastReceiver 的 onReceive()。
  • AMS 的 registerReceiver()
    最终会把远程的 InnerReceiver 对象以及 IntentFilter 对象存储起来,这样整个广播的注册过程就完成了。

广播的发送和接收过程

当通过 send() 发送广播时,AMS 会查找出匹配的广播接收者并将广播发送给它们处理。
普通广播的实现,其发送和接收的本质是一个过程的两个阶段,发送开始于 ContextWrapper 的 sendBroadcast(),但它仍然交给了 ContextImpl 处理:

  • ContextImpl 的 sendBroadcase()
    直接向 AMS 发起了一个异步请求用于发送广播。
  • AMS 的 broadcastIntent()
    调用了 broadcastIntentLocked()。
  • broadcastIntentLocked()
    首先控制广播不会发送给已经停止的应用。
    在内部,会根据 intent-filter查找出匹配的广播接收者并经过一系列的条件过滤,最终会将满足条件的广播接收者添加到 BroadcastQueue 中,接着 BroadcastQueue 就会将广播发送给相应的广播接收者。
  • BroadcastQueue 的 scheduleBroadcastsLocked()
    并没有立即发送广播,会发送一个 BROADCAST_INTENT_MSG 类型的消息,BroadcastQueue 收到消息后会调用 processNextBroadcast()。
  • processNextBroadcast()
    无序广播存储在 mParallelBroadcasts 中,系统会遍历它并通过 deliverToRegisteredReceiverLocked() 将其中的广播发送给它们所有的接收者。
  • deliverToRegisteredReceiverLocked()
    负责将一个广播发送给一个特定的接收者,内部调用了 performReceiveLocked() 来完成具体的发送过程。
  • performReceiveLocked()
    app.thread.scheduleRegisteredReceiver()。
  • ApplicationThread 的 scheduleRegisteredReceiver()
    通过 InnerReceiver 来实现广播的接收。InnerReceiver 的 performReceive() 会调用 LoadedApk.ReceiverDispatcher 的 performReceive()。
  • performReceive()
    会创建一个 Args 对象并通过 mActivityThread 的 post() 来执行 Args 中的逻辑。
    Args 实现了 Runnable 接口。mActivityThread 就是 ActivityThread 的内部类 H。
  • Args 的 run()
    这时,BroadcastReceiver 的 onReceive() 被执行了,也就是说应用已经接收到广播了。
    同时,onReceive() 是在广播接收者的主线程中被调用的。

ContentProvider 的工作过程

当 ContentProvider 所在进程启动时,ContentProvider 会同时启动并发布到 AMS 中,这时,它的 onCreate 要先于 Application 的 onCreate。

当一个应用启动时,入口方法为 ActivityThread 的 main(),main() 是一个静态方法,在其中会创建 ActivityThread 的实例并创建主线程的消息队列,然后在 ActivityThread 的 attach() 中会远程调用 AMS 的 attachApplication() 并将 ApplicationThread 对象提供给 AMS。

  • attachApplication()
    会调用 ApplicationThread 的 bindApplication(),这是个跨进程的过程。
  • bindApplication()
    其内逻辑会通过 ActivityThread 中的 mH Handler 切换到 ActivityThread 中去执行,具体的方法是 handleBindApplication。
  • handleBindApplication()
    其中,ActivityThread 会创建 Application 对象并加载 ContentProvider,然后再调用 Application 的 onCreate()。这时 ContentProvider 就已经启动了。

它的四个方法都是通过 Binder调用的,外界无法直接访问 ContentProvider,它只能通过 AMS 根据 Uri 来获取对应的 ContentProvider 的 Binder 接口 IConentProvider,通过它来访问 ContentProvider 中的数据源。

可通过 android:multiprocess 属性决定 ContentProvider 是否是单实例的,但一般可以简单的认为 ContentProvider 都是单实例的,单实例的启动过程如下:
访问 ContentProvider 需要通过 ContentResolver(抽象类),通过 Context 的 getContentResolver() 获取的实际上是 ApplicationContentResolver 对象。
通过 ContentProvider 的四个方法中任意一个都可触发 ContentProvider 的启动过程,也伴随着所在进程的启动(如未启动)。
query() 中,首先获取 IContentProvider 对象,最终通过 acquireProvider() 获取 ContentProvider:

  • ApplicationContentResolver 的 acquireProvider()
    直接调用了 ActivityThread 的 acquireProvider()。
  • acquireProvider()
    会从 ActivityThread 中(通过 mRroviderMap 存储已经启动的 ContentProvider)查找是否已经存在目标 ContentProvider,存在就直接返回。
    如果没有 ContentProvider 没有启动,那就发送一个进程间请求给 AMS 让其启动目标 ContentProvider,最后再通过 installProvider() 来修改引用计数。

备注

参考资料
Android 开发艺术探索
Android 进阶解密