LockedApk中有一个mReceivers对象,以Context为key, HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>为value。每一个Context都有一个这样的hashmap,key就是receiver,value是ReceiverDispatcher。每一个receiver都对应一个ReceiverDispatcher。
总结:就是创建了一个RD对象(ReceiverDispatcher为了之后AMS和收到广播之后远程调用和可以通过handler插入到消息队列中去处理),这个是在LockedApk中创建的,首先LockedApk有一个mReceivers属性,这个属性里面存放的是key是Context,value是这个上下文中所有注册了receiver的集合,key是receiver,value是RD,这个RD构造方法里面保存了hander以便收到消息之后添加到消息队列中,RD里面有一个静态类InnerReceiver继承自这个类IIntentReceiver.Stub是个代理所以可以通过他进行AMS到Rd中的通信
3.在完成了mPackageInfo.getReceiverDispatcher()创建InnerReceiver对象后,继续调用了AMS的registerReceiver方法
拆开进行分析:
(1)首先获取注册的进程信息
(2)接着迭代filter的actions进行调用getStickLocked函数查找一下有没有对应的sticky intent列表存在。
sticky intent列表:我们在最后一次调用sendStickyBroadcast函数来发送某个Action类型的广播时,系统会把代表这个广播的Intent保存下来,这样,后来调用registerReceiver来注册相同Action类型的广播接收器,就会得到这个最后发出的广播。这就是为什么叫做Sticky Intent了,这个最后发出的广播虽然被处理完了,但是仍然被粘住在ActivityManagerService中,以便下一个注册相应Action类型的广播接收器还能继承处理。
(3)接下来把广播接收器receiver保存一个ReceiverList列表中,这个列表的宿主进程是rl.app,在ActivityManagerService中,用一个进程记录块来表示这个应用程序进程,它里面有一个列表receivers,专门用来保存这个进程注册的广播接收器。接着,又把这个ReceiverList列表以receiver为Key值保存在ActivityManagerService的成员变量mRegisteredReceivers中,这些都是为了方便在收到广播时,快速找到对应的广播接收器的。
(4)上面只是把广播接收器receiver保存起来了,但是还没有把它和filter关联起来,这里就创建一个BroadcastFilter来把广播接收器列表rl和filter关联起来,然后保存在ActivityManagerService中的成员变量mReceiverResolver中去。
这个方法内部,首先获取了最后一个粘性消息(如果有多个action,取最后一个action的最后一次粘性消息,在最后进行返回这个粘性消息。如果注册的receiver传入的是null只传入了actions,那么会直接返回这个最后的粘性消息),接着通过AMS的本地集合变量mRegisteredReceivers通过receiver(key)获取rl(ReceiverList就是value)获取不到进行创建rl,rl构造方法中传入了进程记录块(callerApp)和Binder调用者的uid和pid,还有receiver。创建完后之后把当前rl添加到rl的进程记录块里面的receivers中,然后将receiver为key,rl为value保存添加到mRegisteredReceivers中;
receivers保存完之后开始保存filter,创建一个BroadcastFilter(将filter和rl传入),接着把bf添加到rl中,并把bf添加到AMS本地集合mReceiverResolver中。
这样注册过程就完成了。