上层接口调用registerReceiver
frameworks\base\core\java\android\content\ContextWrapper.java
@Override public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); }
接着进入 ContextImpl类实现具体的逻辑
@Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { return registerReceiver(receiver, filter, null, null); }
@Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) { return registerReceiverInternal(receiver, getUserId(), filter, broadcastPermission, scheduler, getOuterContext(), 0); }
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context, int flags) { IIntentReceiver rd = null; if (receiver != null) { if (mPackageInfo != null && context != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } 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 { final Intent intent = ActivityManager.getService().registerReceiverWithFeature( mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), AppOpsManager.toReceiverId(receiver), rd, filter, broadcastPermission, userId, flags); if (intent != null) { intent.setExtrasClassLoader(getClassLoader()); // TODO: determine at registration time if caller is // protecting themselves with signature permission intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent), getAttributionSource()); } return intent; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
获取IIntentReceiver 类型的rd对象 ,并获取Intent
IIntentReceiver是一个Binder接口,用于进行跨进程的通信,它的具体实现在
LoadedApk.ReceiverDispatcher.InnerReceiver
frameworks\base\core\java\android\app\LoadedApk.java
static final class ReceiverDispatcher { final static class InnerReceiver extends IIntentReceiver.Stub { } }
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage, String callerFeatureId, String receiverId, IIntentReceiver receiver, IntentFilter filter, String permission, int userId, int flags) { enforceNotIsolatedCaller("registerReceiver"); ArrayList<Intent> 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) { callerApp = getRecordForAppLOSP(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.getPkgList().containsKey(callerPackage) && !"android".equals(callerPackage)) { throw new SecurityException("Given caller package " + callerPackage + " is not running in process " + callerApp); } callingUid = callerApp.info.uid; callingPid = callerApp.getPid(); } else { callerPackage = null; callingUid = Binder.getCallingUid(); callingPid = Binder.getCallingPid(); } instantApp = isInstantApp(callerApp, callerPackage, callingUid); userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage); Iterator<String> actions = filter.actionsIterator(); if (actions == null) { ArrayList<String> noAction = new ArrayList<String>(1); noAction.add(null); actions = noAction.iterator(); } // Collect stickies of users int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) }; while (actions.hasNext()) { String action = actions.next(); for (int id : userIds) { ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id); if (stickies != null) { ArrayList<Intent> intents = stickies.get(action); if (intents != null) { if (stickyIntents == null) { stickyIntents = new ArrayList<Intent>(); } stickyIntents.addAll(intents); } } } } } ArrayList<Intent> allSticky = null; if (stickyIntents != null) { final ContentResolver resolver = mContext.getContentResolver(); // Look for any matching sticky broadcasts... for (int i = 0, N = stickyIntents.size(); i < N; i++) { Intent intent = stickyIntents.get(i); // Don't provided intents that aren't available to instant apps. 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<Intent>(); } allSticky.add(intent); } } } // The first sticky in the list is returned directly back to the client. Intent sticky = allSticky != null ? allSticky.get(0) : null; if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Register receiver " + filter + ": " + sticky); if (receiver == null) { return sticky; } // SafetyNet logging for b/177931370. If any process other than system_server tries to // listen to this broadcast action, then log it. if (callingPid != Process.myPid()) { if (filter.hasAction("com.android.server.net.action.SNOOZE_WARNING") || filter.hasAction("com.android.server.net.action.SNOOZE_RAPID")) { EventLog.writeEvent(0x534e4554, "177931370", callingUid, ""); } } synchronized (this) { IApplicationThread thread; if (callerApp != null && ((thread = callerApp.getThread()) == null || thread.asBinder() != caller.asBinder())) { // Original caller already died return null; } ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (rl == null) { rl = new ReceiverList(this, callerApp, callingPid, callingUid, userId, receiver); if (rl.app != null) { final int totalReceiversForApp = rl.app.mReceivers.numberOfReceivers(); 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.mReceivers.addReceiver(rl); } else { try { receiver.asBinder().linkToDeath(rl, 0); } catch (RemoteException e) { return sticky; } rl.linkedToDeath = true; } 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); } BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId, receiverId, 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 { rl.add(bf); if (!bf.debugCheck()) { Slog.w(TAG, "==> For Dynamic broadcast"); } mReceiverResolver.addFilter(bf); } // Enqueue broadcasts for all existing stickies that match // this filter. if (allSticky != null) { ArrayList receivers = new ArrayList(); receivers.add(bf); final int stickyCount = allSticky.size(); for (int i = 0; i < stickyCount; i++) { Intent intent = allSticky.get(i); BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, null, null, null, -1, -1, false, null, null, null, OP_NONE, null, receivers, null, 0, null, null, false, true, true, -1, false, null, false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */); queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } } return sticky; } }