服务端Intent执行过程:
Sticky:这个类型的BroadCast表示某些Intent需要被保留,当新的应用起来后,需要关注这个消息,但是呢,又不需要启动这个应用来接收此消息,比如耳机插入等消息。
这个函数的主要作用就是根据这个Intent的特点,构造BroadCastRecord加入到不同的列表,等待被处理;
这样发送就到了下面这个函数中了:
控制到了scheduleBroadcastsLocked这里,它的逻辑很简单:
private final void scheduleBroadcastsLocked() {
if (mBroadcastsScheduled) {
return;
}
mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
mBroadcastsScheduled = true;
}
先 判断mBroadcastsScheduled是否为真,如果为真就直接返回,这个变量主要是实现scheduleBroadcastsLocked和 processNextBroadcast之间的顺序执行,后面会看到在processNextBroadcast函数里面会把它设置为false; 下面就是通过BROADCAST_INTENT_MSG消息放入到消息队列里面,最后传递给mHandler,从这个角度来说Intent最后也是通过线程本身的消息队列来实现Intent的分发的;
消息分发过程:
mHandler收到BROADCAST_INTENT_MSG这个消息后便调用processNextBroadcast(boolean fromMsg)将消息分发出去了。下面介绍一下这个函数的流程:
1, 先判断fromMsg,如果是通过消息发送过来的就为真,否则为假; 如果为真mBroadcastsScheduled = false,这样的话在函数scheduleBroadcastsLocked里面就可以再次发送BROADCAST_INTENT_MSG的消息从而触 发processNextBroadcast函数被再次调用;
2, 先判断mParallelBroadcasts是否为空,不为空就开始调用这个列表里面的receivers来接收消息,这个过程后面在串行intent 的时候也会碰到,我们留到后面讨论,这里只需要知道它通过一个while循环把Intent发送给关注这个Intent的所有的receivers;
3, 再判断 mPendingBroadcast是否为空,如果不为空,就表示先前发送的串行的Intent还没有处理完毕,一般出现这种可能是因为我们要发送到的 receiver还没有启动,所以需要先启动这个activity,然后等待起来的这个activity处理,这时候,这个 mPendingBroadcast就为true;如果发送这种情况需要判断这个Activity是否死了,如果死了,那么就把 mPendingBroadcast设为false,否则就直接返回,继续等待;
4, 接下来就顺序的从 mOrderedBroadcasts里面取出BroadCastRecord消息,然后对这个消息的receiver一个一个的调用其接收流程,注意这 里要把这个BroadCast的所有的receivers串行发送,都发送完了,才会进入到下一个BroadCastRecord消息;对于这个消息的处 理,先判断其接收者是不是BroadFilter,如果是,就调用deliverToRegisteredReceiver来接收,它的处理流程和前面的 处理并行BroadCast一样。
5,如果不是BroadCast Filter,就需要找出这个reiver所在的进程,这时候通常就是一个IntentFilter所在的进程,如果这个进程活着,那么就调用processCurBroadcastLocked(r, app)来处理。否则需要先启动这个进程,这就是startProcessLocked做的事情,然后设置mPendingBroadcast = r,这样等应用起来它会处理这个消息,后面会有进一步的说明;
到这里这个函数就结束了,比较复杂,里面还有一些安全的检查等等,上面遗留了三个问题:
A)deliverToRegisteredReceiver的处理流程; B)processCurBroadcastLocked的处理流程; C)startProcessLocked以后的进程如何处理这个唤醒它的Intent;
deliverToRegisteredReceiver
这里也分为这个receiver是否启动,如果已经启动就通过binder调用到了接收 activity的进程里面了。
processCurBroadcastLocked的逻辑
它和deliverToRegisteredReceive的最终差别,只在于一个调用的是ScheduleRegisterdReceiver,一个是scheduleReceiver,这两个函数最后都会进入到目标activity的线程;
processCurBroadcastLocked
从这里可以看出最后通过Process.start启动了ActivityThread.java的进程,我们看看这个线程启动后的执行逻辑 首先是在进入主循环之前调用attachApplication通过binder调用进入到activityManagerService.java的进程; 这 个服务器进程在把我们先前设置的mPendingBroadcast设置为null,表示这个pending的broadcat已经得到处理了,然后调用 processCurBroadcastLocked来处理这个broadcast消息,最后通过
app.thread.scheduleReceiver进入到目标线程的接收流程;:
OK,到这里的话所有的发送分发流程已经结束了,剩下的就是两个接收函数还没有讨论一个就是ScheduleRegisterdReceiver,一个是scheduleReceiver;
Android Intent 解析之二,布布扣,bubuko.com