前言
在上一篇Android 9.0系统源码分析(一)广播的注册,我们具体分析了广播注册的流程,本篇文章我们继续来分析一下广播的注销流程。
源码解析
1、我们在Activity种注销广播的时候,首先也是会触发ContextImpl的unregisterReceiver方法:
framework/base/core/java/android/app/ContextImpl.java
class ContextImpl extends Context {
...
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
if (mPackageInfo != null) {
//0101 获取与该注销广播接收者对应的实现IIntentReceiver接口的Binder对象
IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
getOuterContext(), receiver);
try {
//0102 调用ActivityManagerService对象的方法来进行注销
ActivityManager.getService().unregisterReceiver(rd);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} else {
throw new RuntimeException("Not supported in system context");
}
}
...
}
2、在【注释0101处】调用LoadedApk对象的forgetReceiverDispatcher方法:
public IIntentReceiver forgetReceiverDispatcher(Context context,
BroadcastReceiver r) {
synchronized (mReceivers) {
//0201 获取ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>>中当前设备上下文对应的 ArrayMap<BroadcastReceiver, ReceiverDispatcher>
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
LoadedApk.ReceiverDispatcher rd = null;
if (map != null) {
rd = map.get(r);
if (rd != null) {
//0202 从ArrayMap<BroadcastReceiver, ReceiverDispatcher>种将当前广播接收者所对应的数据移除
map.remove(r);
if (map.size() == 0) {
//0203 如果当前Context对应的ArrayMap为空,则移除该对象
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);
}
RuntimeException ex = new IllegalArgumentException(
"Originally unregistered here:");
ex.fillInStackTrace();
rd.setUnregisterLocation(ex);
holder.put(r, rd);
}
//0204 修改标记位
rd.mForgotten = true;
return rd.getIIntentReceiver();
}
}
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
= mUnregisteredReceivers.get(context);
if (holder != null) {
rd = holder.get(r);
if (rd != null) {
RuntimeException ex = rd.getUnregisterLocation();
throw new IllegalArgumentException(
"Unregistering Receiver " + r
+ " that was already unregistered", ex);
}
}
if (context == null) {
throw new IllegalStateException("Unbinding Receiver " + r
+ " from Context that is no longer in use: " + context);
} else {
throw new IllegalArgumentException("Receiver not registered: " + r);
}
}
}
在该方法中,首先会从mReceivers中获取实现了IIntentReceiver接口的广播接收者封装类,如果存在则将其移除。
3、在【注释0102处】调用ActivityManagerService对象的unregisterReceiver方法来进行注销:
framework/base/service/java/com/android/service/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
...
public void unregisterReceiver(IIntentReceiver receiver) {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Unregister receiver: " + receiver);
final long origId = Binder.clearCallingIdentity();
try {
boolean doTrim = false;
synchronized (this) {
//0301 通过当前receiver获取继承自ArrayList<BroadcastFilter>的ReceiverList
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl != null) {
final BroadcastRecord r = rl.curBroadcast;
//0302 从队列中找到对应的BroadcastRecord对象然后返回。
if (r != null && r == r.queue.getMatchingOrderedReceiver(r)) {
//0303 这里判断是否结束广播接收,如果结束则处理下一条广播。
final boolean doNext = r.queue.finishReceiverLocked(
r, r.resultCode, r.resultData, r.resultExtras,
r.resultAbort, false);
if (doNext) {
doTrim = true;
//0304 处理下一条广播
r.queue.processNextBroadcast(false);
}
}
if (rl.app != null) {
// 从广播接收器对应的进程中移除
rl.app.receivers.remove(rl);
}
//0305 移除对应广播的所有过滤器
removeReceiverLocked(rl);
if (rl.linkedToDeath) {
rl.linkedToDeath = false;
rl.receiver.asBinder().unlinkToDeath(rl, 0);
}
}
}
// If we actually concluded any broadcasts, we might now be able
// to trim the recipients' apps from our working set
if (doTrim) {
trimApplications();
return;
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
...
//0305 移除对应广播的所有过滤器
void removeReceiverLocked(ReceiverList rl) {
mRegisteredReceivers.remove(rl.receiver.asBinder());
for (int i = rl.size() - 1; i >= 0; i--) {
mReceiverResolver.removeFilter(rl.get(i));
}
}
...
}
4、从广播队列中获取对应的BroadcastRecord:
- 在【注释0302】处调用BroadcastQueue的getMatchingOrderedReceiver方法,从队列中找到对应的BroadcastRecord对象然后返回。
- 在【注释0303】处判断是否结束广播接收,如果结束则处理下一条广播。
framework/base/service/java/com/android/service/am/BroadcastQueue.java
public final class BroadcastQueue {
...
//0302 从队列中找到对应的BroadcastRecord对象然后返回
public BroadcastRecord getMatchingOrderedReceiver(IBinder receiver) {
if (mOrderedBroadcasts.size() > 0) {
final BroadcastRecord r = mOrderedBroadcasts.get(0);
if (r != null && r.receiver == receiver) {
return r;
}
}
return null;
}
...
//0303 判断是否结束广播接收
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;
if (state == BroadcastRecord.IDLE) {
Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
}
r.receiver = null;
r.intent.setComponent(null);
if (r.curApp != null && r.curApp.curReceivers.contains(r)) {
r.curApp.curReceivers.remove(r);
}
if (r.curFilter != null) {
r.curFilter.receiverList.curBroadcast = null;
}
r.curFilter = null;
r.curReceiver = null;
r.curApp = null;
mPendingBroadcast = null;
r.resultCode = resultCode;
r.resultData = resultData;
r.resultExtras = resultExtras;
if (resultAbort && (r.intent.getFlags() & Intent.FLAG_RECEIVER_NO_ABORT) == 0) {
r.resultAbort = resultAbort;
} else {
r.resultAbort = false;
}
if (waitForServices && r.curComponent != null && r.queue.mDelayBehindServices
&& r.queue.mOrderedBroadcasts.size() > 0
&& r.queue.mOrderedBroadcasts.get(0) == r) {
ActivityInfo nextReceiver;
if (r.nextReceiver < r.receivers.size()) {
Object obj = r.receivers.get(r.nextReceiver);
nextReceiver = (obj instanceof ActivityInfo) ? (ActivityInfo) obj : null;
} else {
nextReceiver = null;
}
// Don't do this if the next receive is in the same process as the current one.
if (receiver == null || nextReceiver == null
|| receiver.applicationInfo.uid != nextReceiver.applicationInfo.uid
|| !receiver.processName.equals(nextReceiver.processName)) {
// In this case, we are ready to process the next receiver for the current broadcast,
// but are on a queue that would like to wait for services to finish before moving
// on. If there are background services currently starting, then we will go into a
// special state where we hold off on continuing this broadcast until they are done.
if (mService.mServices.hasBackgroundServicesLocked(r.userId)) {
Slog.i(TAG, "Delay finish: " + r.curComponent.flattenToShortString());
r.state = BroadcastRecord.WAITING_SERVICES;
return false;
}
}
}
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;
}
...
}
5、处理当前广播的下一条广播,移除对应广播的所有过滤器
- 在【注释0304】处处理下一条广播,关于processNextBroadcast方法,我们会在下一篇章中具体介绍
- 在【注释0305】处移除对应广播的所有过滤器