Android Broadcast原理分析之registerReceiver详解

  public Intent registerReceiver(IApplicationThread caller, String callerPackage,

  IIntentReceiver receiver, IntentFilter filter, String permission, int userId,

  int flags) {

  enforceNotIsolatedCaller("registerReceiver");

  ArrayList stickyIntents = null;

  ProcessRecord callerApp = null;

  final boolean visibleToInstantApps

  = (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;

  int callingUid;

  int callingPid;

  boolean instantApp;

  synchronized(this) {

  if (caller != null) {

  // 正常来讲caller是发起binder call的客户端进程对应的ApplicationThread对象

  // 如果为null则抛异常

  callerApp = getRecordForAppLocked(caller);

  if (callerApp == null) {

  throw new SecurityException(

  "Unable to find app for caller " + caller

  + " (pid=" + Binder.getCallingPid()

  + ") when registering receiver " + receiver);

  }

  if (callerApp.info.uid != SYSTEM_UID &&

  !callerApp.pkgList.containsKey(callerPackage) &&

  !"android".equals(callerPackage)) {

  throw new SecurityException("Given caller package " + callerPackage

  + " is not running in process " + callerApp);

  }

  callingUid = callerApp.info.uid;

  callingPid = callerApp.pid;

  } else {

  callerPackage = null;

  callingUid = Binder.getCallingUid();

  callingPid = Binder.getCallingPid();

  }

  // 判断caller是否为instant app

  instantApp = isInstantApp(callerApp, callerPackage, callingUid);

  userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,

  ALLOW_FULL_ONLY, "registerReceiver", callerPackage);

  // 获取广播注册的filter中的action封装到list中

  Iterator actions = filter.actionsIterator();

  if (actions == null) {

  ArrayList noAction = new ArrayList(1);

  noAction.add(null);

  actions = noAction.iterator();

  }

  // mStickyBroadcasts是一个二级map

  // 一级key是userId,二级key是广播对应的action,value是广播对应intent的list(一般只有一个intent)

  // 这里是为了查询对于当前user,本次注册的所有action对应的sticky广播的intent

  int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };

  while (actions.hasNext()) {

  String action = actions.next();

  for (int id : userIds) {

  ArrayMap> stickies = mStickyBroadcasts.get(id);

  if (stickies != null) {

  ArrayList intents = stickies.get(action);

  if (intents != null) {

  if (stickyIntents == null) {

  stickyIntents = new ArrayList();

  }

  stickyIntents.addAll(intents);

  }

  }

  }

  }

  }

  ArrayList allSticky = null;

  // 这里不为null表示本次注册的广播中有sticky广播

  if (stickyIntents != null) {

  final ContentResolver resolver = mContext.getContentResolver();

  // 查找匹配的sticky广播

  for (int i = 0, N = stickyIntents.size(); i < N; i++) {

  Intent intent = stickyIntents.get(i);

  // 如果caller是instant app,且intent的flag不允许对instant可见,则跳过

  if (instantApp &&

  (intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {

  continue;

  }

  // If intent has scheme "content", it will need to acccess

  // provider that needs to lock mProviderMap in ActivityThread

  // and also it may need to wait application response, so we

  // cannot lock ActivityManagerService here.

  if (filter.match(resolver, intent, true, TAG) >= 0) {

  if (allSticky == null) {

  allSticky = new ArrayList();

  }

  allSticky.add(intent);

  }

  }

  }

  // 直接把最近的一个匹配到的sticky广播返回

  Intent sticky = allSticky != null ? allSticky.get(0) : null;

  // 广播注册的时候receiver是可以为null的,这种情况下这里直接return

  if (receiver == null) {

  return sticky;

  }

  synchronized (this) {

  // 校验caller进程是否正常

  if (callerApp != null && (callerApp.thread == null

  || callerApp.thread.asBinder() != caller.asBinder())) {

  // Original caller already died

  return null;

  }

  // mRegisteredReceivers中存放了所有的已注册的receiver

  // 每个BroadcastReceiver对应一个InnerReceiver,即Binder对象

  // binder对象做key,value是ReceiverList

  // ReceiverList是一个ArrayList

  ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());

  if (rl == null) {

  rl = new ReceiverList(this, callerApp, callingPid, callingUid,

  userId, receiver);

  if (rl.app != null) {

  rl.app.receivers.add(rl);

  } else {

  try {

  // 如果是新创建的receiver,还需要linkToDeath

  receiver.asBinder().linkToDeath(rl, 0);

  } catch (RemoteException e) {

  return sticky;

  }

  rl.linkedToDeath = true;

  }

  // 放入mRegisteredReceivers

  mRegisteredReceivers.put(receiver.asBinder(), rl);

  } else if (rl.uid != callingUid) {

  throw new IllegalArgumentException(

  "Receiver requested to register for uid " + callingUid

  + " was previously registered for uid " + rl.uid

  + " callerPackage is " + callerPackage);

  } else if (rl.pid != callingPid) {

  throw new IllegalArgumentException(

  "Receiver requested to register for pid " + callingPid

  + " was previously registered for pid " + rl.pid

  + " callerPackage is " + callerPackage);

  } else if (rl.userId != userId) {

  throw new IllegalArgumentException(

  "Receiver requested to register for user " + userId

  + " was previously registered for user " + rl.userId

  + " callerPackage is " + callerPackage);

  }

  // 每一个IntentFilter对应一个BroadcastFilter

  BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,

  permission, callingUid, userId, instantApp, visibleToInstantApps);

  // receiverList中存放了通过这个receiver注册的所有的filter

  // 每调用一次register就会add一次

  rl.add(bf);

  // mReceiverResolver中存放所有的BroadcastFilter

  mReceiverResolver.addFilter(bf);

  // 有匹配的sticky广播,则直接开始调度派发

  if (allSticky != null) {

  ArrayList receivers = new ArrayList();

  receivers.add(bf);

  // 对于每一个sticky广播,创建BroadcastRecord并入队(并行)

  final int stickyCount = allSticky.size();

  for (int i = 0; i < stickyCount; i++) {

  Intent intent = allSticky.get(i);

  // 根据flag是否有FLAG_RECEIVER_FOREGROUND判断入队是前台还是后台队列

  BroadcastQueue queue = broadcastQueueForIntent(intent);

  BroadcastRecord r = new BroadcastRecord(queue, intent, null,

  null, -1, -1, false, null, null, AppOpsManager.OP_NONE, null, receivers,

  null, 0, null, null, false, true, true, -1);

  // 入队,并行队列

  queue.enqueueParallelBroadcastLocked(r);

  // 启动广播的调度,也就是开始派发广播

  queue.scheduleBroadcastsLocked();

  }

  }

  return sticky;

  }

  }