Broadcast 分析之 registerReceiver

本文深入探讨了Android中的BroadcastReceiver注册流程,从ContextImpl的涉及,到IIntentReceiver的构造,再到ReceiverDispatcher和AMS的交互。通过AMS的registerReceiverWithFeature方法,广播接收者成功注册,并与过滤器映射,完成在系统中的登记。注销过程与此类似。

Broadcast 分析之 registerReceiver()

注册广播接收者

// frameworks/base/core/java/android/content/Context.java
public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,IntentFilter filter);

最后会调用到 ContextImpl

// frameworks/base/core/java/android/app/ContextImpl.java
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
    return registerReceiver(receiver, filter, null, null);
}
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
                                        IntentFilter filter, String broadcastPermission,
                                        Handler scheduler, Context context, int flags) {
    // frameworks/base/core/java/android/app/ContextImpl.java
    IIntentReceiver rd = null;
    if (receiver != null) {
        if (mPackageInfo != null && context != null) {
            if (scheduler == null) {
                scheduler = mMainThread.getHandler();
            } 
            // 1. 构造 IIntentReceiver, 在这里会传入 receiver 实例,方便后面回调 onReceive()
            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 {
        // 2. 调用 AMS.registerReceiverWithFeature方法注册到AMS, 并把 IIntentReceiver 传递进去
        final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
            mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd,
            filter, broadcastPermission, userId, flags);
        if (intent != null) {
            intent.setExtrasClassLoader(getClassLoader());
            intent.prepareToEnterProcess();
        }
        return intent;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}
  1. 构造 IIntentReceiver
// frameworks/base/core/java/android/app/LoadedApk.java
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
                                             Context context, Handler handler,
                                             Instrumentation instrumentation, boolean registered) {
    synchronized (mReceivers) {
        LoadedApk.ReceiverDispatcher rd = null;
        ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
        if (registered) {
            map = mReceivers.get(context);
            if (map != null) {
                rd = map.get(r);
            }
        }
        if (rd == null) {
            // map 中未缓存,则直接构造
            rd = new ReceiverDispatcher(r, context, handler,
                                        instrumentation, registered);
            if (registered) {
                if (map == null) {
                    map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                    // private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers = new ArrayMap<>();
                    // 保存已注册的广播接收者,
                    // 一个 context 对应多个 map, 
                    // map中: BroadcastReceiver 对应多个 ReceiverDispatcher
                    mReceivers.put(context, map);
                }
                map.put(r, rd);
            }
        } else {
            rd.validate(context, handler);
        }
        rd.mForgotten = false;
        return rd.getIIntentReceiver();
    }
}

ReceiverDispatcher 是 LoadedApk的内部类

// frameworks/base/core/java/android/app/LoadedApk.java
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
                   Handler activityThread, Instrumentation instrumentation,
                   boolean registered) {
    if (activityThread == null) {
        throw new NullPointerException("Handler must not be null");
    }
	// mIIntentReceiver 是 IIntentReceiver.Stub 的子类,作为跨进程通信实体
    mIIntentReceiver = new InnerReceiver(this, !registered);
    mReceiver = receiver;
    mContext = context;
    mActivityThread = activityThread;
    mInstrumentation = instrumentation;
    mRegistered = registered;
    mLocation = new IntentReceiverLeaked(null);
    mLocation.fillInStackTrace();
}
final static class InnerReceiver extends IIntentReceiver.Stub {
    @Override
    public void performReceive(Intent intent, int resultCode, String data,
                               Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
		// 省略部分
        // 实际上这里在其他地方发送广播时,经过一系列处理会被回调
    }
}
  1. 调用 AMS.registerReceiverWithFeature方法注册到AMS, 并把 IIntentReceiver 传递进去
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
                                          String callerFeatureId, IIntentReceiver receiver, IntentFilter filter,
                                          String permission, int userId, int flags) {
    // 省略部分
    synchronized(this) {
        // 省略部分
        ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
        if (rl == null) {
            //根据receiver创建出一个ReceiverList,为啥是个List?因为很有可能一个Receiver可能接受多个广播
            rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                                  userId, receiver);
            if (rl.app != null) {
                final int totalReceiversForApp = rl.app.receivers.size();
                if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
                    throw new IllegalStateException("Too many receivers, total of "
                    + totalReceiversForApp + ", registered for pid: "+ rl.pid + ", callerPackage: " + callerPackage);
                }
                rl.app.receivers.add(rl);
            } else {
                try {
                    receiver.asBinder().linkToDeath(rl, 0);
                } catch (RemoteException e) {
                    return sticky;
                }
                rl.linkedToDeath = true;
            }
            mRegisteredReceivers.put(receiver.asBinder(), rl);
        }
	  //构造出对应的BroadcastFilter,主要为了方便到时候发送端方便寻找到这个接受端
        BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
                                                 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 {
            // //bf被添加到了对应的rl
            rl.add(bf);
            if (!bf.debugCheck()) {
                Slog.w(TAG, "==> For Dynamic broadcast");
            }
            mReceiverResolver.addFilter(bf);
        }
    }
}

在AMS中把广播的对应ReceiverList创建出来,而且与Filter进行映射好,这样广播接受者在AMS中的注册就算完成,销毁的原理大抵相似。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值