从源码角度看广播

简介

几乎每个安卓应用都无可避免的使用到广播。例如监听WIFI的开启状态、时间的获取,甚至是我们最常用的闹钟功能,都是结合着AlarmManager与广播来实现的。理解广播的注册、发送与接收实现源码将使我们更加懂安卓系统,同时,基于对广播的理解,我们也能很快的掌握AMS中其它组件的实现原理。

网上对于广播源码的分析数以千计,其中不乏精品的文章。但这些文章大多都太过枯燥、太抽象、太冗长,我最初看这些文章时,看了很多遍后才能慢慢理解。这篇文章里,我将画出几张简明扼要的图,简略的列出广播注册、发送中涉及到重要类。每副图后都会有我的一些简洁的理解,都是我在平日里开发中积累的精华。初学者能够通过这些对广播源码有个迅速的大体印象,熟悉广播源码的同学也能够查漏补缺。受语言与我自己理解的局限,如果文章中出现错误还希望大家指正。

文章最后,我会附上一张广播实用adb日志的输出对应图,希望能帮大家对于广播日志有个cheat sheet的作用:-)

重要类

  • ReceiverDispatcher
  • BroadcastQueue
  • BroadcastRecord
  • BroadcastFilter
  • ResolveInfo
  • InnterRceiver
  • ReceiverList

广播注册

概括图

未包含的点

我这张图为了避免信息太多内容晦涩,有两个重要的过程没有画出来:

  1. 动态注册广播操作过程中,首先会检查sticky广播进行检查操作
  2. 静态广播的注册逻辑在PMS中,涉及对manifest文件的解析,以后再分析吧

这里我详细说说动态注册时,对sticky的特殊处理。

动态广播注册阶段中,第一步就是对sticky广播进行检查。 如果AMS中的mStickyBroadcasts存在符合过滤条件的Intent,那么这个广播在注册阶段就会被派发。当从registerReceiver传参进来的receiver为NULL,那么这个最新的sticky Intent将直接被返回。值得注意的一点是,在注册阶段发送出的广播是不会出现在dump日志历史记录中的。

具体解析

再看这张图, 我将从左到右对每个重要图像进行解释:

  • mReceivers: 维护在App中的一个列表,用户存储BroadcastReceiver与ReceiverDispatcher之间的对应关系,同一个BroadcastReceiver对应的Binder Stub将不会被反复创建
  • InnerReceiver: 实现在App中的Binder"服务端",它的父类是Binder Stub,当广播在AMS调度时,AMS将在system_server端调用它的代理对象binder call到客户端,以在App端触发广播的onReceive方法
  • mRegisteredReceivers: 动态广播注册的核心对象,是一个HashMap,这个Map以IBinder为键,每个BroadcastReceiver将会在AMS中对应这一个ReceiverList
  • ReceiverList: 继承自一个泛型为IntentFilter的ArrayList,保存着IntentReceiver句柄,同时有着匹配广播Intent的作用

mRegisteredReceivers中的数据在App进程死亡或App调用unregisterReceiver反注册接口才会被清除。

广播发送

广播入队

top Created with Sketch.