broadcoast启动过程

  • content
    {:toc}

    简单使用

braodcast通过静态注册和动态注册两种方式进行使用,这里就不再详细描述

先上个图

图片

ContextImpl通过binder的方式进行通信

开始RTFSC

第一步

自己写的注册类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MainActivity extends AppCompatActivity {

private MyBroadcastReceiver mMyBroadcastReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mMyBroadcastReceiver = new MyBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter(Constant.MY_BROADCAST_ACTION);
//1.动态注册自己写的BroadcastReceiver到AMS中
registerReceiver(mMyBroadcastReceiver, intentFilter);
}
//...
}
1
2
3
public interface Constant {
String MY_BROADCAST_ACTION = "my_broadcast_action";
}

第二步contextWrapper#registerReceiver

contextWrapper#registerReceiver

运用了装饰者设计模式,mBase是ContextImpl的对象

参照:ContextImpl和ContextWrapper(装饰模式)

ContextImpl和ContextWrapper绑定过程

1
2
3
4
5
6
7
8
9
10
11
12
	Context mBase; 

public ContextWrapper(Context base) {
mBase = base;
}
//...
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
//...

其实有个好一点的办法区分,就是找到contextWrapper类,打个断点,看看mBase的类型就好了

第三步ContextImpl#registerReceiver

从第二步,我们已经知道是contextImpl,所以第三步是

ContextImpl#registerReceiver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//...
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}

@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
int flags) {
return registerReceiver(receiver, filter, null, null, flags);
}

@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), 0);
}
//...

一大堆的重载方法(是重写context的抽象方法,相互回调了,就看做为重载方法应该也没毛病)。

最终调用了registerReceiverInternal

第三小步 1.1 ContextImpl#registerReceiverInternal
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 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) {
//1.
scheduler = mMainThread.getHandler();
}
//2.
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 {
//3.ActivityManager.getService()
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();
}
}

这个类没多少内容,全部都copy了下来

  1. 获取ActivityThread的mH这个 handler 对象

  2. IIntentReceiver的binder对象 IIntentReceiver相当于是一个AIDL的接口。2.x的内容和绑定的关系不是很大,就是可能好理解一些,所以我记录了一下2.x的一些内容,实际上回头发送broadcast的时候还是要知道,AMS发送消息回来的时候需要看这些源码

1
2
3
4
5
6
7
8
9
10
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
//...
//2.1
mIIntentReceiver = new InnerReceiver(this, !registered);
//2.1.1 这里同时还存了我们注册的BroadcastReceiver
mReceiver = receiver;
//...
}

​ 2.1 这个里把 ReceiverDispatcher 用 this 传了进行,以便于然后 ,后面AMS那边把IIntentReceiver 这个binder对象传回来的时候进行 调取

ReceiverDispatcher自己的performReceive方法,其实这个里我原来也不太理解,为什么不直接传ReceiverDispatcher对象过去。现在我理解成,因为binder对象是可以通过打包在 Parcel中,通过 Parcel的 writeStrongBinder进行传递的,然后AIDL的方式传递到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
final static class InnerReceiver extends IIntentReceiver.Stub {
//保存了一个mDispatcher
final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
final LoadedApk.ReceiverDispatcher mStrongRef;

InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null;
}

@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 (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
+ " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
}
if (rd != null) {
//然后调用了mDispatcher中的performReceive方法
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
}
//...

​ 2.2 InnerReceiver是ReceiverDispatcher的静态内部类,并且实现了IIntentReceiver的方法。根据AIDL,继承了IIntentReceiver.Stub相当于一个binder对象并且实现了IIntentReceiver的方法,根据多态,然后可以通过IIntentReceiver的方式进行传递

​ 2.3 在往下一步的下一步,我们就能看到接收了,我们重写的 onReceive()

​ ReceiverDispatcher#performReceive

1
2
3
4
5
6
7
8
9
10
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);
//...
// mActivityThread 是 mH ActivityThread的handler
if (intent == null ||
!mActivityThread.post(args.getRunnable())) {
//...
}

​ 2.4 再看args.getRunnable()

1
2
3
4
5
6
7
8
9
10
11
12
13
public final Runnable getRunnable() {
return () -> {
//原来保存好的对象
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;

//...

receiver.setPendingResult(this);
//这个就是那个熟悉的身影了
receiver.onReceive(mContext, intent);
//...
}
  1. ActivityManager.getService() 想当于调用AMS里面对应的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//AIDL绑定,获取AIDL中的Proxy对象
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};

​ 上面代码可以看出,就是个AIDL, asInterface就是返回了一个AIDL中的proxy的对象,这个用来跨进程调用AMS的方法

第四步ActivityManagerService#registerReceiver

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
 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {

//...

//1.sticky的一些判断,然后添加在了mStickyBroadcasts中
//还做了一些uid和pid的判断
if(caller!=null) {
//...
while (actions.hasNext()) {
String action = actions.next();
for (int id : userIds) {
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
if (stickies != null) {
ArrayList<Intent> intents = stickies.get(action);
if (intents != null) {
if (stickyIntents == null) {
stickyIntents = new ArrayList<Intent>();
}
stickyIntents.addAll(intents);
}
}
}

ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
if (stickies == null) {
stickies = new ArrayMap<>();
mStickyBroadcasts.put(userId, stickies);
}
ArrayList<Intent> list = stickies.get(intent.getAction());
if (list == null) {
list = new ArrayList<>();
stickies.put(intent.getAction(), list);
}
final int stickiesCount = list.size();
int i;
for (i = 0; i < stickiesCount; i++) {
if (intent.filterEquals(list.get(i))) {
// This sticky already exists, replace it.
list.set(i, new Intent(intent));
break;
}
}
if (i >= stickiesCount) {
list.add(new Intent(intent));
}
}
}

//...

ArrayList<Intent> allSticky = null;
if (stickyIntents != null) {
final ContentResolver resolver = mContext.getContentResolver();
// Look for any matching sticky broadcasts...
//...
}

// The first sticky in the list is returned directly back to the client.
Intent sticky = allSticky != null ? allSticky.get(0) : null;
if (receiver == null) {
return sticky;
}

synchronized (this) {
if (callerApp != null && (callerApp.thread == null
|| callerApp.thread.asBinder() != caller.asBinder())) {
// Original caller already died
return null;
}
//2.ReceiverList是否存在,如果是空的就创建
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
//...
//3.最后保存了IIntentReceiver的binder对象,但是任然是IIntentReceiver的子类
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
//...

//4.把 rl:ReceiverList 传给了 BroadcastFilter 生成出了bf对象
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
if (rl.containsFilter(filter)) {
Slog.w(TAG, "Receiver with filter " + filter
+ " already registered for pid " + rl.pid
+ ", callerPackage is " + callerPackage);
} else {
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}

//5.把这个自己的action的封装保存了起来,方面后面发送这个action的请求进行发送对应的广播
//所以前面如果有了,就不再加入了
mReceiverResolver.addFilter(bf);
}

// Enqueue broadcasts for all existing stickies that match
// this filter.
// 6.粘性广播,最后如果不为0,就加入到了BroadcastQueue中
if (allSticky != null) {
ArrayList receivers = new ArrayList();
receivers.add(bf);

final int stickyCount = allSticky.size();
for (int i = 0; i < stickyCount; i++) {
Intent intent = allSticky.get(i);
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, null,
null, -1, -1, false, null, null, OP_NONE, null, receivers,
null, 0, null, null, false, true, true, -1);
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}

return sticky;
}
}
}

到此,使用的broadcast在AMS中注册就已经注册完成了

参考

《android源码情景分析》

四大组件之BroadcastRecord

读源码-五分钟理解不了广播机制