当我们通过registerReceiver注册广播的时候,其实是使用的Context来注册的,前面”activity启动流程”,我们已经知道Context的实现类是ContextImpl,所以广播的注册是从ContextImpl中开始的

广播的注册流程

@Overridepublic Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {        return registerReceiver(receiver, filter, null, null);}@Overridepublic Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,            String broadcastPermission, Handler scheduler) {        return registerReceiverInternal(receiver, getUserId(),                filter, broadcastPermission, scheduler, getOuterContext());}@Overridepublic Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,            IntentFilter filter, String broadcastPermission, Handler scheduler) {        return registerReceiverInternal(receiver, user.getIdentifier(),                filter, broadcastPermission, scheduler, getOuterContext());}private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,            IntentFilter filter, String broadcastPermission,            Handler scheduler, Context context) {        IIntentReceiver rd = null;        if (receiver != null) {            // mPackageInfo是一个LoadedApk实例,一个应用进程,就对应一个LoadedApk实例            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 {            // 通过AMS注册广播,并且传递上面获取的InnerReceiver对象            return ActivityManagerNative.getDefault().registerReceiver(                    mMainThread.getApplicationThread(), mBasePackageName,                    rd, filter, broadcastPermission, userId);        } catch (RemoteException e) {            return null;        }}

可以看到所有的处理都来自registerReceiverInternal方法,可以看到上面一大段操作都是给IIntentReceiver赋值,说明这个对象很重要,我们来看看IIntentReceiver

rd = mPackageInfo.getReceiverDispatcher(                    receiver, context, scheduler,                    mMainThread.getInstrumentation(), true);

ReceiverDispatcher是LoadedApk的一个内部类,其内部有一个InnerReceiver类
final static class InnerReceiver extends IIntentReceiver.Stub

我们看下LoadedApk#getReceiverDispatcher方法

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) {                // 先从mReceivers集合中取出当前应用BroadcastReceiver对应的ReceiverDispatcher                map = mReceivers.get(context);                if (map != null) {                    rd = map.get(r);                }            }            // 若系统中的mReceivers集合中,么有当前BroadcastReceiver对应的ReceiverDispatcher,则创建并put到mReceivers            if (rd == null) {                rd = new ReceiverDispatcher(r, context, handler,                        instrumentation, registered);                if (registered) {                    if (map == null) {                        map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();                        mReceivers.put(context, map);                    }                    map.put(r, rd);                }            } else {                // 验证广播发送者的context和handler是否一致                rd.validate(context, handler);            }            rd.mForgotten = false;            return rd.getIIntentReceiver(); // 返回一个InnerReceiver对象,这个对象是在ReceiverDispatcher构造方法中被初始化的。        }    }

在LoadedApk中维护了两个map集合,每一个Context对象对应唯一的ArrayMap,也就是说对于每一个应用,都又一个唯一的ArrayMap来保存其注册的广播

private final ArrayMap> mReceivers        = new ArrayMap>();private final ArrayMap> mUnregisteredReceivers        = new ArrayMap>();

看下InnerReceiver类

final static class InnerReceiver extends IIntentReceiver.Stub {            final WeakReference mDispatcher;            final LoadedApk.ReceiverDispatcher mStrongRef;            InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {                mDispatcher = new WeakReference(rd);                mStrongRef = strong ? rd : null;            }            public void performReceive(Intent intent, int resultCode, String data,                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {                LoadedApk.ReceiverDispatcher rd = mDispatcher.get();                if (ActivityThread.DEBUG_BROADCAST) {                    int seq = intent.getIntExtra("seq", -1);                    Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq                            + " to " + (rd != null ? rd.mReceiver : null));                }                if (rd != null) {                    rd.performReceive(intent, resultCode, data, extras,                            ordered, sticky, sendingUser);                } else {                    // The activity manager dispatched a broadcast to a registered                    // receiver in this process, but before it could be delivered the                    // receiver was unregistered.  Acknowledge the broadcast on its                    // behalf so that the system's broadcast sequence can continue.                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,                            "Finishing broadcast to unregistered receiver");                    IActivityManager mgr = ActivityManagerNative.getDefault();                    try {                        if (extras != null) {                            extras.setAllowFds(false);                        }                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());                    } catch (RemoteException e) {                        Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");                    }                }            }        }

最终还是交给了AMS处理注册广播的操作
首先在AMS中维护了下面两个集合

final SparseArray>> mStickyBroadcasts =            new SparseArray>>();final HashMap mRegisteredReceivers = new HashMap<>();public Intent registerReceiver(IApplicationThread caller, String callerPackage,            IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {        enforceNotIsolatedCaller("registerReceiver");        ArrayList stickyIntents = null;        ProcessRecord callerApp = null;        int callingUid;        int callingPid;        synchronized(this) {             .....            // 对当前调用进程做权限检查            userId = handleIncomingUser(callingPid, callingUid, userId,                    true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage);            // 这个filter就是我们通过registerReceiver(BroadcastReceiver receiver, IntentFilter filter)传递进来的filter            Iterator actions = filter.actionsIterator();            if (actions == null) {                ArrayList noAction = new ArrayList(1);                noAction.add(null);                actions = noAction.iterator();            }            // 保存当前所有粘性广播的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);                        }                    }                }            }        }        // 添加所有有对应处理者的粘性广播到allSticky集合中        ArrayList 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);                // 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);                }            }        }        // 当receiver为null,直接返回第一个粘性广播        Intent sticky = allSticky != null ? allSticky.get(0) : null;        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Register receiver " + filter + ": " + sticky);        if (receiver == null) {            return sticky;        }        synchronized (this) {            if (callerApp != null && (callerApp.thread == null                    || callerApp.thread.asBinder() != caller.asBinder())) {                // 调用者已经死亡,直接返回                return null;            }            // 第一次注册某个广播,这里返回值是null            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.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);            } else if (rl.pid != callingPid) {                throw new IllegalArgumentException(                        "Receiver requested to register for pid " + callingPid                        + " was previously registered for pid " + rl.pid);            } else if (rl.userId != userId) {                throw new IllegalArgumentException(                        "Receiver requested to register for user " + userId                        + " was previously registered for user " + rl.userId);            }            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,                    permission, callingUid, userId);            rl.add(bf);            if (!bf.debugCheck()) {                Slog.w(TAG, "==> For Dynamic broadcast");            }            mReceiverResolver.addFilter(bf);            //所有匹配该filter的sticky广播执行入队操作            //如果没有使用sendStickyBroadcast,则allSticky=null。            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, -1, -1, null, null, AppOpsManager.OP_NONE, null, receivers,                            null, 0, null, null, false, true, true, -1);                    //该广播加入到并行广播队列                    queue.enqueueParallelBroadcastLocked(r);                    //调度广播,发送BROADCAST_INTENT_MSG消息,触发处理下一个广播。                    queue.scheduleBroadcastsLocked();                }            }            return sticky;        }}

广播注册流程总结

广播的注册过程:
1. ContextImpl#registerReceiver——-> ContextImpl#registerReceiverInternal
在registerReceiverInternal方法中,创建IIntentReceiver,IIntentReceiver主要用来和AMS服务段远程通信的。

A. 创建IIntentReceiver
在LoadedApk#getReceiverDispatcher方法中,通过rd.getIIntentReceiver()返回一个IIntentReceiver实现类,其实就是InnerReceiver,
在返回之前做了下面的操作:
map.put(r, rd);
一个InnerReceiver对应一个ReceiverDispatcher,这个在后面广播接收的时候会使用到。

B. 通过AMS的registerReceiver注册广播,并且传递创建好的InnerReceiver对象

C. 在AMS中,添加InnerReceiver和接收者队列到mRegisteredReceivers集合中
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
mRegisteredReceivers.put(receiver.asBinder(), rl);

广播的发送过程

同样的首先看下ContextImpl类

@Overridepublic void sendBroadcast(Intent intent) {        warnIfCallingFromSystemProcess();        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());        try {            intent.prepareToLeaveProcess();            // 通过AMS的broadcastIntent方法发送广播            ActivityManagerNative.getDefault().broadcastIntent(                    mMainThread.getApplicationThread(), intent, resolvedType, null,                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,                    getUserId());        } catch (RemoteException e) {            throw new RuntimeException("Failure from system", e);        }}

进入AMS

public final int broadcastIntent(IApplicationThread caller,            Intent intent, String resolvedType, IIntentReceiver resultTo,            int resultCode, String resultData, Bundle resultExtras,            String[] requiredPermissions, int appOp, Bundle options,            boolean serialized, boolean sticky, int userId) {        // 检查当前inent的合法性        enforceNotIsolatedCaller("broadcastIntent");        synchronized(this) {            intent = verifyBroadcastLocked(intent);            final ProcessRecord callerApp = getRecordForAppLocked(caller);            final int callingPid = Binder.getCallingPid();            final int callingUid = Binder.getCallingUid();            final long origId = Binder.clearCallingIdentity();            // 通过broadcastIntentLocked发送广播            int res = broadcastIntentLocked(callerApp,                    callerApp != null ? callerApp.info.packageName : null,                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,                    requiredPermissions, appOp, null, serialized, sticky,                    callingPid, callingUid, userId);            Binder.restoreCallingIdentity(origId);            return res;        }}

继续看下ActivityManagerService#broadcastIntentLocked方法:

private final int broadcastIntentLocked(ProcessRecord callerApp,            String callerPackage, Intent intent, String resolvedType,            IIntentReceiver resultTo, int resultCode, String resultData,            Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle options,            boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {        intent = new Intent(intent);        // 被stop的包不会接收广播        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);        // 必须等到开机结束        if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);        }        userId = handleIncomingUser(callingPid, callingUid, userId,                true, ALLOW_NON_FULL, "broadcast", callerPackage);        // 确保接收该广播的user处于running状态,否则直接跳过        if (userId != UserHandle.USER_ALL && !isUserRunningLocked(userId, false)) {            if ((callingUid != Process.SYSTEM_UID                    || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)                    && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {                Slog.w(TAG, "Skipping broadcast of " + intent                        + ": user " + userId + " is stopped");                return ActivityManager.BROADCAST_FAILED_USER_STOPPED;            }        }        BroadcastOptions brOptions = null;        if (options != null) {            brOptions = new BroadcastOptions(options);            if (brOptions.getTemporaryAppWhitelistDuration() > 0) {                // See if the caller is allowed to do this.  Note we are checking against                // the actual real caller (not whoever provided the operation as say a                // PendingIntent), because that who is actually supplied the arguments.                if (checkComponentPermission(                        android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,                        Binder.getCallingPid(), Binder.getCallingUid(), -1, true)                        != PackageManager.PERMISSION_GRANTED) {                    String msg = "Permission Denial: " + intent.getAction()                            + " broadcast from " + callerPackage + " (pid=" + callingPid                            + ", uid=" + callingUid + ")"                            + " requires "                            + android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;                    Slog.w(TAG, msg);                    throw new SecurityException(msg);                }            }        }        // 判断当前包是否又权限发送该广播        int callingAppId = UserHandle.getAppId(callingUid);        if (callingAppId == Process.SYSTEM_UID || callingAppId == Process.PHONE_UID            || callingAppId == Process.SHELL_UID || callingAppId == Process.BLUETOOTH_UID            || callingAppId == Process.NFC_UID || callingUid == 0) {            // Always okay.        } else if (callerApp == null || !callerApp.persistent) {            try {                if (AppGlobals.getPackageManager().isProtectedBroadcast(                        intent.getAction())) {                    String msg = "Permission Denial: not allowed to send broadcast "                            + intent.getAction() + " from pid="                            + callingPid + ", uid=" + callingUid;                    Slog.w(TAG, msg);                    throw new SecurityException(msg);                } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(intent.getAction())) {                    // Special case for compatibility: we don't want apps to send this,                    // but historically it has not been protected and apps may be using it                    // to poke their own app widget.  So, instead of making it protected,                    // just limit it to the caller.                    if (callerApp == null) {                        String msg = "Permission Denial: not allowed to send broadcast "                                + intent.getAction() + " from unknown caller.";                        Slog.w(TAG, msg);                        throw new SecurityException(msg);                    } else if (intent.getComponent() != null) {                        // They are good enough to send to an explicit component...  verify                        // it is being sent to the calling app.                        if (!intent.getComponent().getPackageName().equals(                                callerApp.info.packageName)) {                            String msg = "Permission Denial: not allowed to send broadcast "                                    + intent.getAction() + " to "                                    + intent.getComponent().getPackageName() + " from "                                    + callerApp.info.packageName;                            Slog.w(TAG, msg);                            throw new SecurityException(msg);                        }                    } else {                        // Limit broadcast to their own package.                        intent.setPackage(callerApp.info.packageName);                    }                }            } catch (RemoteException e) {                Slog.w(TAG, "Remote exception", e);                return ActivityManager.BROADCAST_SUCCESS;            }        }        // 处理和package相关的,如果当前包被移除,则需要移除对应的activity等        final String action = intent.getAction();        if (action != null) {            switch (action) {                case Intent.ACTION_UID_REMOVED:                case Intent.ACTION_PACKAGE_REMOVED:                case Intent.ACTION_PACKAGE_CHANGED:                case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:                case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:                    // Handle special intents: if this broadcast is from the package                    // manager about a package being removed, we need to remove all of                    // its activities from the history stack.                    if (checkComponentPermission(                            android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,                            callingPid, callingUid, -1, true)                            != PackageManager.PERMISSION_GRANTED) {                        String msg = "Permission Denial: " + intent.getAction()                                + " broadcast from " + callerPackage + " (pid=" + callingPid                                + ", uid=" + callingUid + ")"                                + " requires "                                + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;                        Slog.w(TAG, msg);                        throw new SecurityException(msg);                    }                    switch (action) {                        case Intent.ACTION_UID_REMOVED:                            final Bundle intentExtras = intent.getExtras();                            final int uid = intentExtras != null                                    ? intentExtras.getInt(Intent.EXTRA_UID) : -1;                            if (uid >= 0) {                                mBatteryStatsService.removeUid(uid);                                mAppOpsService.uidRemoved(uid);                            }                            break;                        case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:                            // If resources are unavailable just force stop all those packages                            // and flush the attribute cache as well.                            String list[] =                                    intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);                            if (list != null && list.length > 0) {                                for (int i = 0; i < list.length; i++) {                                    forceStopPackageLocked(list[i], -1, false, true, true,                                            false, false, userId, "storage unmount");                                }                                mRecentTasks.cleanupLocked(UserHandle.USER_ALL);                                sendPackageBroadcastLocked(                                        IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list,                                        userId);                            }                            break;                        case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:                            mRecentTasks.cleanupLocked(UserHandle.USER_ALL);                            break;                        case Intent.ACTION_PACKAGE_REMOVED:                        case Intent.ACTION_PACKAGE_CHANGED:                            Uri data = intent.getData();                            String ssp;                            if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {                                boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);                                boolean fullUninstall = removed &&                                        !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);                                final boolean killProcess =                                        !intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);                                if (killProcess) {                                    forceStopPackageLocked(ssp, UserHandle.getAppId(                                            intent.getIntExtra(Intent.EXTRA_UID, -1)),                                            false, true, true, false, fullUninstall, userId,                                            removed ? "pkg removed" : "pkg changed");                                }                                if (removed) {                                    sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,                                            new String[] {ssp}, userId);                                    if (fullUninstall) {                                        mAppOpsService.packageRemoved(                                                intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);                                        // Remove all permissions granted from/to this package                                        removeUriPermissionsForPackageLocked(ssp, userId, true);                                        removeTasksByPackageNameLocked(ssp, userId);                                        mBatteryStatsService.notePackageUninstalled(ssp);                                    }                                } else {                                    cleanupDisabledPackageComponentsLocked(ssp, userId, killProcess,                                            intent.getStringArrayExtra(                                                    Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));                                }                            }                            break;                    }                    break;                case Intent.ACTION_PACKAGE_ADDED:                    // Special case for adding a package: by default turn on compatibility mode.                    Uri data = intent.getData();                    String ssp;                    if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {                        final boolean replacing =                                intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);                        mCompatModePackages.handlePackageAddedLocked(ssp, replacing);                        try {                            ApplicationInfo ai = AppGlobals.getPackageManager().                                    getApplicationInfo(ssp, 0, 0);                            mBatteryStatsService.notePackageInstalled(ssp,                                    ai != null ? ai.versionCode : 0);                        } catch (RemoteException e) {                        }                    }                    break;                case Intent.ACTION_TIMEZONE_CHANGED:                    // If this is the time zone changed action, queue up a message that will set                    // the timezone of all currently running processes. This message will get                    // queued up before the broadcast happens.                    Message msg = mHandler.obtainMessage(UPDATE_TIME_ZONE);                    msg.obj = intent.getStringExtra("time-zone");                    mHandler.sendMessage(msg);                    break;                // 系统action,时间发生变化,发送消息                case Intent.ACTION_TIME_CHANGED:                    // If the user set the time, let all running processes know.                    final int is24Hour =                            intent.getBooleanExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1                                    : 0;                    mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));                    BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();                    synchronized (stats) {                        stats.noteCurrentTimeChangedLocked();                    }                    break;                case Intent.ACTION_CLEAR_DNS_CACHE:                    mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);                    break;                case Proxy.PROXY_CHANGE_ACTION:                    ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);                    mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));                    break;            }        }        // 保存所有的粘性广播到mStickyBroadcasts中        if (sticky) {            if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,                    callingPid, callingUid)                    != PackageManager.PERMISSION_GRANTED) {                String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="                        + callingPid + ", uid=" + callingUid                        + " requires " + android.Manifest.permission.BROADCAST_STICKY;                Slog.w(TAG, msg);                throw new SecurityException(msg);            }            if (requiredPermissions != null && requiredPermissions.length > 0) {                Slog.w(TAG, "Can't broadcast sticky intent " + intent                        + " and enforce permissions " + Arrays.toString(requiredPermissions));                return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;            }            if (intent.getComponent() != null) {                throw new SecurityException(                        "Sticky broadcasts can't target a specific component");            }            // We use userId directly here, since the "all" target is maintained            // as a separate set of sticky broadcasts.            if (userId != UserHandle.USER_ALL) {                // But first, if this is not a broadcast to all users, then                // make sure it doesn't conflict with an existing broadcast to                // all users.                ArrayMap> stickies = mStickyBroadcasts.get(                        UserHandle.USER_ALL);                if (stickies != null) {                    ArrayList list = stickies.get(intent.getAction());                    if (list != null) {                        int N = list.size();                        int i;                        for (i=0; iif (intent.filterEquals(list.get(i))) {                                throw new IllegalArgumentException(                                        "Sticky broadcast " + intent + " for user "                                        + userId + " conflicts with existing global broadcast");                            }                        }                    }                }            }            ArrayMap> stickies = mStickyBroadcasts.get(userId);            if (stickies == null) {                stickies = new ArrayMap<>();                mStickyBroadcasts.put(userId, stickies);            }            ArrayList list = stickies.get(intent.getAction());            if (list == null) {                list = new ArrayList<>();                stickies.put(intent.getAction(), list);            }            final int stickiesCount = list.size();            int i;            for (i = 0; i < stickiesCount; i++) {                if (intent.filterEquals(list.get(i))) {                    // This sticky already exists, replace it.                    list.set(i, new Intent(intent));                    break;                }            }            if (i >= stickiesCount) {                list.add(new Intent(intent));            }        }        int[] users;        if (userId == UserHandle.USER_ALL) {            // Caller wants broadcast to go to all started users.            users = mStartedUserArray;        } else {            // Caller wants broadcast to go to one specific user.            users = new int[] {userId};        }        // 将所有静态注册的广播接收者保存到receivers中,动态注册的广播保存到registeredReceivers中        List receivers = null;        List registeredReceivers = null;        // Need to resolve the intent to interested receivers...        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)                 == 0) {            receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);        }        if (intent.getComponent() == null) {            if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {                // Query one target user at a time, excluding shell-restricted users                UserManagerService ums = getUserManagerLocked();                for (int i = 0; i < users.length; i++) {                    if (ums.hasUserRestriction(                            UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {                        continue;                    }                    List registeredReceiversForUser =                            mReceiverResolver.queryIntent(intent,                                    resolvedType, false, users[i]);                    if (registeredReceivers == null) {                        registeredReceivers = registeredReceiversForUser;                    } else if (registeredReceiversForUser != null) {                        registeredReceivers.addAll(registeredReceiversForUser);                    }                }            } else {                registeredReceivers = mReceiverResolver.queryIntent(intent,                        resolvedType, false, userId);            }        }        // 表示是否替换之前相同的广播,即之前发送过的一个广播,但是接收者还没有接收,此时又发送了一个相同的广播        final boolean replacePending =                (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueing broadcast: " + intent.getAction()                + " replacePending=" + replacePending);        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;        if (!ordered && NR > 0) {            // If we are not serializing this broadcast, then send the            // registered receivers separately so they don't wait for the            // components to be launched.            final BroadcastQueue queue = broadcastQueueForIntent(intent);            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,                    callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,                    appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,                    resultExtras, ordered, sticky, false, userId);            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);            final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);            if (!replaced) {                queue.enqueueParallelBroadcastLocked(r);                queue.scheduleBroadcastsLocked();            }            registeredReceivers = null;            NR = 0;        }        // Merge into one list.        int ir = 0;        if (receivers != null) {            // A special case for PACKAGE_ADDED: do not allow the package            // being added to see this broadcast.  This prevents them from            // using this as a back door to get run as soon as they are            // installed.  Maybe in the future we want to have a special install            // broadcast or such for apps, but we'd like to deliberately make            // this decision.            String skipPackages[] = null;            if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())                    || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())                    || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {                Uri data = intent.getData();                if (data != null) {                    String pkgName = data.getSchemeSpecificPart();                    if (pkgName != null) {                        skipPackages = new String[] { pkgName };                    }                }            } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {                skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);            }            if (skipPackages != null && (skipPackages.length > 0)) {                for (String skipPackage : skipPackages) {                    if (skipPackage != null) {                        int NT = receivers.size();                        for (int it=0; itif (curt.activityInfo.packageName.equals(skipPackage)) {                                receivers.remove(it);                                it--;                                NT--;                            }                        }                    }                }            }            int NT = receivers != null ? receivers.size() : 0;            int it = 0;            ResolveInfo curt = null;            BroadcastFilter curr = null;            while (it < NT && ir < NR) {                if (curt == null) {                    curt = (ResolveInfo)receivers.get(it);                }                if (curr == null) {                    curr = registeredReceivers.get(ir);                }                if (curr.getPriority() >= curt.priority) {                    // Insert this broadcast record into the final list.                    receivers.add(it, curr);                    ir++;                    curr = null;                    it++;                    NT++;                } else {                    // Skip to the next ResolveInfo in the final list.                    it++;                    curt = null;                }            }        }        while (ir < NR) {            if (receivers == null) {                receivers = new ArrayList();            }            receivers.add(registeredReceivers.get(ir));            ir++;        }        if ((receivers != null && receivers.size() > 0)                || resultTo != null) {            BroadcastQueue queue = broadcastQueueForIntent(intent);            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,                    callerPackage, callingPid, callingUid, resolvedType,                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,                    resultData, resultExtras, ordered, sticky, false, userId);            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r                    + ": prev had " + queue.mOrderedBroadcasts.size());            if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,                    "Enqueueing broadcast " + r.intent.getAction());            boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);            if (!replaced) {                queue.enqueueOrderedBroadcastLocked(r);                // 广播的分发,真正发送广播的地方在BroadcastQueue#scheduleBroadcastsLocked中执行的                queue.scheduleBroadcastsLocked();            }        }        return ActivityManager.BROADCAST_SUCCESS;}

下面看下BroadcastQueue#scheduleBroadcastsLocked方法:

public void scheduleBroadcastsLocked() {        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["                + mQueueName + "]: current="                + mBroadcastsScheduled);        if (mBroadcastsScheduled) {            return;        }        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));        mBroadcastsScheduled = true;}private final class BroadcastHandler extends Handler {        public BroadcastHandler(Looper looper) {            super(looper, null, true);        }        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case BROADCAST_INTENT_MSG: {                    if (DEBUG_BROADCAST) Slog.v(                            TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");                    processNextBroadcast(true);                } break;                ......            }        }}final void processNextBroadcast(boolean fromMsg) {        synchronized(mService) {            BroadcastRecord r;            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "processNextBroadcast ["                    + mQueueName + "]: "                    + mParallelBroadcasts.size() + " broadcasts, "                    + mOrderedBroadcasts.size() + " ordered broadcasts");            mService.updateCpuStats();            if (fromMsg) {                mBroadcastsScheduled = false;            }            // 先发送有序广播            while (mParallelBroadcasts.size() > 0) {                r = mParallelBroadcasts.remove(0);                r.dispatchTime = SystemClock.uptimeMillis();                r.dispatchClockTime = System.currentTimeMillis();                final int N = r.receivers.size();                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["                        + mQueueName + "] " + r);                for (int i=0; iif (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,                            "Delivering non-ordered on [" + mQueueName + "] to registered "                            + target + ": " + r);                    // 遍历有序广播,并且逐个发送                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);                }                addBroadcastToHistoryLocked(r);                EventLog.writeEvent(EventLogTags.AM_BROADCAST_FINISHED, mQueueName, 0,                        (r.intent != null) ? r.intent.toString() : "null");                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["                        + mQueueName + "] " + r);            }            // Now take care of the next serialized one...            // If we are waiting for a process to come up to handle the next            // broadcast, then do nothing at this point.  Just in case, we            // check that the process we're waiting for still exists.            if (mPendingBroadcast != null) {                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,                        "processNextBroadcast [" + mQueueName + "]: waiting for "                        + mPendingBroadcast.curApp);                boolean isDead;                synchronized (mService.mPidsSelfLocked) {                    ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);                    isDead = proc == null || proc.crashing;                }                if (!isDead) {                    // It's still alive, so keep waiting                    return;                } else {                    Slog.w(TAG, "pending app  ["                            + mQueueName + "]" + mPendingBroadcast.curApp                            + " died before responding to broadcast");                    mPendingBroadcast.state = BroadcastRecord.IDLE;                    mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;                    mPendingBroadcast = null;                }            }            boolean looped = false;            // 逐个遍历有序广播队列,发送            do {                if (mOrderedBroadcasts.size() == 0) {                    // No more broadcasts pending, so all done!                    mService.scheduleAppGcsLocked();                    if (looped) {                        // If we had finished the last ordered broadcast, then                        // make sure all processes have correct oom and sched                        // adjustments.                        mService.updateOomAdjLocked();                    }                    return;                }                r = mOrderedBroadcasts.get(0);                boolean forceReceive = false;                // 处理超时的广播,如果当前广播发送的时间超时,则直接跳过,接着发送下一个                int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;                if (mService.mProcessesReady && r.dispatchTime > 0) {                    long now = SystemClock.uptimeMillis();                    if ((numReceivers > 0) &&                            (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {                        Slog.w(TAG, "Hung broadcast ["                                + mQueueName + "] discarded after timeout failure:"                                + " now=" + now                                + " dispatchTime=" + r.dispatchTime                                + " startTime=" + r.receiverTime                                + " intent=" + r.intent                                + " numReceivers=" + numReceivers                                + " nextReceiver=" + r.nextReceiver                                + " state=" + r.state);                        //在broadcastTimeoutLocked方法中,同样会发送消息到BroadcastHandler,接着处理下一个广播的发送                        broadcastTimeoutLocked(false); // forcibly finish this broadcast                        forceReceive = true;                        r.state = BroadcastRecord.IDLE;                    }                }                if (r.state != BroadcastRecord.IDLE) {                    if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,                            "processNextBroadcast("                            + mQueueName + ") called when not idle (state="                            + r.state + ")");                    return;                }                if (r.receivers == null || r.nextReceiver >= numReceivers                        || r.resultAbort || forceReceive) {                    // No more receivers for this broadcast!  Send the final                    // result if requested...                    if (r.resultTo != null) {                        try {                            if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,                                    "Finishing broadcast [" + mQueueName + "] "                                    + r.intent.getAction() + " app=" + r.callerApp);                            // 实现广播接收者的回调就在这里                            performReceiveLocked(r.callerApp, r.resultTo,                                new Intent(r.intent), r.resultCode,                                r.resultData, r.resultExtras, false, false, r.userId);                            // Set this to null so that the reference                            // (local and remote) isn't kept in the mBroadcastHistory.                            r.resultTo = null;                        } catch (RemoteException e) {                            r.resultTo = null;                            Slog.w(TAG, "Failure ["                                    + mQueueName + "] sending broadcast result of "                                    + r.intent, e);                        }                    }                    if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");                    cancelBroadcastTimeoutLocked();                    if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,                            "Finished with ordered broadcast " + r);                    // ... and on to the next...                    addBroadcastToHistoryLocked(r);                    EventLog.writeEvent(EventLogTags.AM_BROADCAST_FINISHED, mQueueName, 1,                            (r.intent != null) ? r.intent.toString() : "null");                    // 将已经发送的当前广播从队列中移除                    mOrderedBroadcasts.remove(0);                    r = null;                    looped = true;                    continue;                }            } while (r == null);            // Get the next receiver...            int recIdx = r.nextReceiver++;            .......}

在processNextBroadcast方法中,通过performReceiveLocked最终实现了广播接收者的回调

private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,            Intent intent, int resultCode, String data, Bundle extras,            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {        // Send the intent to the receiver asynchronously using one-way binder calls.        if (app != null) {            if (app.thread != null) {                // If we have an app thread, do the call through that so it is                // correctly ordered with other one-way calls.                app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,                        data, extras, ordered, sticky, sendingUser, app.repProcState);            } else {                // Application has died. Receiver doesn't exist.                throw new RemoteException("app.thread must not be null");            }        } else {            // 这里的receiver就是之前注册广播的时候的InnerReceiver            receiver.performReceive(intent, resultCode, data, extras, ordered,                    sticky, sendingUser);        }}

前面广播注册过程中,我们已经知道主要是添加广播对应的InnerReceiver和ReceiverList到mRegisteredReceivers集合中,这里就找到对应的根据对应的receiver回调其performReceive方法,InnerReceiver#performReceive

public void performReceive(Intent intent, int resultCode, String data,                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {                LoadedApk.ReceiverDispatcher rd = mDispatcher.get();                if (ActivityThread.DEBUG_BROADCAST) {                    int seq = intent.getIntExtra("seq", -1);                    Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq                            + " to " + (rd != null ? rd.mReceiver : null));                }                // 实际上通过ReceiverDispatcher#performReceive                if (rd != null) {                    rd.performReceive(intent, resultCode, data, extras,                            ordered, sticky, sendingUser);                } else {                    // The activity manager dispatched a broadcast to a registered                    // receiver in this process, but before it could be delivered the                    // receiver was unregistered.  Acknowledge the broadcast on its                    // behalf so that the system's broadcast sequence can continue.                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,                            "Finishing broadcast to unregistered receiver");                    IActivityManager mgr = ActivityManagerNative.getDefault();                    try {                        if (extras != null) {                            extras.setAllowFds(false);                        }                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());                    } catch (RemoteException e) {                        Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");                    }                }}

在广播注册的过程中,将广播接收者和存入一个map集合中,一个BroadcastReceiver对应一个ReceiverDispatcher,所有的BroadcastReceiver和ReceiverDispatcher对应一个Context,即同一个应用

private final ArrayMap> mReceivers

看下ReceiverDispatcher#performReceive方法:

public void performReceive(Intent intent, int resultCode, String data,                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {            if (ActivityThread.DEBUG_BROADCAST) {                int seq = intent.getIntExtra("seq", -1);                Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq                        + " to " + mReceiver);            }            // Args是一个线程,这里通过handler和Args线程,在Args线程中实现最终广播接收的回调            Args args = new Args(intent, resultCode, data, extras, ordered,                    sticky, sendingUser);            if (!mActivityThread.post(args)) {                if (mRegistered && ordered) {                    IActivityManager mgr = ActivityManagerNative.getDefault();                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,                            "Finishing sync broadcast to " + mReceiver);                    args.sendFinished(mgr);                }            }}public void run() {                final BroadcastReceiver receiver = mReceiver;                final boolean ordered = mOrdered;                if (ActivityThread.DEBUG_BROADCAST) {                    int seq = mCurIntent.getIntExtra("seq", -1);                    Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()                            + " seq=" + seq + " to " + mReceiver);                    Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered                            + " mOrderedHint=" + ordered);                }                final IActivityManager mgr = ActivityManagerNative.getDefault();                final Intent intent = mCurIntent;                mCurIntent = null;                if (receiver == null || mForgotten) {                    if (mRegistered && ordered) {                        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,                                "Finishing null broadcast to " + mReceiver);                        sendFinished(mgr);                    }                    return;                }                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");                try {                    ClassLoader cl =  mReceiver.getClass().getClassLoader();                    intent.setExtrasClassLoader(cl);                    setExtrasClassLoader(cl);                    receiver.setPendingResult(this);                    // 回调对应BroadcastReceiver的onReceive方法                    receiver.onReceive(mContext, intent);                } catch (Exception e) {                    if (mRegistered && ordered) {                        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,                                "Finishing failed broadcast to " + mReceiver);                        sendFinished(mgr);                    }                    if (mInstrumentation == null ||                            !mInstrumentation.onException(mReceiver, e)) {                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                        throw new RuntimeException(                            "Error receiving broadcast " + intent                            + " in " + mReceiver, e);                    }                }                if (receiver.getPendingResult() != null) {                    finish();                }                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}

好了到此为止,广播的接收流程也走完了,下面总结一下流程。

广播的发送流程总结

广播的发送流程:
1. 在ContextImpl#sendBroadcast中通过Binder机制,调用ActivityManagerService#broadcastIntent

  1. broadcastIntent —-> broadcastIntentLocked
    在broadcastIntentLocked中调用了BroadcastQueue#scheduleBroadcastsLocked方法

  2. 在BroadcastQueue#scheduleBroadcastsLocked中发送一个”BROADCAST_INTENT_MSG”消息到BroadcastHandler处理

  3. BroadcastHandler处理”BROADCAST_INTENT_MSG”消息时候,调用BroadcastQueue#processNextBroadcast方法

  4. 在BroadcastQueue#processNextBroadcast中有一行关键代码:
    // 实现广播接收的回调就在这里
    performReceiveLocked(r.callerApp, r.resultTo,
    new Intent(r.intent), r.resultCode,
    r.resultData, r.resultExtras, false, false, r.userId);

  5. 在BroadcastQueue#performReceiveLocked方法中,通过传递进来的InnerReceiver回调其接收动作
    receiver.performReceive(intent, resultCode, data, extras, ordered,
    sticky, sendingUser);

  6. 在InnerReceiver#performReceive中调用与其对应的ReceiverDispatcher#performReceive
    在广播注册的时候,我们已经知道一个InnerReceiver对应一个唯一的ReceiverDispatcher

  7. 在ReceiverDispatcher#performReceive中通过handler和Args线程中回调对应的onReceive方法
    receiver.onReceive(mContext, intent);

更多相关文章

  1. Android的静态注册广播问题
  2. Android(安卓)NDK之发送短信
  3. Android(安卓)实现发送短信demo
  4. android耳机广播接收
  5. Android使用HttpURLConnection上传文件
  6. Android(安卓)SmsManager(短信管理器),发送短信息
  7. Android短信发送器
  8. 国内目前最全面的介绍——Android中的BroadCastReceiver
  9. android 注册页面实现

随机推荐

  1. 自定义弹窗,dialog
  2. Android异步加载图片详解之方式一(4)
  3. Android(安卓)ViewPager 的简单应用
  4. DialogUtils Material风格对话框工具类
  5. 安卓 图片处理
  6. android打电话简单功能(完整代码)
  7. Android播放视频(三)
  8. 0 - 总述
  9. 4. Android(安卓)URL
  10. Android动态权限列表