您的位置:首页 > 移动开发 > Android开发

[Android]有序广播是如何实现有序循环(五)

2017-08-26 20:46 363 查看

[Android]有序广播是如何实现有序循环(五)

Android有序广播是如何实现有序循环五
平行广播的循环前面已经讲到过

有序广播是如何循环起来的
1 如何将有序广播BroadcastRecord 发送给动态注册的Receiver

2 对于静态注册的Receiver是如何有序循环的

BroadcastRecord 完整的发送

Overview

而对有序广播来说,==原则上每次processNextBroadcast()只会将BroadcastRecord发送给一个receiver而已。当然,此时摘下的receiver既有可能是动态注册的,也有可能是静态的==。

对于动态注册的receiver,目标进程处理完广播之后,会间接调用am.finishReceiver()向AMS发出反馈,关于这一步,前文在讲Args.run()时已有涉及,只是当时主要关心的是里面的receiver.onReceive()一句,现在我们要关心其中的receiver.setPendingResult()一句:

不论任何广播,在APK处理完后,都要通知到AMS做一些收尾工作.

1. 平行广播的循环前面已经讲到过

参考BroadcastQueue如何分发广播(四)


2. 有序广播是如何循环起来的?

2.1 如何将有序广播BroadcastRecord 发送给动态注册的Receiver?

重点是,有序广播是如何循环起来的?

回顾 Ams中创建BroadcastRecord的代码,mReceivers集合中是有两种对象:ResolveInfo/BroadcastFilter

BroadcastFilter 即是动态注册的Receiver

if (nextReceiver instanceof BroadcastFilter) {
// Simple case: this is a registered receiver who gets
// a direct call.
BroadcastFilter filter = (BroadcastFilter)nextReceiver;

deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
if (r.receiver == null || !r.ordered) {
// The receiver has already finished, so schedule to
// process the next one.
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
} else {
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
scheduleTempWhitelistLocked(filter.owningUid,
brOptions.getTemporaryAppWhitelistDuration(), r);
}
}
return;
}


NOTE:

执行流程类似于平行广播,最终也会进入到LoadedApk.ReceiverDispatcher($Args)

区别在于:

deliverToRegisteredReceiverLocked(r, filter, /order/ r.ordered, recIdx) //

最终还是会进入到Args.run(){}

try {
ClassLoader cl =  mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
// 注意,把自己设到BroadcastReceiver的mPendingResult域里了
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
} catch (Exception e) {}

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


frameworks/base/core / java / android / content /BroadcastReceiver.java

if (mType == TYPE_COMPONENT) {
...
} else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
final IActivityManager mgr = ActivityManagerNative.getDefault();
sendFinished(mgr);
}


mType 对于registed广播来说,在注册时就已经决定

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;
}


frameworks/base/core / java / android / content /BroadcastReceiver.java

public void sendFinished(IActivityManager am) {
synchronized (this) {
...
mFinished = true;
try {
// 注册此处的区别,对于ordered广播,需要保留resultCode resultData,resultExtras, mAbortBroadcst等信息,而对于
// 并行广播,无须关注这些
if (mOrderedHint) {
// 将广播结束的消息告知Ams
am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
mAbortBroadcast, mFlags);
} else {
// This broadcast was sent to a component; it is not ordered,
// but we still need to tell the activity manager we are done.
am.finishReceiver(mToken, 0, null, null, false, mFlags);
}
} catch (RemoteException ex) {
}
}
}


ActivityManagerService.java

public void finishReceiver(IBinder who, int resultCode, String resultData,
Bundle resultExtras, boolean resultAbort, int flags) {
try {
boolean doNext = false;
BroadcastRecord r;
synchronized(this) {
BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
? mFgBroadcastQueue : mBgBroadcastQueue;
//
r = queue.getMatchingOrderedReceiver(who);
if (r != null) {
// finishReceiverLocked做善后工作,判断该节点是否还需要继续分发
doNext = r.queue.finishReceiverLocked(r, resultCode,
resultData, resultExtras, resultAbort, true);
}
}
//
if (doNext) {
r.queue.processNextBroadcast(false);
}
} finally {
}
}


BroadcastQueue.java

public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
// 保存之前的状态
final int state = r.state;
final ActivityInfo receiver = r.curReceiver;
r.state = BroadcastRecord.IDLE;

// 这里为什么要做大量的置空操作?
r.receiver = null;
r.intent.setComponent(null);
if (r.curApp != null && r.curApp.curReceiver == r) {
r.curApp.curReceiver = null;
}
if (r.curFilter != null) {
r.curFilter.receiverList.curBroadcast = null;
}
r.curFilter = null;
r.curReceiver = null;
r.curApp = null;
mPendingBroadcast = null;

// 保留上个receiver的操作结果
r.resultCode = resultCode;
r.resultData = resultData;
r.resultExtras = resultExtras;

...
r.curComponent = null;
// We will process the next receiver right now if this is finishing
// an app receiver (which is always asynchronous) or after we have
// come back from calling a receiver.
return state == BroadcastRecord.APP_RECEIVE
|| state == BroadcastRecord.CALL_DONE_RECEIVE;
}


思考:
这里为何要做大量的置空操作?

每次在deliverToRegisteredReceiverLocked,都会在BroadcastRecord保存当前receiver对应信息,

而当发送完成时置空,释放对之前Receiver对应的内存,

下次在deliver时,重置赋值,而且这些信息只对Ordered广播有效

思考:

最后的state 为什么要== APP_RECEIVE/ CALL_DONE_RECEIVE

针对ordered广播在deliver后,都会重置状态,表示该节点的发送状态;当在finish时重置r.state = Idle,以便将此records分发给下一个receiver.

总结:
==至此,一个动态receive的接收就结束了==

2.2 对于静态注册的Receiver是如何有序循环的?

// 对于静态广播的接收是由ActivityThread来分发的

private void handleReceiver(ReceiverData data)
{
. . . . . .
IActivityManager mgr = ActivityManagerNative.getDefault();
BroadcastReceiver receiver;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
data.intent.setExtrasClassLoader(cl);
data.setExtrasClassLoader(cl);
receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
} catch (Exception e) {
. . . . . .
}
try {
. . . . . .
receiver.setPendingResult(data);
receiver.onReceive(context.getReceiverRestrictedContext(), data.intent);
} catch (Exception e) {
. . . . . .
} finally {
sCurrentBroadcastIntent.set(null);
}
if (receiver.getPendingResult() != null) {
data.finish();
}
}


ActivityThread.java

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;
}


BroadcastReceiver.java

public final void finish() {
if (mType == TYPE_COMPONENT) {
final IActivityManager mgr = ActivityManagerNative.getDefault();
if (QueuedWork.hasPendingWork()) {
...
} else {
sendFinished(mgr);
}
} else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
...
}
}


==至此,静态receiver的完整分发流程结束==

总结:
receiver分发完成后,若是需要发送下一个receiver,依然是要回到processNextBroadcast(),而每次process只能发送到一个receiver

3. BroadcastRecord 完整的发送

如何将Broadcast完整的发送给所有的receiver

do{
int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;

// nextReceiver > numReceivers,即表示发送到了该节点的最后一条
if (r.receivers == null || r.nextReceiver >= numReceivers
|| r.resultAbort || forceReceive) {
// No more receivers for this broadcast!  Send the final
// result if requested...
cancelBroadcastTimeoutLocked();

// 添加到Broadcast 记录
addBroadcastToHistoryLocked(r);
if (r.intent.getComponent() == null && r.intent.getPackage() == null
&& (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
// This was an implicit broadcast... let's record it for posterity.
mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
}
// 并且需要将这个操作完成的节点,从list中移除
mOrderedBroadcasts.remove(0);
r = null;
looped = true;
continue;
}
} while ( r != null)


总结:
==当执行到此处表示最后一个receive也分发完成,需要将该节点移除,并处理下一个节点==
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: