Earth Guardian

You are not LATE!You are not EARLY!

0%

四大组件 -- Broadcast

广播 Broadcast 属于 Android 四大组件之一,通过观察者模式,用于实现进程间的异步通信。

广播的实现机制是观察者模式;消息发布/订阅模式的事件驱动模型,消息的生产者发布事件,而使用者订阅感兴趣的事件。Broadcast 机制和 Binder 机制不一样的地方在于:广播的发送者和接收者事先是不需要知道对方的存在的,这也是观察者模式的特点,显而易见的优点是系统的各个组件可以松耦合地组织在一起,所有的广播发送和接收都是通过系统 AMS 来调度的,它充当了广播总线的功能。

基础

广播实现进程间异步交互:进程间通信时通过 Binder 来实现的,异步通信是通过 Handler 实现。

广播接收器的分类

  • 静态注册广播接收器:Manifest-declared receivers
    AndroidManifest.xml 文件中通过 <receiver> 声明的广播接收器。
  • 动态注册广播接收器:Context-registered receivers
    通过 registerReceiver 注册的广播接收器。

广播的分类

  • 普通广播
    通过 sendBroadcast 发出的广播。
  • 有序广播
    通过 sendOrderedBroadcast 发出的广播;有序广播对应的广播接收器存在优先级关系,优先级越高越先收到广播。有序广播还可以有回调广播接收器,即广播匹配的所有广播接收器处理完毕后,系统会再向广播发送者,发回这个回调。
  • 粘性广播
    通过 sendStickyBroadcast 发出的广播。粘性广播发送后,系统会把代表这个广播的 Intent 保存下来,如果后面在动态注册相同 Action 的广播接收器时,系统就将最后发出的粘性广播重新发送给这个广播接收器。也就是说,尽管广播早就发送处理完毕了,但是后续如果有新注册的广播接收器能匹配这个广播,还是会响应广播事件的。但是粘性广播从 Android 5.0 开始就将相关系统接口全部标注为 @Deprecated。它们不提供安全性(任何人都可以访问它们),没有保护(任何人都可以修改它们)以及许多其他问题。所以 Android 平台已经弃用,本文也不做介绍。

广播的标记

根据发送广播 Intent 设置的标记来区分:

  • FLAG_RECEIVER_FOREGROUND
    表示广播为前台广播,允许接收者以前台的优先级运行,有更短的时间间隔。默认情况下广播都是后台广播
  • FLAG_RECEIVER_REPLACE_PENDING
    表示新的广播会替换掉那些已存在的相同广播。相同的定义是通过 Intent.filterEquals 方法对两个广播的 Intent 比较,当匹配到相同的,新的广播和对应的接收器会将待发送的广播列表中已存在的替换掉,在列表中保留同样的位置。这个标志通常被粘性广播使用,只保证将最新的广播的值传递给接收器。

广播的 ANR

前台广播的 ANR 时间是 10 秒,后台广播是 60 秒。因为默认为后台广播,所以通常情况下,需要在 60 秒内处理完所有的广播事件。广播的 ANR 只会出现在有序处理的广播队列中(包含有序广播和静态注册的广播接收器匹配的普通广播)中

1
2
3
4
// ActivityManagerService.java
// How long we allow a receiver to run before giving up on it.
static final int BROADCAST_FG_TIMEOUT = 10*1000;
static final int BROADCAST_BG_TIMEOUT = 60*1000;

相关类文件

速查表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
framework/base
./core/java/android/app/ContextImpl.java
./core/java/android/app/ActivityThread.java
./core/java/android/app/LoadedApk.java
./core/java/android/app/BroadcastOptions.java
./core/java/android/content/IIntentReceiver.aidl
./core/java/android/content/pm/PackageParser.java
./core/java/android/content/BroadcastReceiver.java
./services/core/java/com/android/server/am/BroadcastRecord.java
./services/core/java/com/android/server/am/ReceiverList.java
./services/core/java/com/android/server/am/BroadcastFilter.java
./services/core/java/com/android/server/am/BroadcastQueue.java
./services/core/java/com/android/server/am/ActivityManagerService.java
./services/core/java/com/android/server/pm/PackageManagerService.java

类简介

  • BroadCastReceiver
    广播接收器,用于处理接收的每个广播事件。
  • IIntentReceiver
    AIDL 文件,每个 BroadCastReceiver 都会转换为一个 IIntentReceiver,用来跨进程传递数据。
  • LoadedApk.ReceiverDispatcher
    广播接收发布器,BroadCastReceiver 都是在这转换为 IIntentReceiver 的。每个动态注册的广播接收器 BroadcastReceiver 都对应一个 LoadedApk.ReceiverDispatcher ,最终都是在这进行响应调用 onReceive 的。
  • BroadcastFilter
    IntentFilter 的子类,广播过滤器,用于匹配广播 Intent;包含广播接收者相关信息,权限等。只有动态注册广播广播接收器会用到。
  • ReceiverList
    ArrayList 的子类,是一个集合用来存储 BroadcastFilter 。记录广播接收器相关信息等,只有动态注册的广播接收器会用到,每个 BroadCastReceiver 对应一个 ReceiverList ,而每个 ReceiverList 可以包含多个 BroadcastFilter ,表示能够监听多个广播。
  • BroadcastRecord
    继承了 Binder,用来跨进程传递数据。发送的每个广播 Intent ,最后都会对应一个 BroadcastRecord ;它记录了广播的发送时间,发送者,接受者,广播携带的数据,回调,所在 BroadcastQueue 等等。
  • BroadcastQueue
    广播队列,有两个 ArrayList<BroadcastRecord> 用于存储 BroadcastRecord 分别是:mParallelBroadcasts 存储并行处理的广播;mOrderedBroadcasts 存储有序处理的广播。
  • ContextImpl
    广播发送,广播接收器动态注册的入口。
  • ActivityThread
    应用主线程,广播发送过程都是由它进入系统进程 AMS,广播接收器响应事件是有系统 AMS 进入它。
  • ActivityManagerService
    AMS 系统四大组件大管家,类似广播总线:管理广播接收器的注册,管理广播的发送到匹配的广播接收器中处理。
  • PackageParser
    包解析类,会从 AndroidManifest.xml 中解析出静态注册的广播接收器。
  • PackageManagerService
    PMS 系统包管家,负责静态注册广播接收器的存储,查询。

BroadcastFilter 类详解

BroadcastFilter 继承了 IntentFilter 类,广播信息过滤器,即动态注册广播接收器时,注册的是哪个广播过滤器。

源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
final class BroadcastFilter extends IntentFilter {
// Back-pointer to the list this filter is in.
final ReceiverList receiverList;
final String packageName;
final String requiredPermission;
final int owningUid;
final int owningUserId;

BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList,
String _packageName, String _requiredPermission,
int _owningUid, int _userId) {
super(_filter);
receiverList = _receiverList;
packageName = _packageName;
requiredPermission = _requiredPermission;
owningUid = _owningUid;
owningUserId = _userId;
}

public void dump(PrintWriter pw, String prefix) {...}
public void dumpBrief(PrintWriter pw, String prefix) {...}
public void dumpInReceiverList(PrintWriter pw, Printer pr,
String prefix) {...}
void dumpBroadcastFilterState(PrintWriter pw, String prefix) {...}
public String toString() {...}

成员变量

  • receiverList :当前对象属于哪个接收列表
  • packageName :动态注册广播发起者的包名
  • requiredPermission :设置发送广播时需要的权限
  • owningUid :动态注册广播发起者 Uid
  • owningUserId :动态注册广播发起者 UserId

这里简单介绍下 uid, userId 的区别:

  • uid
    Linux 下的概念,表示 Linux 系统下的用户 ID
  • userId
    Android 的多用户概念,从 4.2 开始系统支持多用户登录,记录登录用户的 ID ;不支持多用户登录的系统上,这个值是唯一的。多用户支持是在 frameworks/base/core/res/res/values/config.xml 文件中,config_multiuserMaximumUsers 值来决定的。

ReceiverList 类详解

ReceiverList 继承了 ArrayList ,本质上是一个数据集合,数据类型为 BroadcastFilter。动态注册广播接收器时,每个广播接收器 BroadCastReceiver 对应一个 ReceiverList ,记录了一系列 BroadcastFilter 的列表,表示这个广播接收器注册了一个或多个广播过滤器。

源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
final class ReceiverList extends ArrayList<BroadcastFilter>
implements IBinder.DeathRecipient {
final ActivityManagerService owner;
public final IIntentReceiver receiver;
public final ProcessRecord app;
public final int pid;
public final int uid;
public final int userId;
BroadcastRecord curBroadcast = null;
boolean linkedToDeath = false;

String stringName;

ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
int _pid, int _uid, int _userId, IIntentReceiver _receiver) {
owner = _owner;
receiver = _receiver;
app = _app;
pid = _pid;
uid = _uid;
userId = _userId;
}

// Want object identity, not the array identity we are inheriting.
public boolean equals(Object o) {return this == o;}
public int hashCode() {return System.identityHashCode(this);}

public void binderDied() {
linkedToDeath = false;
owner.unregisterReceiver(receiver);
}

void dumpLocal(PrintWriter pw, String prefix) {...}
void dump(PrintWriter pw, String prefix) {...}
public String toString() {...}

成员变量

  • ActivityManagerService ownerAMS 对象
  • IIntentReceiver receiver :当前 ReceiverList 对应的 IIntentReceiver
  • ProcessRecord app :动态注册广播发起者进程相关信息
  • pid :动态注册广播发起者进程 Id
  • uid :动态注册广播发起者 uid
  • userId :动态注册广播发起者 userId
  • BroadcastRecord curBroadcast :动态注册的广播,其详细信息
  • linkedToDeathBinder 通信机制是否断开
  • stringNameReceiverList 转换成的字符串

BroadCastReceiver 类详解

BroadCastReceiver 广播接收器,用来处理监听的广播事件。BroadcastReceiver 是抽象类,抽象方法为 onReceive ,注册广播接收器前,需要在其子类中实现。

PendingResult

PendingResult 是广播接收器待处理的结果类,是异步结果类;简要介绍下这个类存在的意义:
通常情况下,UI 主线程阻塞超过 5 秒就会产生 ANR,更不用说卡顿现象 UI Jank;所以广播接收器中如果有耗时工作(比如磁盘读写,网络下载等),需要及时切换到后台工作线程中执行;而 PendingResult 就存储了广播处理器接收到广播所有相关信息,将 PendingResult 对象传递到后台工作线程完成广播处理,处理完后需要调用 PendingResult.finish() 通过系统该广播接收器已经处理完毕。 PendingResult 类有两个注意事项:

  • PendingResult 类中的状态不是线程安全的,使用时将整个对象交给后台工作线程,避免并发竞争,该线程将负责设置结果并最终调用 finish()
  • 系统中关于广播接收器的 ANR :前台广播接收器允许运行时间大概是 10 秒,后台广播是 60 秒,如果广播处理器没有处理完毕就会产生 ANR 。注意这个过程的计算时间是:从广播分发到广播处理器,直到广播处理器通知系统处理完毕的总时间。即使通过 PendingResult 切换到后台工作线程,直到调用 PendingResult.finish() ,这整个过程都受到了这个 ANR 时间的限制。所以长时间的工作是不能放到 BroadCastReceiver 中来实现的,PendingResult 仅仅是多争取到了几秒钟

PendingResult 类的两个子类

PendingResult 类的构造方法是 @hide 隐藏的,通常在 BroadcastReceiver.onReceive() 中调用 goAsync() 返回得到;而实际构造是在其子类中,静态注册广播和动态注册广播对应不同的子类:

  • ActivityThread.ReceiverData 对应静态注册广播
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    static final class ReceiverData extends 
    BroadcastReceiver.PendingResult {
    public ReceiverData(Intent intent,int resultCode,String resultData,
    Bundle resultExtras, boolean ordered, boolean sticky,
    IBinder token, int sendingUser) {
    super(resultCode, resultData, resultExtras, TYPE_COMPONENT,
    ordered, sticky,token, sendingUser, intent.getFlags());
    this.intent = intent;
    }

    Intent intent;
    ActivityInfo info;
    CompatibilityInfo compatInfo;
    public String toString() {...}
    }
  • LoadedApk.ReceiverDispatcher.Args 对应动态注册广播
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    final class Args extends BroadcastReceiver.PendingResult 
    implements Runnable {
    private Intent mCurIntent;
    private final boolean mOrdered;
    private boolean mDispatched;

    public Args(Intent intent, int resultCode, String resultData,
    Bundle resultExtras, boolean ordered,
    boolean sticky, int sendingUser) {
    super(resultCode, resultData, resultExtras,
    mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED,
    ordered, sticky, mIIntentReceiver.asBinder(),
    sendingUser, intent.getFlags());
    mCurIntent = intent;
    mOrdered = ordered;
    }

    public void run() {...}
    }

PendingResult 类源码分析

PendingResult 对应的广播类型有三种:

  • TYPE_COMPONENT :静态注册广播
  • TYPE_REGISTERED :动态注册广播
  • TYPE_UNREGISTERED :取消广播注册
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
public static class PendingResult {
// 广播类型:静态注册,动态注册,解除注册
public static final int TYPE_COMPONENT = 0;
public static final int TYPE_REGISTERED = 1;
public static final int TYPE_UNREGISTERED = 2;

final int mType;
final boolean mOrderedHint;
final boolean mInitialStickyHint;
final IBinder mToken;
final int mSendingUser;
final int mFlags;

int mResultCode;
String mResultData;
Bundle mResultExtras;
boolean mAbortBroadcast;
boolean mFinished;

/** @hide */
public PendingResult(int resultCode, String resultData,
Bundle resultExtras, int type, boolean ordered,
boolean sticky, IBinder token, int userId, int flags) {
mResultCode = resultCode;
mResultData = resultData;
mResultExtras = resultExtras;
mType = type;
mOrderedHint = ordered;
mInitialStickyHint = sticky;
mToken = token;
mSendingUser = userId;
mFlags = flags;
}

// 获取和保存广播相关信息
public final void setResultCode(int code) {...}
public final int getResultCode() {...}
public final void setResultData(String data) {...}
public final String getResultData() {...}
public final void setResultExtras(Bundle extras) {...}
public final Bundle getResultExtras(boolean makeMap) {...}
public final void setResult(int code, String data,
Bundle extras) {...}
public int getSendingUserId() {...}

// 终止有序广播
public final boolean getAbortBroadcast() {return mAbortBroadcast;}
public final void abortBroadcast() {
checkSynchronousHint();
mAbortBroadcast = true;
}
public final void clearAbortBroadcast() {
mAbortBroadcast = false;
}

public final void finish() {
if (mType == TYPE_COMPONENT) {
// 如果是静态注册广播
final IActivityManager mgr = ActivityManager.getService();
if (QueuedWork.hasPendingWork()) {
// 如果还有任务没有执行完,将任务加入队列排队执行
QueuedWork.queue(new Runnable() {
@Override public void run() {
...
sendFinished(mgr);
}
}, false);
} else {
...
sendFinished(mgr);
}
} else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
// 如果是有序广播
...
final IActivityManager mgr = ActivityManager.getService();
sendFinished(mgr);
}
}
// 设置类加载器
public void setExtrasClassLoader(ClassLoader cl) {
if (mResultExtras != null) {
mResultExtras.setClassLoader(cl);
}
}

/** @hide */
public void sendFinished(IActivityManager am) {
synchronized (this) {
if (mFinished) {
throw new IllegalStateException("...");
}
mFinished = true;

try {
if (mResultExtras != null) {
mResultExtras.setAllowFds(false);
}
if (mOrderedHint) {
am.finishReceiver(mToken, mResultCode, mResultData,
mResultExtras, mAbortBroadcast, mFlags);
} else {
am.finishReceiver(mToken, 0, null, null, false, mFlags);
}
} catch (RemoteException ex) {
}
}
}
...
}

BroadcastReceiver 源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public abstract class BroadcastReceiver {
private PendingResult mPendingResult;
...
public static class PendingResult {...}

public BroadcastReceiver() {}

public abstract void onReceive(Context context, Intent intent);

public final PendingResult goAsync() {
PendingResult res = mPendingResult;
mPendingResult = null;
return res;
}

public IBinder peekService(Context myContext, Intent service) {...}

// 设置 PendingResult 实例,存储获取相关结果
public final void setPendingResult(PendingResult result) {
mPendingResult = result;
}
public final PendingResult getPendingResult() {
return mPendingResult;
}
public final String getResultData() {
return mPendingResult != null ? mPendingResult.mResultData : null;
}
public final void setResultExtras(Bundle extras) {
checkSynchronousHint();
mPendingResult.mResultExtras = extras;
}
public final void setResultCode(int code) {...}
public final int getResultCode() {...}
public final Bundle getResultExtras(boolean makeMap) {...}
public final void setResult(int code, String data,
Bundle extras) {...}
public int getSendingUserId() {...}

// 终止有序广播
public final boolean getAbortBroadcast() {
return mPendingResult != null ?
mPendingResult.mAbortBroadcast : false;
}
public final void abortBroadcast() {
checkSynchronousHint();
mPendingResult.mAbortBroadcast = true;
}
public final void clearAbortBroadcast() {
if (mPendingResult != null) {
mPendingResult.mAbortBroadcast = false;
}
}
public final boolean isOrderedBroadcast() {...}
public final boolean isInitialStickyBroadcast() {...}
...
}

BroadcastReceiver 重要方法

BroadcastReceiver 大部分数据存储都是通过 PendingResult 实例来保存的。

  • onReceive
    抽象方法,子类必须实现;广播接收器处理的入口。
  • goAsync
    异步广播,返回 PendingResult 实例,进入后台线程处理;处理完毕后必须调用 PendingResult.finish() 结束。
  • abortBroadcast
    如果广播接收器收到的是有序广播,则终止有序广播继续向下传递。

IIntentReceiver 详解

IIntentReceiver 是一个 AIDL 文件,所以 IIntentReceiver 接口继承了 Binder 机制中的 IInterface ,表示服务端拥有的能力或者说能提供的功能。 IIntentReceiver 声明的方法,是在 LoadedApk.ReceiverDispatcher.InnerReceiver 中实现的。IIntentReceiver.aidl 源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
// frameworks/base/core/java/android/content/IIntentReceiver.aidl
/**
* System private API for dispatching intent broadcasts.
* This is given to the activity manager as part of registering for
* an intent broadcasts, and is called when it receives intents.
*
* {@hide}
*/
oneway interface IIntentReceiver {
void performReceive(in Intent intent, int resultCode, String data,
in Bundle extras, boolean ordered,
boolean sticky, int sendingUser);
}

BroadCastReceiver 是系统组件,并不支持跨进程传输,Android Broadcast 机制使用 IIntentReceiver 来进行代替 BroadCastReceiver 来进行跨进程传输。
可以看出 IIntentReceiver 只提供了一个方法 performReceive ,该方法仅仅在动态注册的广播接收器中会触发调用(静态注册广播接收器在 ActivityThread 中通过反射直接调用 onReceive 回调);系统进程 AMS 在分发广播处理事件时,会向注册了广播接收的应用进程调用该方法,最终调用 BroadcastReceiver.onReceive 触发回调。注意:方法使用了 oneway 关键字,表示非阻塞调用;即 AMS 进程分发广播事件时,不需要等待每个应用接收者执行完 onReceive

LoadedApk

LoadedApk 类存储了当前加载的 Apk 相关信息,包括主线程,文件所在路径,类加载器,注册的广播列表,启动的服务列表等等;LoadedApk 类是在每个应用加载初始化进程、主线程时实例化的,每个应用对应一个 LoadedApk 实例。
本文只分析和广播 Broadcast 相关内容,LoadedApk 中存储了当前 Apk 中所有的普通广播接收器 BroadCastReceiver ,即通过 registerReceiver 注册到系统中的广播接收器。
有序广播中的回调广播接收器,即广播发送出去后,等待所有广播接收器处理完毕,最后产生一个回调给广播发送者,作用类似 startActivityForResult 。回调 BroadCastReceiver 不需要通过 registerReceiver 注册到系统中,是以参数的形式在 sendOrderedBroadcast() 发送广播时传递出去,这类广播不会存储到 LoadedApk 中。

ContextImpl 代码中可以看到:LoadedApk 对这两类广播接收器的处理过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// ContextImpl.java  
// 1. 普通广播接收器:注册广播接收器时,在 LoadedApk 中保存下来
private Intent registerReceiverInternal(BroadcastReceiver receiver,
int userId, IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
// 获取广播接收器对应的 IIntentReceiver
// register 变量值为 true, LoadedApk 保存该广播接收器
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
// 如果 LoadedApk 没有加载,则新建一个 IIntentReceiver 对象
rd = new LoadedApk.ReceiverDispatcher(receiver, context,
scheduler, null, true).getIIntentReceiver();
}
}
...
}

// 2. 有序广播接收器:不注册广播,所以也不会保存
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, int appOp, Bundle options,
BroadcastReceiver resultReceiver, Handler scheduler,
int initialCode, String initialData, Bundle initialExtras) {
IIntentReceiver rd = null;
if (resultReceiver != null) {
if (mPackageInfo != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
// 获取广播接收器对应的 IIntentReceiver
// register 变量值为 false,不做保存
rd = mPackageInfo.getReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
mMainThread.getInstrumentation(), false);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(resultReceiver,
getOuterContext(), scheduler, null, false)
.getIIntentReceiver();
}
}
}

部分源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
public final class LoadedApk {
// 保存所有通过 registerReceiver 注册的广播接收器
private final ArrayMap<Context,
ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
= new ArrayMap<Context,
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
private final ArrayMap<Context,
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>
mUnregisteredReceivers
= new ArrayMap<Context,
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();

public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map=null;
if (registered) {
map = mReceivers.get(context);
if (map != null) {
rd = map.get(r);
}
}
if (rd == null) {
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
// 如果是通过 registerReceiver 注册的,保存到 mReceivers 中
if (registered) {
if (map == null) {
map = new ArrayMap<BroadcastReceiver,
LoadedApk.ReceiverDispatcher>();
mReceivers.put(context, map);
}
map.put(r, rd);
}
} else {
rd.validate(context, handler);
}
rd.mForgotten = false;
return rd.getIIntentReceiver();
}
}

public IIntentReceiver forgetReceiverDispatcher(Context context,
BroadcastReceiver r) {
synchronized (mReceivers) {
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>
map = mReceivers.get(context);
LoadedApk.ReceiverDispatcher rd = null;
if (map != null) {
rd = map.get(r);
if (rd != null) {
map.remove(r);
if (map.size() == 0) {
mReceivers.remove(context);
}
if (r.getDebugUnregister()) {
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>
holder = mUnregisteredReceivers.get(context);
if (holder == null) {
holder = new ArrayMap<BroadcastReceiver,
LoadedApk.ReceiverDispatcher>();
mUnregisteredReceivers.put(context, holder);
}
...
holder.put(r, rd);
}
rd.mForgotten = true;
return rd.getIIntentReceiver();
}
}
...
throw ...
}
}

static final class ReceiverDispatcher {

// 静态内部类 InnerReceiver
final static class InnerReceiver extends IIntentReceiver.Stub {
...
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher=new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null;
}

// 最终调用的是外部类的 performReceive
@Override
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered,
boolean sticky, int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;
if (intent == null) {
Log.wtf(TAG, "Null intent received");
rd = null;
} else {
rd = mDispatcher.get();
}
...
if (rd != null) {
// 调用外部类的 performReceive
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
} else {
...
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
if (extras != null) {
extras.setAllowFds(false);
}
// 广播接收器已经处理完这条广播
mgr.finishReceiver(this, resultCode, data,
extras, false, intent.getFlags());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
}

final IIntentReceiver.Stub mIIntentReceiver;
final BroadcastReceiver mReceiver;
final Context mContext;
final Handler mActivityThread;
final Instrumentation mInstrumentation;
final boolean mRegistered;
final IntentReceiverLeaked mLocation;
RuntimeException mUnregisterLocation;
boolean mForgotten;

// 成员内部类 Args
final class Args extends BroadcastReceiver.PendingResult
implements Runnable {
private Intent mCurIntent;
private final boolean mOrdered;
private boolean mDispatched;

public Args(Intent intent, int resultCode, String resultData,
Bundle resultExtras, boolean ordered,
boolean sticky, int sendingUser) {
super(resultCode, resultData, resultExtras,
mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED,
ordered, sticky, mIIntentReceiver.asBinder(),
sendingUser, intent.getFlags());
mCurIntent = intent;
mOrdered = ordered;
}

// 执行当前广播接收器 BroadCastReceiver.onReceive
// 并告诉系统广播接收器处理完毕
public void run() {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
...
final IActivityManager mgr=ActivityManagerNative.getDefault();
...
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
} catch (Exception e) {
if (mRegistered && ordered) {
...
sendFinished(mgr);
}
...
}

// 如果没有 PendingResult,调用 finish 开始处理下一个广播接收器
if (receiver.getPendingResult() != null) {
finish();
}
...
}
}

ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
if (activityThread == null) {
throw new NullPointerException("Handler must not be null");
}

mIIntentReceiver = new InnerReceiver(this, !registered);
mReceiver = receiver;
mContext = context;
mActivityThread = activityThread;
mInstrumentation = instrumentation;
mRegistered = registered;
mLocation = new IntentReceiverLeaked(null);
mLocation.fillInStackTrace();
}

...
BroadcastReceiver getIntentReceiver() {return mReceiver;}
IIntentReceiver getIIntentReceiver() {return mIIntentReceiver;}

public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered,
boolean sticky, int sendingUser) {
final Args args = new Args(intent, resultCode, data,
extras, ordered, sticky, sendingUser);
...
// 当前线程发布任务 Args
if (intent == null || !mActivityThread.post(args)) {
if (mRegistered && ordered) {
IActivityManager mgr=ActivityManagerNative.getDefault();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(...);
args.sendFinished(mgr);
}
}
}
}
...
}

成员变量

  • mReceivers :当前 Apk 注册的广播列表
  • mUnregisteredReceivers :当前 Apk 取消广播注册的列表

这两个成员变量都是 Map 结构,Key 值都是 ContextValue 仍然是一个 Map 结构:

  • Key: Context
    每个 Activity 或者每个 Service 注册的广播分开记录,方便快速查找某个 Context 实例注册的所有广播。
  • Value: ArrayMap<BroadcastReceiver, ReceiverDispatcher>

BroadcastReceiverReceiverDispatcher 是一一对应的,每个广播接收器都会对应一个广播接收分发器ContextImpl.sendOrderedBroadcast, ContextImpl.registerReceiver 会对每个广播接收器 BroadCastReceiver ,通过 LoadedApk 找到或者生成对应的 ReceiverDispatcher ;在发送有序广播或者注册广播接收器,等到广播接收者开始执行时,AMS 通过 ReceiverDispatcher.InnerReceiver 来触发回调,即调用 BroadCastReceiver.onReceive

ReceiverDispatcher 静态内部类

ReceiverDispatcherLoadedApk 的静态内部类,同时它自己还包含两个内部类:

  • 静态内部类 InnerReceiver
    实现了 IIntentReceiver.performReceive 方法,实际最终调用的是外部类 ReceiverDispatcher.performReceive 方法。
  • 成员内部类 Args
    继承了 BroadCastReceiver.PendingResult 类,可以执行部分异步操作;同时实现了 Runnable ,通过传入的 Handler 发布这个任务,并调用 BroadCastReceiver.onReceive ,处理广播接收器回调事件。处理完后,通知系统该广播接收器处理完毕。
  • 成员变量
    mRegistered :记录该广播接收器是否通过 registerReceiver 注册的,即是否为动态注册的广播接收器。

ReceiverDispatcher 的几个重要方法:

  • getIIntentReceiver :返回广播接收器 BroadCastReceiver 对应的 IIntentReceiver 对象
  • performReceive :使用当前线程 Handler 发送 Args 对象并执行;所有动态注册的广播接收器,都是在这里回调 onReceive 方法

广播相关方法

  • getReceiverDispatcher
    根据广播接收器获取广播接收分发器的 IIntentReceiver ,用于跨进程传递。主要是从 mReceivers 中获取;如果不存在则新建。
  • forgetReceiverDispatcher
    mReceivers 中移除指定回调广播接收器,并放入 mUnregisteredReceivers 中,返回值也是该广播接收器对应的 IIntentReceiver

BroadcastRecord 类详解

BroadcastRecord 继承了 Binder ,表明该对象作为数据容器,能被跨进程通信。BroadcastRecord 保存了广播发送者相关信息,包含发送者的:包名,进程信息,广播是否有序,请求的权限等等。

源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/**
* An active intent broadcast.
*/
final class BroadcastRecord extends Binder {
final Intent intent; // the original intent that generated us
// original component name set on the intent
final ComponentName targetComp;
final ProcessRecord callerApp; // process that sent this
final String callerPackage; // who sent this
final int callingPid; // the pid of who sent this
final int callingUid; // the uid of who sent this
final boolean ordered; // serialize the send to receivers?
final boolean sticky; // originated from existing sticky data?
// initial broadcast from register to sticky?
final boolean initialSticky;
final int userId; // user id this broadcast was for
final String resolvedType; // the resolved data type
// permissions the caller has required
final String[] requiredPermissions;
final int appOp; // an app op that is associated with this broadcast
final BroadcastOptions options; // BroadcastOptions supplied by caller
final List receivers; // contains BroadcastFilter and ResolveInfo
final int[] delivery; // delivery state of each receiver
IIntentReceiver resultTo; // who receives final result if non-null
long enqueueClockTime; // the clock time the broadcast was enqueued
long dispatchTime; // when dispatch started on this set of receivers
long dispatchClockTime; // the clock time the dispatch started
long receiverTime; // when current receiver started for timeouts.
long finishTime; // when we finished the broadcast.
int resultCode; // current result code value.
String resultData; // current result data value.
Bundle resultExtras; // current result extra data values.
boolean resultAbort; // current result abortBroadcast value.
int nextReceiver; // next receiver to be executed.
IBinder receiver; // who is currently running, null if none.
int state;
int anrCount; // has this broadcast record hit any ANRs?
int manifestCount; // number of manifest receivers dispatched.
int manifestSkipCount; // number of manifest receivers skipped.
BroadcastQueue queue; // the outbound queue handling this broadcast

// 广播的五种状态
static final int IDLE = 0;
static final int APP_RECEIVE = 1;
static final int CALL_IN_RECEIVE = 2;
static final int CALL_DONE_RECEIVE = 3;
static final int WAITING_SERVICES = 4;
// 四种投递状态
static final int DELIVERY_PENDING = 0;
static final int DELIVERY_DELIVERED = 1;
static final int DELIVERY_SKIPPED = 2;
static final int DELIVERY_TIMEOUT = 3;

// The following are set when we are calling a receiver (one that
// was found in our list of registered receivers).
BroadcastFilter curFilter;

// The following are set only when we are launching a receiver (one
// that was found by querying the package manager).
ProcessRecord curApp; // hosting application of current receiver.
// the receiver class that is currently running.
ComponentName curComponent;
// info about the receiver that is currently running.
ActivityInfo curReceiver;

BroadcastRecord(BroadcastQueue _queue,
Intent _intent, ProcessRecord _callerApp,
String _callerPackage, int _callingPid, int _callingUid,
String _resolvedType, String[] _requiredPermissions,
int _appOp, BroadcastOptions _options, List _receivers,
IIntentReceiver _resultTo, int _resultCode,
String _resultData, Bundle _resultExtras,
boolean _serialized, boolean _sticky,
boolean _initialSticky, int _userId) {
if (_intent == null) {
throw new NullPointerException("
Can't construct with a null intent");
}
queue = _queue;
intent = _intent;
targetComp = _intent.getComponent();
callerApp = _callerApp;
callerPackage = _callerPackage;
callingPid = _callingPid;
callingUid = _callingUid;
resolvedType = _resolvedType;
requiredPermissions = _requiredPermissions;
appOp = _appOp;
options = _options;
receivers = _receivers;
delivery = new int[_receivers != null ? _receivers.size() : 0];
resultTo = _resultTo;
resultCode = _resultCode;
resultData = _resultData;
resultExtras = _resultExtras;
ordered = _serialized;
sticky = _sticky;
initialSticky = _initialSticky;
userId = _userId;
nextReceiver = 0;
state = IDLE;
}

boolean cleanupDisabledPackageReceiversLocked(String packageName,
Set<String> filterByClasses, int userId, boolean doit) {
if ((userId != UserHandle.USER_ALL && this.userId != userId)
|| receivers == null) {
return false;
}

boolean didSomething = false;
Object o;
for (int i = receivers.size() - 1; i >= 0; i--) {
o = receivers.get(i);
if (!(o instanceof ResolveInfo)) {
continue;
}
ActivityInfo info = ((ResolveInfo)o).activityInfo;

final boolean sameComponent = packageName == null
|| (info.applicationInfo.packageName.equals(packageName)
&& (filterByClasses == null
|| filterByClasses.contains(info.name)));
if (sameComponent) {
if (!doit) {
return true;
}
didSomething = true;
receivers.remove(i);
if (i < nextReceiver) {
nextReceiver--;
}
}
}
nextReceiver = Math.min(nextReceiver, receivers.size());

return didSomething;
}

void dump(PrintWriter pw, String prefix, SimpleDateFormat sdf) {...}
public String toString() {...}
}

重要成员变量

  • Intent intent :广播发送时的 Intent
  • ComponentName targetComp :广播发送者组件名称
  • ProcessRecord callerApp :广播发送者进程记录
  • String callerPackage :广播发送者包名
  • callingPid :广播发送者 Pid
  • callingUid :广播发送者 Uid
  • userId :广播发送者 userId
  • ordered :广播是否有序发送
  • sticky :广播是否为粘性广播
  • initialSticky :广播是否一开始就设置为粘性广播
  • resolvedTypeIntent 的类型
  • String[] requiredPermissions :广播发送者拥有的广播权限
  • appOp :广播对应的应用管理权限
  • BroadcastOptions options :广播发送者设定的选项
  • List receivers :广播接收者列表,特别需要注意的是:它包含了两种类型数据 ResolveInfo, BroadcastFilter,分别对应静态注册广播接收器和动态注册广播接收器,取出时需要做类型判断
  • int[] delivery :每个广播接收者的投递状态,状态分为四种
  • IIntentReceiver resultTo :有序广播中回调的广播接收器,它也是有序广播的最后一个接收者
  • enqueueClockTime :广播进入队列的时间
  • dispatchTime :开始分派广播的开机时间
  • dispatchClockTime :开始分派广播的系统绝对时间
  • receiverTime :广播接收者接收到的时间
  • finishTime :广播接收者处理完广播的完成时间
  • resultCode :广播处理完毕的结果码
  • resultData :广播处理完毕的简单数据
  • resultExtras :广播处理完毕的复杂数据
  • resultAbort :广播是否被终止
  • int nextReceiver :下一个广播接收者索引
  • IBinder receiver :广播当前接收者
  • int state :广播的当前状态,状态分为五种
  • anrCount :当前广播出现的 ANR 次数
  • manifestCount :分发给静态注册广播接收者的次数
  • manifestSkipCount :分发给静态注册广播接收者跳过的次数
  • BroadcastQueue queue :处理当前广播所在队列
  • BroadcastFilter curFilter :处理广播时当前广播过滤器
  • ProcessRecord curApp :广播当前接收者的进程信息
  • ComponentName curComponent :广播当前接收者的组件信息
  • ActivityInfo curReceiver :广播当前接收者的信息

cleanupDisabledPackageReceiversLocked 方法

BroadcastRecord 中只有一个包内可见的方法 cleanupDisabledPackageReceiversLocked ,该方法功能是从 List receivers 清理掉已经取消注册的广播注册接收者。

BroadcastQueue 类详解

BroadcastQueue 用来保存系统和应用发出的广播信息;通常使用两个广播队列 BroadcastQueue :一个用来保存前台广播,一个用来保存后台广播;而每个广播队列 BroadcastQueue 包含两个列表:一个用来并行处理;一个用来有序处理。

重要成员变量

  • ArrayList<BroadcastRecord> mParallelBroadcasts
    存储并行处理的广播:首先它是普通广播,其次这些广播匹配的广播接收器必须是动态注册的。
  • ArrayList<BroadcastRecord> mOrderedBroadcasts
    存储有序处理的广播:包含有序广播和普通广播(匹配的广播接收器时静态注册的)。
  • mTimeoutPeriod
    广播接收器 ANR 超时时间阀值。前台广播是 10 秒,后台广播是 60 秒。

BroadcastHandler

BroadcastHandler 是成员内部类,用来处理下一条广播,或者处理广播超时 ANR

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
static final int BROADCAST_INTENT_MSG = 
ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG;
static final int BROADCAST_TIMEOUT_MSG =
ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1;

final BroadcastHandler mHandler;
private final class BroadcastHandler extends Handler {
public BroadcastHandler(Looper looper) {
super(looper, null, true);
}

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
if (DEBUG_BROADCAST) Slog.v(
TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
broadcastTimeoutLocked(true);
}
} break;
}
}
}

AppNotResponding

AppNotResponding 成员内部类,广播接收器处理广播事件时发生 ANR

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private final class AppNotResponding implements Runnable {
private final ProcessRecord mApp;
private final String mAnnotation;

public AppNotResponding(ProcessRecord app, String annotation) {
mApp = app;
mAnnotation = annotation;
}

@Override
public void run() {
mService.mAppErrors.appNotResponding(mApp,
null, null, false, mAnnotation);
}
}

静态注册广播接收器流程分析

静态注册的广播接收器,又称为 Manifest 文件声明广播接收器,是在 PMS 扫描 AndroidManifest.xml 信息时解析的;所有静态注册的广播接收器,统一由 PMS 保存,广播在发送过程中,查找匹配的静态注册广播接收器也是在 PMS 中查询。

流程图

0021-broadcast-manifest-declare-receiver.png

PackageParser.parseBaseApplication 详解

PackageParser 主要用于详细解析包内相关信息,而 parseBaseApplication 主要解析 AndroidManifest.xml ,将每个 TAG 都解析并保存,其中静态注册的广播接收器存储到 receivers 中,而 PMS 会根据每个包解析的数据,保存整个系统全部的静态注册广播接收器(当然也保存其他 Activity, Services, ContentProvider 等信息)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// PackageParser.java
// 保存当前 Package 中所有的 BroadCastReceiver
public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);

private boolean parseBaseApplication(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
...
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG
|| parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG
|| type == XmlPullParser.TEXT) {
continue;
}

String tagName = parser.getName();
if (tagName.equals("activity")) {
...
} else if (tagName.equals("receiver")) {
// 解析到是静态注册的广播接收器,添加到 receivers 中
Activity a = parseActivity(owner, res, parser, flags,
outError, cachedArgs, true, false);
if (a == null) {
mParseError =
PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.receivers.add(a);
}
...
}
...
}

PMS 静态注册广播接收器

PMS 在调用完 PackageParser.parsePackage 解析完指定包名信息后,将存储在 PackageParser.Package.receivers 的静态广播接收器信息,再保存到 PMS.mReceivers 中,方便后续全局查询。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// PackageManageServices.java
// All available receivers, for your resolving pleasure.
// 存储整个系统所有的静态注册广播接收器
final ActivityIntentResolver mReceivers =
new ActivityIntentResolver();

/**
* Adds a scanned package to the system. When this method is finished,
* the package will be available for query, resolution, etc...
*/
private void commitPackageSettings(PackageParser.Package pkg,
PackageSetting pkgSetting, UserHandle user, int scanFlags,
boolean chatty) throws PackageManagerException {
final String pkgName = pkg.packageName;
...
// PackageParser 解析到静态注册广播接收器
N = pkg.receivers.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.receivers.get(i);
a.info.processName=fixProcessName(pkg.applicationInfo.processName,
a.info.processName);
// 将广播接收器存储到 PMS 的 mReceivers 中
mReceivers.addActivity(a, "receiver");
if (chatty) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
}
...
}

PMS 查询静态注册广播接收器

AMS 在发送广播时,会从 PMS 中查询匹配的静态广播接收器;PMS.queryIntentReceiversInternal 根据广播 Intent ,从 mReceivers 中查询匹配的 ResolveInfo,而 ResolveInfo.activityInfo 存储了对应的广播接收器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// PackageManageServices.java
// PMS.queryIntentReceivers --> queryIntentReceiversInternal
private @NonNull List<ResolveInfo> queryIntentReceiversInternal(
Intent intent, String resolvedType, int flags, int userId,
boolean allowDynamicSplits) {
...
synchronized (mPackages) {
String pkgName = intent.getPackage();
if (pkgName == null) {
// 从 mReceivers 中查询匹配的静态注册广播接收器
final List<ResolveInfo> result = mReceivers.queryIntent(
intent, resolvedType, flags, userId);
return applyPostResolutionFilter(result, instantAppPkgName,
allowDynamicSplits, callingUid, userId);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
// 从 mReceivers 中查询匹配的静态注册广播接收器
final List<ResolveInfo> result=mReceivers.queryIntentForPackage(
intent, resolvedType, flags, pkg.receivers, userId);
return applyPostResolutionFilter(result, instantAppPkgName,
allowDynamicSplits, callingUid, userId);
}
return Collections.emptyList();
}
}

// 自定义类,根据广播 Intent ,查询匹配的 ResolveInfo
final class ActivityIntentResolver extends IntentResolver<
PackageParser.ActivityIntentInfo, ResolveInfo> {
public List<ResolveInfo> queryIntent(Intent intent,
String resolvedType, boolean defaultOnly, int userId) {
if (!sUserManager.exists(userId)) return null;
mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
return super.queryIntent(intent, resolvedType,
defaultOnly, userId);
}

public List<ResolveInfo> queryIntent(Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
mFlags = flags;
return super.queryIntent(intent, resolvedType,
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
userId);
}

public List<ResolveInfo> queryIntentForPackage(Intent intent,
String resolvedType, int flags,
ArrayList<PackageParser.Activity> packageActivities,
int userId) {...}
...
}

protected-broadcast 受保护的广播

AndroidManifest.xml 中声明的 protected-broadcast 受保护广播 ACTION ,表示它们只能被有系统权限的广播接收器接收。在 PackageParser.Package.protectedBroadcasts 中保存,同时 PMS.mProtectedBroadcasts 会做系统全局保存, AMS 发送广播时会查询 PMS 做权限检查,如果没有权限则不会分发给该广播接收器。

动态注册/取消广播接收器流程分析

流程图

0021-broadcast-register-receiver.png

动态注册 ContextImpl/LoadedApk

动态注册时统一由 ContextImpl.registerReceiverInternal 向系统注册广播接收器。这个过程主要功能:

  • BroadCastReceiver 转换为对应的 IIntentReceiver ,用于跨进程通信
  • LoadedApk.getReceiverDispatcher 会将当前 Apk 注册的每个广播接收器保存到 mReceivers 中;如果是有序广播的回调广播接收器则不保存
  • AMS 中注册 IIntentReceiver
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// LoadedApk.java 
private Intent registerReceiverInternal(BroadcastReceiver receiver,
int userId, IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
// BroadCastReceiver 转换为 IIntentReceiver
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(receiver, context,
scheduler, null, true).getIIntentReceiver();
}
}
try {
// 向 AMS 中注册 IIntentReceiver
final Intent intent = ActivityManager.getService()
.registerReceiver(mMainThread.getApplicationThread(),
mBasePackageName, rd, filter, broadcastPermission,
userId, flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

// LoadedApk.java
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>
map = null;
if (registered) {
map = mReceivers.get(context);
if (map != null) {
rd = map.get(r);
}
}
if (rd == null) {
// 新建 ReceiverDispatcher 对象
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
if (registered) {
// 注册的广播接收器都保存到 mReceivers 中
// 如果是有序广播的回调广播接收器则不保存
if (map == null) {
map = new ArrayMap<BroadcastReceiver,
LoadedApk.ReceiverDispatcher>();
mReceivers.put(context, map);
}
map.put(r, rd);
}
} else {
rd.validate(context, handler);
}
rd.mForgotten = false;
return rd.getIIntentReceiver();
}
}

动态注册 AMS

广播接收器动态注册时,广播接收器的相关信息保存在 AMS 中:

  • mRegisteredReceivers
    保存所有动态注册的广播接收器对应的 ReceiverListmRegisteredReceivers 并没有太多作用,注册保存信息,取消注册时从这里删除。
  • mReceiverResolver
    保存所有所有动态注册广播接收器时对应的广播过滤器 BroadcastFilter 。广播发送过程中,会根据 IntentmReceiverResolver 中查找 BroadcastFilter ;每个 BroadcastFilter 都保存了它所属的 ReceiverList ;而 ReceiverList 保存了 BroadCastReceiver 对应的 IIntentReceiver ;动态注册广播接收器事件处理时,使用 IIntentReceiver 处理 onReceive 回调。

主要功能:

  • 获取动态注册广播接收器,应用进程相关信息
  • 处理粘性广播事件
  • BroadCastReceiver 生成对应的 ReceiverListBroadcastFilter
  • ReceiverList 添加到 mRegisteredReceivers
  • BroadcastFilter 添加到 mReceiverResolver
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// ActivityManagerService.java
public Intent registerReceiver(IApplicationThread caller,
String callerPackage, IIntentReceiver receiver,
IntentFilter filter, String permission, int userId,
int flags) {
enforceNotIsolatedCaller("registerReceiver");
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
...
int callingUid;
int callingPid;
...
Intent sticky = allSticky != null ? allSticky.get(0) : null;
...
synchronized (this) {
if (callerApp != null && (callerApp.thread == null
|| callerApp.thread.asBinder() != caller.asBinder())) {
// Original caller already died
return null;
}
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid,
callingUid, userId, receiver);
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
...
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
} else ...
BroadcastFilter bf = new BroadcastFilter(filter, rl,
callerPackage, permission, callingUid, userId,
instantApp, visibleToInstantApps);
rl.add(bf);
...
mReceiverResolver.addFilter(bf);
...
return sticky;
}
}

取消注册 ContextImpl/LoadedApk

取消注册时统一由 ContextImpl.unregisterReceiver 向系统取消注册广播接收器。这个过程主要功能:

  • BroadCastReceiver 转换为对应的 IIntentReceiver ,用于跨进程通信
  • LoadedApk.forgetReceiverDispatcher 会将当前需要取消注册的广播接收器,从 mReceivers 中移除;如果需要调试,会同时将它加入 mUnregisteredReceivers
  • AMS 中取消注册 IIntentReceiver
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
if (mPackageInfo != null) {
// BroadCastReceiver 转换为 IIntentReceiver
// 在 LoadedApk 中从 mReceivers 中移除
IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
getOuterContext(), receiver);
try {
// 向 AMS 中取消广播接收器的注册
ActivityManager.getService().unregisterReceiver(rd);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} else {
throw new RuntimeException("Not supported in system context");
}
}

public IIntentReceiver forgetReceiverDispatcher(Context context,
BroadcastReceiver r) {
synchronized (mReceivers) {
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>
map = mReceivers.get(context);
LoadedApk.ReceiverDispatcher rd = null;
if (map != null) {
rd = map.get(r);
if (rd != null) {
map.remove(r);
// 从 mReceivers 中移除
if (map.size() == 0) {
mReceivers.remove(context);
}
if (r.getDebugUnregister()) {
...
// 如果需要调试,存入 mUnregisteredReceivers 中
mUnregisteredReceivers.put(context, holder);
...
}
rd.mForgotten = true;
return rd.getIIntentReceiver();
}
}
...
}
}

取消注册 AMS

广播接收器取消注册时,从 AMS 中移除对应的数据,主要功能为:

  • mRegisteredReceivers 中移除 ReceiverList
  • mReceiverResolver 中移除 ReceiverList 中所有的 BroadcastFilter
  • 如果还存在没有处理完的广播接收器,触发 BroadcastQueue.processNextBroadcast 继续处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// ActivityManagerService.java
public void unregisterReceiver(IIntentReceiver receiver) {
...
final long origId = Binder.clearCallingIdentity();
try {
boolean doTrim = false;
synchronized(this) {
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl != null) {
final BroadcastRecord r = rl.curBroadcast;
// 还存在没有处理完的广播接收器
if (r != null && r == r.queue.getMatchingOrderedReceiver(r)) {
final boolean doNext = r.queue.finishReceiverLocked(
r, r.resultCode, r.resultData, r.resultExtras,
r.resultAbort, false);
if (doNext) {
doTrim = true;
r.queue.processNextBroadcast(false);
}
}
if (rl.app != null) {
rl.app.receivers.remove(rl);
}
// 移除当前广播接收器对应的所有信息
removeReceiverLocked(rl);
...
}
}
...
} finally {
Binder.restoreCallingIdentity(origId);
}
}

// 移除当前广播接收器对应的所有信息
void removeReceiverLocked(ReceiverList rl) {
mRegisteredReceivers.remove(rl.receiver.asBinder());
for (int i = rl.size() - 1; i >= 0; i--) {
mReceiverResolver.removeFilter(rl.get(i));
}
}

广播发送流程分析

先回顾下基础概念,广播的类型:

  • 普通广播:通过 sendBroadcast 发送的广播
  • 有序广播:通过 sendOrderedBroadcast 发送的广播

系统对广播响应并处理的方式分为:

  • 并行处理
    广播存储位置:BroadcastQueue.mParallelBroadcasts ;并行处理的广播为:普通广播,且它对应的广播接收器一定是动态注册的。
  • 有序处理
    广播存储位置:BroadcastQueue.mOrderedBroadcasts ;有序处理的广播为:有序广播和普通广播(对应的广播接收器是静态注册的)。
    mOrderedBroadcasts 中处理普通广播(对应的广播接收器时静态注册的)非常费解,初看代码时很容易搞错,存储逻辑是在 AMS 调度时决定的。

流程图

  • 广播发送过程,从广播发送所在应用进程进入系统进程 Context -> AMS -> BroadcastQueue

0021-broadcast-sendbroadcast-1.png

  • 广播发送过程,从系统进程进入广播接收器应用所在进程 BroadcastQueue -> ActivityThread -> BroadCastReceiver.onReceive

0021-broadcast-sendbroadcast-2.png

ContextImpl.sendBroadcast 发送普通广播

ContextImpl 对于普通广播并不做特别处理,比较简单,直接将 Intent 和广播发送应用相关信息传递给 AMS ,进入系统来处理分发流程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType=intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess(this);
// 进入 AMS 处理具体的广播发送流程
ActivityManager.getService().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType,
null, Activity.RESULT_OK, null, null, null,
AppOpsManager.OP_NONE, null, false, false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

ContextImpl.sendOrderedBroadcast 发送有序广播

有序广播支持广播接收器回调,所以进入系统 AMS 处理前,会先将 BroadCastReceiver 转换为 IIntentReceiver ,回调广播接收器在 LoadedApk 中不做保存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
void sendOrderedBroadcast(Intent intent, String receiverPermission,
int appOp, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras, Bundle options) {
warnIfCallingFromSystemProcess();
IIntentReceiver rd = null;
if (resultReceiver != null) {
if (mPackageInfo != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
// 将 BroadCastReceiver 转换为 IIntentReceiver
// 回调广播接收器在 LoadedApk 中不做保存
rd = mPackageInfo.getReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
mMainThread.getInstrumentation(), false);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
null, false).getIIntentReceiver();
}
}
String resolvedType=intent.resolveTypeIfNeeded(getContentResolver());
String[] receiverPermissions = receiverPermission == null ? null
: new String[] {receiverPermission};
try {
intent.prepareToLeaveProcess(this);
// 进入 AMS 处理具体的有序广播发送流程
ActivityManager.getService().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, receiverPermissions,
appOp, options, true, false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

AMS.broadcastIntentLocked 广播发送解析

不管是普通广播还是有序广播,在 AMS 中都是进入了 broadcastIntentLocked(Intent, ...) 方法来调度处理的。这个方法中会处理很多系统级广播,比如 Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_REMOVED, Intent.ACTION_TIME_CHANGED 等等,在 AMS 做预处理或者直接处理完毕。该方法主要功能:

  • 各种权限检查
  • 系统广播处理
  • 收集该广播匹配的所有动态注册广播接收器
  • 收集该广播匹配的所有静态注册广播接收器
  • 将广播对应的广播记录存入广播队列(如果是有序广播,会按照优先级先排序再存入)

代码分析(代码有简化和调整位置)如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// ActivityManagerService.java
final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp,
Bundle bOptions, boolean ordered, boolean sticky,
int callingPid, int callingUid, int userId) {
intent = new Intent(intent);
// 各种权限检查,系统广播处理
...
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
// 1. 查询广播对应的所有静态注册的广播接收器
receivers = collectReceiverComponents(intent, resolvedType,
callingUid, users);
...
// 2. 查询广播对应的所有动态注册的广播接收器
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false /*defaultOnly*/, users[i]);
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
// 3. 普通广播对应的动态注册广播接收器列表,新建广播记录对象
// 加入到 mParallelBroadcasts 广播队列
if (!ordered && NR > 0) {
...
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, callerInstantApp,
resolvedType, requiredPermissions, appOp, brOptions,
registeredReceivers, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, userId);
if (DEBUG_BROADCAST)
Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
final boolean replaced = replacePending
&& (queue.replaceParallelBroadcastLocked(r) != null);
// Note: We assume resultTo is null for non-ordered broadcasts.
if (!replaced) {
// 加入到 mParallelBroadcasts 广播队列
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
registeredReceivers = null;
NR = 0;
}

// 其他情况时,合并两个广播接收器列表:
// 即有序广播对应的动态注册广播接收器,
// 和普通广播对应的静态注册广播接收器。
// Merge into one list.
int ir = 0;
// 有序广播对应的广播接收器排序
...
while (ir < NR) {
if (receivers == null) {
receivers = new ArrayList();
}
receivers.add(registeredReceivers.get(ir));
ir++;
}
// resultTo 是有序广播的回调广播接收器
// 4. 将合并的广播接收器列表,新建广播记录对象,
// 加入到 mOrderedBroadcasts 广播队列
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, callerInstantApp,
resolvedType, requiredPermissions, appOp, brOptions,
receivers, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, userId);
...
// 加入到 mOrderedBroadcasts 广播队列
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
...
return ActivityManager.BROADCAST_SUCCESS;
}

BroadcastQueue.processNextBroadcast 广播发送解析

不管是并行处理还是有序处理,在 BroadcastQueue 中都是进入 processNextBroadcast(boolean fromMsg) 方法处理的。该方法主要功能:

  • 并行处理的广播接收器,一次全部处理完
  • 有序广播处理完毕后,处理回调广播接收器
  • 各种权限检查
  • 调用 deliverToRegisteredReceiverLocked 处理所有动态注册的广播接收器
  • 如果是静态广播接收器,开启对应的应用进程
  • 调用 processCurBroadcastLocked 处理所有静态注册的广播接收器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// BroadcastQueue.java
final void processNextBroadcast(boolean fromMsg) {
BroadcastRecord r = null;
...
// 1. mParallelBroadcasts 广播队列中,处理普通广播对应的动态注册的广播接收器
// 特点是:一次调用整个队列全部处理完
while (mParallelBroadcasts.size() > 0) {
r = mParallelBroadcasts.remove(0);
...
final int N = r.receivers.size();
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
...
// 动态注册的广播接收器: target 可以直接强制转换为 BroadcastFilter
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target,
false, i);
}
...
}

// mOrderedBroadcasts 队列中,找到下一个需要处理的广播接收器
boolean looped = false;
do {
// mOrderedBroadcasts 广播队列处理完毕退出
if (mOrderedBroadcasts.size() == 0) {
...
return;
}
r = mOrderedBroadcasts.get(0);
boolean forceReceive = false;
int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
...
if (r.receivers == null || r.nextReceiver >= numReceivers
|| r.resultAbort || forceReceive) {
// No more receivers for this broadcast! Send the final
// result if requested...
// 有序广播全部处理完毕,执行回调 BroadCastReceiver
if (r.resultTo != null) {
try {
if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
"Finishing broadcast [" + mQueueName + "] "
+ r.intent.getAction() + " app=" + r.callerApp);
performReceiveLocked(r.callerApp, r.resultTo,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, false, false, r.userId);
r.resultTo = null;
} catch (RemoteException e) {
...
}
}

...
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
"Finished with ordered broadcast " + r);
...
mOrderedBroadcasts.remove(0);
r = null;
looped = true;
continue;
}
} while (r == null);

// Get the next receiver...
int recIdx = r.nextReceiver++;
...
final Object nextReceiver = r.receivers.get(recIdx);
// 2. mOrderedBroadcasts 队列中,下一个广播接收器是动态注册的
// 类型检查,它对应的一定是有序广播,处理完后返回
if (nextReceiver instanceof BroadcastFilter) {
// Simple case: this is a registered receiver who gets
// a direct call.
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Delivering ordered ["
+ mQueueName + "] to registered "
+ filter + ": " + r);
deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
...
return;
}

// 3. mOrderedBroadcasts 队列中,下一个广播接收器是静态注册的
// Hard case: need to instantiate the receiver, possibly
// starting its application process to host it.
ResolveInfo info =
(ResolveInfo)nextReceiver;
ComponentName component = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
...
String targetProcess = info.activityInfo.processName;
ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
info.activityInfo.applicationInfo.uid, false);
...
// Is this receiver's application already running?
// 3.1 如果对应 app 已经在运行,处理广播接收器事件
if (app != null && app.thread != null && !app.killed) {
try {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.versionCode,
mService.mProcessStats);
processCurBroadcastLocked(r, app);
return;
} catch (RuntimeException e) {
...
return;
}
}
// Not running--get it started, to be executed when the app comes up.
// 3.2 如果 app 没有运行,启动该应用进程
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Need to start app ["
+ mQueueName + "] " + targetProcess + " for broadcast " + r);
if ((r.curApp=mService.startProcessLocked(targetProcess,
info.activityInfo.applicationInfo, true,
r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
"broadcast", r.curComponent,
(r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0,
false, false))
== null) {
// 启动失败
...
return;
}

// 3.2 将广播设置为 pending 状态,等到应用启动后
// AMS 会调用 sendPendingBroadcastsLocked 执行该广播接收器事件
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;
...
}

deliverToRegisteredReceiverLocked 方法解析

BroadcastQueue.deliverToRegisteredReceiverLocked 专门用来处理动态注册的广播接收器,最终是在 performReceiveLocked 方法中调用了 ActivityThread.scheduleRegisteredReceiver ,进入广播接收器所在进程处理具体的回调 onReceive。这个阶段主要功能:

  • 各种权限检查
  • 添加完善广播记录
  • 跨进程进入广播接收器所在应用进程,调用 onReceive
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
boolean skip = false;
// 各种权限检查等等
...
// 如果忽略该广播直接返回
if (skip) {
r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
return;
}
// If this is not being sent as an ordered broadcast, then we
// don't want to touch the fields that keep track of the current
// state of ordered broadcasts.
// 有序广播相关处理
if (ordered) {
r.receiver = filter.receiverList.receiver.asBinder();
r.curFilter = filter;
filter.receiverList.curBroadcast = r;
r.state = BroadcastRecord.CALL_IN_RECEIVE;
if (filter.receiverList.app != null) {
// Bump hosting application to no longer be in background
// scheduling class. Note that we can't do that if there
// isn't an app... but we can only be in that case for
// things that directly call the IActivityManager API, which
// are already core system stuff so don't matter for this.
r.curApp = filter.receiverList.app;
filter.receiverList.app.curReceivers.add(r);
mService.updateOomAdjLocked(r.curApp, true);
}
}
try {
if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
"Delivering to " + filter + " : " + r);
if (filter.receiverList.app != null
&& filter.receiverList.app.inFullBackup) {
...
} else {
// 处理动态注册的广播接收器
performReceiveLocked(filter.receiverList.app,
filter.receiverList.receiver, new Intent(r.intent),
r.resultCode, r.resultData, r.resultExtras,
r.ordered, r.initialSticky, r.userId);
}
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
}
} catch (RemoteException e) {
Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
...
}
}

void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser)
throws RemoteException {
// Send the intent to the receiver asynchronously
// using one-way binder calls.
if (app != null) {
if (app.thread != null) {
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
try {
// 跨进程通信,进入应用所在进程处理动态注册的广播接收器
app.thread.scheduleRegisteredReceiver(receiver, intent,
resultCode, data, extras, ordered, sticky,
sendingUser, app.repProcState);
} catch (RemoteException ex) {
...
}
} else {
// Application has died. Receiver doesn't exist.
throw new RemoteException("app.thread must not be null");
}
} else {
receiver.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
}
}

ActivityThread.scheduleRegisteredReceiver 方法解析

每个应用的主线程中 ActivityThread.scheduleRegisteredReceiver 来执行广播处理事件,performReceive 对应的是 LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive 方法。

1
2
3
4
5
6
7
8
public void scheduleRegisteredReceiver(IIntentReceiver receiver, 
Intent intent, int resultCode, String dataStr,
Bundle extras, boolean ordered, boolean sticky,
int sendingUser, int processState) throws RemoteException {
updateProcessState(processState, false);
receiver.performReceive(intent, resultCode, dataStr, extras,
ordered, sticky, sendingUser);
}

processCurBroadcastLocked 方法解析

BroadcastQueue.processCurBroadcastLocked 专门处理静态注册的广播接收器。该方法主要功能:

  • BroadCastReceiver 子类存储到 intent
  • 跨进程进入静态广播接收器所在进程,通过反射调用 onReceive
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app) throws RemoteException {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " for app " + app);
...
r.receiver = app.thread.asBinder();
r.curApp = app;
app.curReceivers.add(r);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
mService.updateLruProcessLocked(app, false, null);
mService.updateOomAdjLocked();

// Tell the application to launch this receiver.
// 将 BroadCastReceiver 子类存储到 intent 中
r.intent.setComponent(r.curComponent);

boolean started = false;
try {
...
// 跨进程通信,进入应用所在进程处理静态注册的广播接收器
app.thread.scheduleReceiver(new Intent(r.intent),
r.curReceiver,
mService.compatibilityInfoForPackageLocked(
r.curReceiver.applicationInfo),
r.resultCode, r.resultData, r.resultExtras,
r.ordered, r.userId, app.repProcState);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r
+ " DELIVERED for app " + app);
started = true;
} finally {
if (!started) {
...
}
}
}

ActivityThread.scheduleReceiver 方法解析

ActivityThread.scheduleReceiver 处理静态注册的广播接收器,从 intent 中获取具体的广播接收器子类组件名,在 handleReceiver 中使用反射技术生成对应的实例对象,并调用其 onReceive 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data,
Bundle extras, boolean sync, int sendingUser, int processState){
updateProcessState(processState, false);
// 新建 ReceiverData 对象
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
sync, false, mAppThread.asBinder(), sendingUser);
r.info = info;
r.compatInfo = compatInfo;
sendMessage(H.RECEIVER, r);
}

private void handleReceiver(ReceiverData data) {
...
// 从 intent 中取出 BroadCastReceiver 子类的组件名
String component = data.intent.getComponent().getClassName();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
IActivityManager mgr = ActivityManager.getService();
Application app;
BroadcastReceiver receiver;
ContextImpl context;
try {
app = packageInfo.makeApplication(false, mInstrumentation);
context = (ContextImpl) app.getBaseContext();
if (data.info.splitName != null) {
context = (ContextImpl) context.
createContextForSplit(data.info.splitName);
}
// 反射,生成对应的 BroadCastReceiver 子类实例对象
java.lang.ClassLoader cl = context.getClassLoader();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);
receiver = (BroadcastReceiver)cl.loadClass(component)
.newInstance();
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(...);
data.sendFinished(mgr);
throw new RuntimeException(...);
}

try {
...
// 调用 onReceive 方法
sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(...);
data.sendFinished(mgr);
if (!mInstrumentation.onException(receiver, e)) {
throw new RuntimeException(...);
}
} finally {
sCurrentBroadcastIntent.set(null);
}

if (receiver.getPendingResult() != null) {
data.finish();
}
}

AMS.finishReceiver 结束广播

所有的广播接收器处理完毕后,最终会调用系统 ActivityManagerService.finishReceiver 结束整个流程。结束流程前会再次检查确认,是否还有广播接收器没有处理完(静态注册的广播接收器,如果应用没有启动,会先启动应用进程),存在的话就触发 BroadcastQueue.processNextBroadcast 继续分发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// ActivityManagerService.java
public void finishReceiver(IBinder who, int resultCode,
String resultData, Bundle resultExtras,
boolean resultAbort, int flags) {
...
final long origId = Binder.clearCallingIdentity();
try {
boolean doNext = false;
BroadcastRecord r;

// 再次检查,如果还存在没有处理完的广播接收器
// 触发 processNextBroadcast 继续分发广播
synchronized(this) {
BroadcastQueue queue =
(flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
? mFgBroadcastQueue : mBgBroadcastQueue;
r = queue.getMatchingOrderedReceiver(who);
if (r != null) {
doNext = r.queue.finishReceiverLocked(r, resultCode,
resultData, resultExtras, resultAbort, true);
}
}

if (doNext) {
r.queue.processNextBroadcast(false);
}
trimApplications();
} finally {
Binder.restoreCallingIdentity(origId);
}
}

广播 ANR

processNextBroadcast 中可以看到,广播的 ANR 只会出现在有序处理的广播队列 mOrderedBroadcasts 中,也就是普通广播匹配的动态注册的广播接收器不会出现 ANR

  • setBroadcastTimeoutLocked :设置广播超时延时消息
  • broadcastTimeoutLocked :当广播接收者等待时间过长,触发 ANR 机制
  • cancelBroadcastTimeoutLocked :当广播正常执行完毕清除

超时时间计算方式:从队列中取出有效广播开始计时,直到所有的广播接收器处理完毕,才取消计时。
示例:发送一个有序广播,AndroidManifest.xml 中静态注册的广播接收器和一个动态注册的广播接收器都能匹配到,同时有序广播带有回调广播接收器,也就是说该广播一共会有三个 BroadCastReceiver.onReceive 响应处理。看对应的 Log 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 1. AMS.broadcastIntent 发送广播
06-17*.163: D/XMT(1485): ***********AMS: broadcastIntent##########
06-17*.163: V/ActivityManager(1485): Broadcast: Intent { act=broadcast.service.order flg=0x10 (has extras) } ordered=true userid=0
06-17*.163: V/ActivityManager(1485): Enqueueing broadcast: broadcast.service.order replacePending=false
// 2. 广播是后台广播
06-17*.163: I/ActivityManager(1485): Broadcast intent Intent { act=broadcast.service.order flg=0x10 (has extras) } on background queue
// 3. 存入 BroadcastQueue.mOrderedBroadcasts 中
06-17*.163: V/ActivityManager(1485): Enqueueing ordered broadcast BroadcastRecord{46a4f31 u0 broadcast.service.order}: prev had 0
06-17*.163: I/ActivityManager(1485): Enqueueing broadcast broadcast.service.order
06-17*.164: V/BroadcastQueue(1485): Schedule broadcasts [background]: current=false
06-17*.164: V/BroadcastQueue(1485): Received BROADCAST_INTENT_MSG
// 4. 进入 BroadcastQueue.processNextBroadcast 处理具体的广播, mOrderedBroadcasts 中只有一个广播
06-17*.164: V/BroadcastQueue(1485): processNextBroadcast [background]: 0 parallel broadcasts, 1 ordered broadcasts
// 5. 从 mOrderedBroadcasts 中取出有效广播
06-17*.164: V/BroadcastQueue(1485): Processing ordered broadcast [background] BroadcastRecord{46a4f31 u0 broadcast.service.order}
// 6. 有序处理广播 ANR 开始计时
06-17*.164: V/BroadcastQueue(1485): Submitting BROADCAST_TIMEOUT_MSG [background] for BroadcastRecord{46a4f31 u0 broadcast.service.order} at 40095097
// 7. deliverToRegisteredReceiverLocked 开始处理动态注册的广播接收器
06-17*.164: V/BroadcastQueue(1485): Delivering ordered [background] to registered BroadcastFilter{d73ca43 u0 ReceiverList{a3cf3f2 9397 com.ymzs.androidbasicknowledge:broadcast/10076/u0 remote:550afd}}: BroadcastRecord{46a4f31 u0 broadcast.service.order}
06-17*.165: I/BroadcastQueue(1485): Delivering to BroadcastFilter{d73ca43 u0 ReceiverList{a3cf3f2 9397 com.ymzs.androidbasicknowledge:broadcast/10076/u0 remote:550afd}} : BroadcastRecord{46a4f31 u0 broadcast.service.order}
// 8. 动态注册的广播接收器响应 onReceive
06-17*.168: D/XMT:BroadcastService(9397): mActionOrderBroadcastReceiver: onReceive = order
// 9. 动态注册广播接收器响应完毕后,调用 finishReceiver 结束广播流程
06-17*.169: V/ActivityManager(1485): Finish receiver: android.os.BinderProxy@550afd
// 10. 结束广播流程时,发现 mOrderedBroadcasts 中还有广播没有处理完毕
// 触发 processNextBroadcast 继续分发广播
06-17*.169: V/BroadcastQueue(1485): processNextBroadcast [background]: 0 parallel broadcasts, 1 ordered broadcasts
// 11. processCurBroadcastLocked 开始处理静态注册的广播接收器
06-17*.169: V/BroadcastQueue(1485): Process cur broadcast BroadcastRecord{46a4f31 u0 broadcast.service.order} for app ProcessRecord{64ad616 9368:com.ymzs.androidbasicknowledge/u0a76}
06-17*.170: V/BroadcastQueue(1485): Delivering to component ComponentInfo{com.ymzs.androidbasicknowledge/com.ymzs.androidbasicknowledge.ipc.BroadcastReceiverMy}: BroadcastRecord{46a4f31 u0 broadcast.service.order}
06-17*.171: V/BroadcastQueue(1485): Process cur broadcast BroadcastRecord{46a4f31 u0 broadcast.service.order} DELIVERED for app ProcessRecord{64ad616 9368:com.ymzs.androidbasicknowledge/u0a76}
// 12. 静态注册的广播接收器响应 onReceive
06-17*.175: D/XMT:BroadcastReceiverMy(9368): BroadcastReceiverMy: onReceive = order
// 13. 静态注册广播接收器响应完毕后,调用 finishReceiver 结束广播流程
06-17*.176: V/ActivityManager(1485): Finish receiver: android.os.BinderProxy@61c0b97
// 14. 结束广播流程时,发现 mOrderedBroadcasts 中还有广播没有处理完毕
// 触发 processNextBroadcast 继续分发广播,处理有序广播的回调
06-17*.176: V/BroadcastQueue(1485): processNextBroadcast [background]: 0 parallel broadcasts, 1 ordered broadcasts
// 15. 有序广播的回调广播接收器响应 onReceive
06-17*.176: D/XMT:BroadcastActivity(9397): mResultBroadcastReceiver: onReceive = order
06-17*.176: I/BroadcastQueue(1485): Finishing broadcast [background] broadcast.service.order app=ProcessRecord{64ad616 9368:com.ymzs.androidbasicknowledge/u0a76}
// 17. 有序处理广播 ANR 计时取消
06-17*.177: V/BroadcastQueue(1485): Cancelling BROADCAST_TIMEOUT_MSG
06-17*.177: V/BroadcastQueue(1485): Finished with ordered broadcast BroadcastRecord{46a4f31 u0 broadcast.service.order}

示例

静态注册广播接收器

  • BroadCastReceiver 子类文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class BroadcastReceiverMy extends BroadcastReceiver {

    private static final String TAG = "XMT:BroadcastReceiverMy";

    @Override
    public void onReceive(Context context, Intent intent) {
    if (intent != null){
    // broadcast ANR 60s
    //Log.d(TAG, "BroadcastReceiverMy: sleep...");
    //try{
    // Thread.sleep(65*1000);
    //} catch(Exception e){}

    String value = intent.getStringExtra("key");
    Log.d(TAG, "BroadcastReceiverMy: onReceive = " + value);
    }
    }
    }
  • AndroidManifest.xml 中声明
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <receiver
    android:name=".ipc.BroadcastReceiverMy"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
    <action android:name="broadcast.service.normal"></action>
    </intent-filter>
    <intent-filter>
    <action android:name="broadcast.service.order"></action>
    </intent-filter>
    </receiver>

动态注册广播接收器

动态注册和取消注册广播必须在生命周期中成对出现,比如在 onCreate/onDestroy, onResume/onPause, onStart/onStop 对应出现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
private boolean registeredOrder;
private boolean registeredNormal;
private BroadcastReceiver mActionOrderBroadcastReceiver
= new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
String value = intent.getStringExtra("key");
Log.d(TAG, "mActionOrderBroadcastReceiver: onReceive = "
+ value);
setResultData("mActionOrderBroadcastReceiver:From Service");
}
}
};

private BroadcastReceiver mActionNormalBroadcastReceiver
= new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null){
String value = intent.getStringExtra("key");
Log.d(TAG, "mActionNormalBroadcastReceiver: onReceive = "
+ value);
}
}
};

@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: ");
IntentFilter intentFilter =
new IntentFilter(BroadcastActivity.BROADCAST_ACTION_ORDER);
registerReceiver(mActionOrderBroadcastReceiver, intentFilter);
registeredOrder = true;

intentFilter =
new IntentFilter(BroadcastActivity.BROADCAST_ACTION_NORMAL);
registerReceiver(mActionNormalBroadcastReceiver, intentFilter);
registeredNormal = true;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
doLongWork();
return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
if (registeredOrder){
unregisterReceiver(mActionOrderBroadcastReceiver);
mActionOrderBroadcastReceiver = null;
registeredOrder = false;
}
if (registeredNormal){
unregisterReceiver(mActionNormalBroadcastReceiver);
mActionNormalBroadcastReceiver = null;
registeredNormal = false;
}
}

广播发送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 发送有序广播,并包含回调广播接收器
private void sendOrderBroadcast(){
Log.d(TAG, "sendOrderBroadcast: ");
Intent intent = new Intent(BROADCAST_ACTION_ORDER);
intent.putExtra("key", "order");
sendOrderedBroadcast(intent, null, mResultBroadcastReceiver,
null, 0, null, null);
}

private BroadcastReceiver mResultBroadcastReceiver
= new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
String result = getResultData();
mTvResultReceiver.setText(result);
}
};

// 发送普通广播
private void sendNormalBroadcast(){
Log.d(TAG, "sendNormalBroadcast: sendNormalBroadcast");
Intent intent = new Intent(BROADCAST_ACTION_NORMAL);
intent.putExtra("key", "normal");
sendBroadcast(intent);
}

小结

广播接收器静态注册过程

静态注册的广播接收器,是开机时 PMS 启动后解析扫描所有包时注册的,保存在每个包的 PackageParser.Package.receivers 中,系统 PMS.mReceivers 会全局保存所有静态注册的广播接收器。 AMS 中并不会保存静态注册的广播接收器信息,而是直接向 PMS 中查询。

AMS 中存储的广播相关信息

  • 广播队列:前台广播队列 mFgBroadcastQueue 和后台广播队列 mBgBroadcastQueue
  • 广播接收器哈希表 mRegisteredReceivers:所有动态注册的广播接收器
  • 广播过滤器符号表 mReceiverResolver:所有动态注册的广播过滤器
1
2
3
4
5
6
BroadcastQueue mFgBroadcastQueue;
BroadcastQueue mBgBroadcastQueue;

final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
= new IntentResolver<BroadcastFilter, BroadcastFilter>() {...}

权限检查

广播在发送的过程中,会有大量的权限检查,比如 AMS.broadcastIntentLocked, BroadcastQueue.processNextBroadcast, BroadcastQueue.deliverToRegisteredReceiverLocked 都会反复做权限检查。

广播接收器优先级

数字越大表示优先级越高,接收有序广播时优先级高的先接收到。

  • 静态注册广播接收器
    1
    2
    3
    4
    5
    <receiver android:name=".smsReceiver">
    <intent-filter android:priority="1000">
    <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
    </intent-filter>
    </receiver>
  • 动态注册广播接收器
    1
    2
    3
    4
    IntentFilter intentFilter = new IntentFilter(
    "android.provider.Telephony.SMS_RECEIVED");
    intentFilter.setPriority(1000);
    registerReceiver(broadcastReceiver, intentFilter);

广播接收器响应

广播接收器回调 onReceive 触发响应的位置

  • 静态注册的广播接收器
    ActivityThread.handleReceiver 中使用反射,触发 onReceive 方法。静态注册的广播接收器并不会对应 ReceiverDispatcher
  • 动态注册的广播接收器
    动态注册的广播接收器对应一个 ReceiverDispatcher ,通过它找到 LoadedApk.Args ,在 Runnable.run 中触发 onReceive 方法。

前后台广播及 ANR

广播发送时,通过 Intent 是否设置 FLAG_RECEIVER_FOREGROUND 来区分,如果设置了表示前台广播,对应 ANR 超时为 10 秒;默认为后台广播,对应超时为 60 秒。
广播的 ANR 是会出现在有序处理广播队列中,在 BroadcastQueue.processNextBroadcast 中计算的,从有序队列 mOrderedBroadcasts 取出有效广播后开始计时,直到有序广播匹配的所有广播接收器包括有序广播的回调广播接收器,全部处理完毕才会取消计时。具体可以看“广播 ANR” 这一节的 Log 分析。
注意:如果广播接收器的 onReceive 是在主线程中处理,同时还会受到 Activity 超时 5 秒产生 ANR 的限制!也就是说等不到 60 秒,可能 Activity 就出现 ANR 了。如果 onReceive 有耗时任务,请新开线程处理。

有序广播

  • 可以被终止
    优先级高的广播接收者接收到后,可以通过 abortBroadcast 来终止继续向下传递广播。
  • 可以有回调 BroadCastReceiver
    广播接收器回调,发送有序广播时,可以同时指定一个 BroadCastReceiver 回调;当有序广播全部被执行完后,会触发这个回调。也就是说有序广播,在顺序接收过程中,每个广播接收者都可以在回调 BroadCastReceiver 中向发送者写回数据。

广播发送过程

  • 整个广播发送及响应过程都是异步的,大量使用 Handler 异步处理
  • 源码中可以看到大量 synchronized 关键字,而且大多使用 AMS 作为对象锁,所以系统处理广播的过程有大量同步过程

并行处理和有序处理

  • mParallelBroadcasts 广播队列
    存储的广播为普通广播(对应的广播接收器是动态注册的),该队列的所有广播都是并行处理的,在 processNextBroadcast 中一次全部处理完。
  • mOrderedBroadcasts 广播队列
    存储的广播为有序广播和普通广播(对应的广播接收器时静态注册的)该队列的所有广播都是有序处理的,在 processNextBroadcast 中从队列中取出一个有效广播,处理完一个广播接收器后,会触发 AMS.finishReceiver 结束整个广播过程。但是 finishReceiver 方法每次都会调用 BroadcastQueue.finishReceiverLocked 检查 mOrderedBroadcasts 是否全部处理完毕。如果没有,调用 processNextBroadcast 继续从有序队列中取出广播处理。具体可以参考“广播 ANR” 中的 Log 分析。

进程和线程间交互

  • Handler 线程间异步通信
  • LocalBroadcastManager 同一个应用相同进程内异步通信,本质上仍然是通过 Handler 实现的
  • BroadCastReceiver 进程间异步通信,不同应用不同进程间的通信,通过系统广播总线统一管理广播,用户使用很简单方便
  • Messenger 进程间异步通信,相同应用不同进程间的通信,常用于 Activity, Service 不在同一进程时使用
  • AIDL 进程间同步通信

参考文档