解析BroadcastReceiver的注册、发送与接收过程

广播的注册、 发送和接收过程

       广播作为四大组件之 ,使用频率远没有 Activity 高,但是广播的工作过程还是十分有必要了解的。本节主要从三个方面讲解广播工作过程,分别是广播的注册、发送和接收。本文基于Android8.1.0系统分析广播的注册、发送和接收过程。

1. 广播的注册过程

       广播的注册通俗来讲就是广播接受者注册自己感兴趣的广播,广播的注册分为两种形式,分别是静态注册和动态注册,静态注册在应用安装时有PackageManagerService来完成注册过程,关于这一过程本文先不做介绍,本文主要分析广播的动态注册过程。

       想要动态注册广播,需要调用registerReceiver方法,它在ContextWrapper中实现,代码如下所示:

frameworks/base/core/java/android/content/ContextWrapper.java

    @Override
    public Intent registerReceiver(
        BroadcastReceiver receiver, IntentFilter filter) {
        return mBase.registerReceiver(receiver, filter);
    }
        这里 mBase 具体指向就是 Co nte xtlm pl , Contextlmpl 的  register Receiver 方法 有很多重载的方法,但是最终都会调用 registerReceiverInternal方法,代码如下所示:
 
frameworks/base/core/java/android/app/ContextImpl.java
    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) { // ... 1
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                rd = mPackageInfo.getReceiverDispatcher(
                    receiver, context, scheduler,
                    mMainThread.getInstrumentation(), true); // ... 2
            } else {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                rd = new LoadedApk.ReceiverDispatcher(
                        receiver, context, scheduler, null, true).getIIntentReceiver(); // ... 3
            }
        }
        try {
            final Intent intent = ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                    broadcastPermission, userId, flags); // ... 4
            if (intent != null) {
                intent.setExtrasClassLoader(getClassLoader());
                intent.prepareToEnterProcess();
            }
            return intent;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
       在注释1 处判断如果 Loaded Apk  类型的 mPackagel nfo 不 等于 null ,并且 context 不等与 null 就调用注释2 处的代码,通过 mPackageinfo 的  getRece iverDispatcher 方法 获取 rd 对 象,否则就调用注释3处的代码来创建 rd 对象。注释2 和注释3处 的代码的 目的都是要获取 IIntentReceiver 类型的 rd 对象, IIntentReceiver 是一个  Binder 接口,用于广播的跨进程的通 信,它在 Loa ded Apk.ReceiverDi spatc her.InnerR ece iver 中 实现,代码如下所示:
 
frameworks/base/core/java/android/app/LoadedApk.java

    static final class ReceiverDispatcher {

        final static class InnerReceiver extends IIntentReceiver.Stub {
            final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
            final LoadedApk.ReceiverDispatcher mStrongRef;

            InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
                mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                mStrongRef = strong ? rd : null;
            }
            ...

        }
        ...      

    }
       回到 registerReceiverInternal 方法 在注释4 处调用了I Activity Manager 的  registerReceiver 方法,最终会调用 AMS 的 register Receiver 方法,并 llntentReceiver 类型的  rd 传进去, 这里之所以不直接传入 BroadcastReceiver 而是 传入 llntentReceiver , 是 因为注册 广播是一个 跨进程过程, 需要具有跨进程的通信功能的 IlntentReceiver 。接下来分析AMS的register Receiver方法,代码如下所示:
 

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
            int flags) {
        ...
        ArrayList<Intent> stickyIntents = null;
        ProcessRecord callerApp = null;
        ...
        synchronized(this) {
            if (caller != null) {
                callerApp = getRecordForAppLocked(caller); // ... 1
                ...
            } else {
                ...
            }
            ...  
            Iterator<String> actions = filter.actionsIterator(); // ... 2
            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); // ... 3
                        }
                    }
                }
            }
        }

        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); // ... 4
                }
            }
        }

        // 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;
        }

        synchronized (this) {
            ... 
            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); // ... 5
            if (rl == null) {
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver); // ... 6
               ...
            } 
            ...
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps); // ... 7
            rl.add(bf); // ... 8
            if (!bf.debugCheck()) {
                Slog.w(TAG, "==> For Dynamic broadcast");
            }
            mReceiverResolver.addFilter(bf); // ... 9
            ...
            return sticky;
        }
    }
       在注释1处通过 getRecordF or App Locked 方法 得到 ProcessRecord 类型的 caller App 对象, 它用于描述请求 AMS 注册广播接收者的 Activity 所在的应用程序进程。在注释2 处根据传人的 IntentFilter 类型 filter 得到 actions 列表,根据 actions 列表和 userlds (user Ids 可以理解为应用程序的uid )得到所有的粘性广播的 intent ,并在注释3 处传入到 sticky Intents 中。接下来从 sticky Intents 中找到匹配传入的参数 filter 的粘性广播的 intent ,在注释4 处将这些 intent 存入到 all Sticky 列表中,从这里可以看出粘性广播是存储在 AMS 中的。
       在注释5 处获取 ReceiverList 列表 ,如果为空则 在注释6 处创建 Receiver List 继 承自 Array List ,用来存储广播接收 者。在注释 7 处创建 BroadcastFilter 并传入此前创建的  Receiver List  , BroadcastFilter 用来描 述注 册的广 播接 者,并在注释8 处通过 add 将自身 添加到 Receiver List 中 。在注释9处将  BroadcastFilter 加到 IntentRes olver 类型 rnReceiverResolver 中,这 样当 A MS 收到 广播时 就可 以从 m Receiver Resolver 中找到 对应的 广播接者 了,从而达到 了注册 广播 的目的。
 

2. 广播的发送和接收过程

       广播的发送和接收过程分为两个部分来进行讲解,分别是 Contextlmpl 到 AMS 的调用过程和 AMS 到 BroadcastReceiver 的调用过程。

     2.1 ContextImpl到AMS的调用过程

       广播 可以发送多种 类型, 括无序广播(普通广播) 、有序广播 和粘性 广播,  这里以无序广播 为例来讲解广播的 发送过 程。要发送无序广播需要 调用 se ndBroadcast 方法 ,它在 ContextWrapper 中实现,代码如下所示:
 
frameworks/base/core/java/android/content/ContextWrapper.java
    public void sendBroadcast(Intent intent) {
        mBase.sendBroadcast(intent);
    }

       在“解析Service的启动过程”一文章我们分析过,mBase具体指向就是ContextImpl,接下来查看ContextImpl的sendBroadcast方法,代码如下所示:

frameworks/base/core/java/android/app/Contextlmpl.java

    public void sendBroadcast(Intent intent) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        try {
            intent.prepareToLeaveProcess(this);
            ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                    getUserId()); // ... 1
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

       在注释1处最终会调用AMS的broadcastIntent方法,代码如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    public final int broadcastIntent(IApplicationThread caller,
            Intent intent, String resolvedType, IIntentReceiver resultTo,
            int resultCode, String resultData, Bundle resultExtras,
            String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean serialized, boolean sticky, int userId) {
        enforceNotIsolatedCaller("broadcastIntent");
        synchronized(this) {
            // 验证广播是否合法
            intent = verifyBroadcastLocked(intent); // ... 1
            final ProcessRecord callerApp = getRecordForAppLocked(caller);
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            int res = broadcastIntentLocked(callerApp,
                    callerApp != null ? callerApp.info.packageName : null,
                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                    requiredPermissions, appOp, bOptions, serialized, sticky,
                    callingPid, callingUid, userId); // ... 2
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

       在注释1处,首先验证广播是否合法,我们先分析verifyBroadcastLocked方法,代码如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    final Intent verifyBroadcastLocked(Intent intent) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors() == true) { // ... 1
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        int flags = intent.getFlags(); // ... 2

        if (!mProcessesReady) {
            // if the caller really truly claims to know what they're doing, go
            // ahead and allow the broadcast without launching any receivers
            if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) { // ... 3
                // This will be turned into a FLAG_RECEIVER_REGISTERED_ONLY later on if needed.
            } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { // ... 4
                Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
                        + " before boot completion");
                throw new IllegalStateException("Cannot broadcast before boot completed");
            }
        }

        if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
            throw new IllegalArgumentException(
                    "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
        }

        if ((flags & Intent.FLAG_RECEIVER_FROM_SHELL) != 0) {
            switch (Binder.getCallingUid()) {
                case ROOT_UID:
                case SHELL_UID:
                    break;
                default:
                    Slog.w(TAG, "Removing FLAG_RECEIVER_FROM_SHELL because caller is UID "
                            + Binder.getCallingUid());
                    intent.removeFlags(Intent.FLAG_RECEIVER_FROM_SHELL);
                    break;
            }
        }

        return intent;
    }
        在注释1处验证  intent 是否 不为 null 且有文件描述符。 注释2处 获得 intent 中的 flag  。注释3 处如果 系统正 在启 动过程中, 判断如果flag 设置为 FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT(启动检查时 只接受 动态注册的 广播 接收 者) 则不做处 理, 如 果不是则在注释4 处判断如果 flag 没有设置为 FLAG_RECEIVER_REGISTERED_ONLY  ( 只接受 动态注 册的广播接收者)则抛 出异 常。 我们再回到 broadcastln tent 方法 ,在注释2处调 用了 broadcastIntentLocked 方法 , 代码如下所示:
 

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    final int broadcastIntentLocked(ProcessRecord callerApp,
            String callerPackage, Intent intent, String resolvedType,
            IIntentReceiver resultTo, int resultCode, String resultData,
            Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
 ...
 if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            BroadcastQueue queue = broadcastQueueForIntent(intent);
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId); // ... 1

            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());

            final BroadcastRecord oldRecord =
                    replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
            if (oldRecord != null) {
                // Replaced, fire the result-to receiver.
                if (oldRecord.resultTo != null) {
                    final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
                    try {
                        oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
                                oldRecord.intent,
                                Activity.RESULT_CANCELED, null, null,
                                false, false, oldRecord.userId);
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Failure ["
                                + queue.mQueueName + "] sending broadcast result of "
                                + intent, e);

                    }
                }
            } else {
                queue.enqueueOrderedBroadcastLocked(r);
                queue.scheduleBroadcastsLocked(); // ... 2
            }
        } else {
            // There was nobody interested in the broadcast, but we still want to record
            // that it happened.
            if (intent.getComponent() == null && intent.getPackage() == null
                    && (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                // This was an implicit broadcast... let's record it for posterity.
                addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
            }
        }

        return ActivityManager.BROADCAST_SUCCESS;
}

       这里省略了很多代码,前面的工作主要是将动态注册的广播接收者和静态注册的广播接受者按照优先级高低不同存储在不同的列表中,再将这两个列表合并到receivers列表中,这样receivers列表包含了所有广播接受者(无序广播和有序广播)。在注释1处创建BroadcastRecord对象并将receivers传进去,在注释2处调用BroadcastQueue的scheduleBroadcastsLocked方法。

     2.2 AMS到BroadcastReceiver的调用过程

       BroadcastQueue 的  scheduleBroadcastsLocked 方法 的代码如下所示:
 
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
    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)); // ... 1
        mBroadcastsScheduled = true;
    }
       在注释1 处向 BroadcastHandler  类型的  mHandler 对象发送了 BROADCAST_INTENT_MSG 类型 的消息,这个消息 在 BroadcastHandler 的  handleMessage 方法 中进行处理 ,代码如下所示:
 

frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java

    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;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
    }
       在handleMe ssage 方法 中调用了 processNextBroadcast 方法 ,方法对无序 广播和有序广 播分 别进行处理,旨在 将广播发送给广播接收者 ,下面给出 processN extBroadcast 方法中对 无序广播 的处理 部分,代码如下所示:
 

frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java


    final void processNextBroadcast(boolean fromMsg) {
        synchronized(mService) {
            ...
            if (fromMsg) {
                // 已经处理了BROADCAST_INTENT_MSG类型的消息
                mBroadcastsScheduled = false; // ... 1
            }

            // First, deliver any non-serialized broadcasts right away.
            // 遍历存储无序广播的mParallelBroadcasts列表
            while (mParallelBroadcasts.size() > 0) { // ... 2
                // 获取无序广播
                r = mParallelBroadcasts.remove(0); // ... 3
                ...
                for (int i=0; i<N; i++) {
                    Object target = r.receivers.get(i);
                    if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                            "Delivering non-ordered on [" + mQueueName + "] to registered "
                            + target + ": " + r);
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);// ... 4
                }
                ...
            }
            ...
        }
    }
       从前面 BroadcastHandler 方法 中我们 得知传入的 参数 fr omMsg 的值为 true ,因此在注释1 处将 rnBroadcastsScheduled 设置为  flase ,表示对于此前发来的 BROADCAST_ INTENT_ MSG 类型的消息已经处理了。注释2 处的 mParallelBroadcasts 列 表用来存 储无序广播,通过 while 循环将 mParallelBroadcasts 中的无序广播发送给对应的广播接收者。  在注释3处获取 每一 个 mParallelBroadcasts 中存储的 BroadcastRecord 类 型的 r  对象。在注释4 处将这些 r 对象描述的广播发送给对应的广播接收者, deliverToRegisteredReceiverLocked  方法代码 如下所示:
 

frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java


    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
        ...
        try {
            if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
                    "Delivering to " + filter + " : " + r);
            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                // Skip delivery if full backup in progress
                // If it's an ordered broadcast, we need to continue to the next receiver.
                if (ordered) {
                    skipReceiverLocked(r);
                }
            } else {
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId); // ... 1
            }
            if (ordered) {
                r.state = BroadcastRecord.CALL_DONE_RECEIVE;
            }
        } catch (RemoteException e) {
            Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
            if (ordered) {
                r.receiver = null;
                r.curFilter = null;
                filter.receiverList.curBroadcast = null;
                if (filter.receiverList.app != null) {
                    filter.receiverList.app.curReceivers.remove(r);
                }
            }
        }
    }
       这里省去了大部分的代码,这些代码是用来检查广播发送者和广播接收者的权限的。 如果通过了权限的检查, 会调用注释 1 处的 performReceiveLocked 方法,代码如下所示:
 
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java

    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) { // ... 1
            if (app.thread != null) { // ... 2
                // If we have an app thread, do the call through that so it is
                // correctly ordered with other one-way calls.
                try {
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState); // ... 3
                // TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
                // DeadObjectException when the process isn't actually dead.
                //} catch (DeadObjectException ex) {
                // Failed to call into the process.  It's dying so just let it die and move on.
                //    throw ex;
                } catch (RemoteException ex) {
                    // Failed to call into the process. It's either dying or wedged. Kill it gently.
                    synchronized (mService) {
                        Slog.w(TAG, "Can't deliver broadcast to " + app.processName
                                + " (pid " + app.pid + "). Crashing it.");
                        app.scheduleCrash("can't deliver broadcast");
                    }
                    throw ex;
                }
            } else {
                // Application has died. Receiver doesn't exist.
                throw new RemoteException("app.thread must not be null");
            }
        } else {
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
        }
    }
       在注释1和 注释2 处的代 码表示如 果广播接 者所在的应用 程序进程存在并且正在运行, 则执 行注释3 处的代 码,表示用广播接收者所在的 应用程序进程来接收 广播,这里app . thr ead  指的是  Applic ationT hread ,下面 来查看 Applic ationThread的 scheduleRegisteredReceiver 方法, 代码如 下所示:
 
frameworks/base/core/java/android/app/ActivityThread.java
        public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
                int resultCode, String dataStr, Bundle extras, boolean ordered,
                boolean sticky, int sendingUser, int processState) throws RemoteException {
            updateProcessState(processState, false);
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
        }
       在 scheduleRegisteredReceiver 方法中 调用了 IlntentRecei ver 类型 的对象 receiver的performReceive方发,IIntentReceiver   在前面提到过,用于广播的跨进程 的通信,  它的 具体实 现为 LoadedApk.ReceiverDispatcher.lnnerReceiver ,代码如下所示:
 
frameworks/base/core/java/android/app/LoadedApk.java
 
    static final class ReceiverDispatcher {

        final static class InnerReceiver extends IIntentReceiver.Stub {
            final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
            final LoadedApk.ReceiverDispatcher mStrongRef;

            InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
                mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                mStrongRef = strong ? rd : null;
            }

            @Override
            public void performReceive(Intent intent, int resultCode, String data,
                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                final LoadedApk.ReceiverDispatcher rd;
                if (intent == null) {
                    Log.wtf(TAG, "Null intent received");
                    rd = null;
                } else {
                    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); // ... 1
                } 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 = ActivityManager.getService();
                    try {
                        if (extras != null) {
                            extras.setAllowFds(false);
                        }
                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
            }
            ...      
        }

    }
       IlntentReceiver  使用了 A IDL  来实 现进程间 通信。 lnnerReceiver 继承自 IlntentRe ceiver.Stub ,是 Binder 通信 的服 务器 端, IlntentReceiver 则是 Binder 通信的客 户端、 InnerReceiver 在 本地的代理,它的具 体的实 就是 InnerReceiver 。在Inner Receiver 的  performReceive 方法 的注释1 处调用了 Receiver Dispatcher 类型的 rd 对象的 performReceive 方法 ,代码如下所示:
 
frameworks/base/core/java/android/app/LoadedApk.java
 
        public void performReceive(Intent intent, int resultCode, String data,
                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
            final Args args = new Args(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser); // ... 1
            if (intent == null) {
                Log.wtf(TAG, "Null intent received");
            } else {
                if (ActivityThread.DEBUG_BROADCAST) {
                    int seq = intent.getIntExtra("seq", -1);
                    Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
                            + " seq=" + seq + " to " + mReceiver);
                }
            }
            if (intent == null || !mActivityThread.post(args.getRunnable())) { // ... 2
                if (mRegistered && ordered) {
                    IActivityManager mgr = ActivityManager.getService();
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing sync broadcast to " + mReceiver);
                    args.sendFinished(mgr);
                }
            }
        }
       在注释1 处将广播  intent 等信 息封装为  Args 对象,  在注释2 处调用 mActi vi tyThread 的  post 方法并 传入了  Args 对 象。这个 mActivityThread  是一个  Handler 对象,具体 指向的就是 H ,注释2处的代码就 是将 Args 对象的  getRunna ble 方法 通过 H  发送 到 线程 的消息列中, Args 的  getRunnable 方法 如下所示:
 
frameworks/base/core/java/android/app/LoadedApk.java

        final class Args extends BroadcastReceiver.PendingResult {
            ...
            public final Runnable getRunnable() {
                return () -> {
                    final BroadcastReceiver receiver = mReceiver;
                    ...
                    try {
                        ClassLoader cl = mReceiver.getClass().getClassLoader();
                        intent.setExtrasClassLoader(cl);
                        intent.prepareToEnterProcess();
                        setExtrasClassLoader(cl);
                        receiver.setPendingResult(this);
                        receiver.onReceive(mContext, intent); // ... 1
                    } 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 处执行了 B roadcas tReceiv er 类型的 receiver 对象的 onReceive 方法 ,这样 注册 的广播接收 者就 收到了广 播并得到了 intent。

猜你喜欢

转载自blog.csdn.net/lixiong0713/article/details/107222774