展开说说:Android之广播BroadcastReceiver源码浅析

上一篇《展开说说:Android之广播BroadcastReceiver生命周期》总结了广播的简单应用,本篇记录一下梳理广播从消息发送到被被接收的完整流程。

概述:

a、本篇以Activity发送无序广播为例,以下代码基于sdk版本android-30。

b、以下记录切换出当前类则序号的首位数字加1第二位归1,当前类内部方法跳转仅序号第二位加1。

c、本文插入的代码较多,如果不习惯在博客内部阅读可以只关注文字提到的关键方法和类自行查找代码阅读。

1、Activity中发送广播sendBroadcast(intent);

2、首先会调用ContextWrappersendBroadcast

@Override
public void sendBroadcast(Intent intent) {
    mBase.sendBroadcast(intent);
}

这个mBase就是Context,Context内部的sendBroadcast是个抽象方法,因此Context也是个抽象类。

3、Context的sendBroadcast

public abstract void sendBroadcast(@RequiresPermission Intent intent);

4、来到Context的子类实现类ComtextImpl

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

上面ActivityManager类的方法获取到IActivityManager:

   @UnsupportedAppUsage
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

他不是java类是个aidl文件,因此sendBroadcast方法的getService()是返回他的实例ActivityManagerServices。

4、ActivityManagerServices,下文简称AMS

4.1 broadcastIntentWithFeature方法实现

public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
            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);

            final ProcessRecord callerApp = getRecordForAppLocked(caller);
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();

            final long origId = Binder.clearCallingIdentity();
            try {
                return broadcastIntentLocked(callerApp,
                        callerApp != null ? callerApp.info.packageName : null, callingFeatureId,
                        intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                        requiredPermissions, appOp, bOptions, serialized, sticky,
                        callingPid, callingUid, callingUid, callingPid, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    }

4.2他的broadcastintentwithfeature方法调用了broadcastIntentLocked

方法,然后它继续调用另一个重载方法broadcastIntentLocked,然后根据intent-filter找到对应的满足接收要求的广播接收者将其添加到BroadcastQueue中。然后它将广播消息发送给符合条件的广播接收者,部分代码:

 if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            BroadcastQueue queue = broadcastQueueForIntent(intent);
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                    callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId,
                    allowBackgroundActivityStarts, timeoutExempt);

            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);

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

5、BroadcastQueue广播消息队列

5.1 broadcastIntentLocked中先发一个handler消息

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

5.2 接收handler消息BROADCAST_INTENT_MSG:

  @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BROADCAST_INTENT_MSG: {
                    if (DEBUG_BROADCAST) Slog.v(
                            TAG_BROADCAST, "Received BROADCAST_INTENT_MSG ["
                            + mQueueName + "]");
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }

5.3 processNextBroadcast方法内调用processNextBroadcastLocked加了Synchronization:

    final void processNextBroadcast(boolean fromMsg) {
        synchronized (mService) {
            processNextBroadcastLocked(fromMsg, false);
        }
    }

5.4遍历将final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();内的广播消息通过方法发送给所有广播接收者。

   while (mParallelBroadcasts.size() > 0) {
            r = mParallelBroadcasts.remove(0);
            r.dispatchTime = SystemClock.uptimeMillis();
            r.dispatchClockTime = System.currentTimeMillis();

            if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                    createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
                    System.identityHashCode(r));
                Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                    createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
                    System.identityHashCode(r));
            }

            final int N = r.receivers.size();
            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
                    + mQueueName + "] " + r);
            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);
            }
            addBroadcastToHistoryLocked(r);
            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
                    + mQueueName + "] " + r);
        }

5.5 上面方法可以看出是通过deliverToRegisteredReceiverLocked来发消息的,其内部又调用performReceiveLocked方法:

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.
                try {
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
                // 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");
            }

app.thread.scheduleRegisteredReceiver,实际app.thread就是ApplicationThread。

6、ApplicationThread是ActivityThread的子类,scheduleRegisteredReceiver实现:

        // This function exists to make sure all receiver dispatching is
        // correctly ordered, since these are one-way calls and the binder driver
        // applies transaction ordering per object for such calls.
        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);
        }

7、通过IIntentReceiver的performReceive方法:

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

IIntentReceiver的performReceive方法再调用外部类ReceiverDispatcher的performReceive方法:

 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);
            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())) {
                if (mRegistered && ordered) {
                    IActivityManager mgr = ActivityManager.getService();
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing sync broadcast to " + mReceiver);
                    args.sendFinished(mgr);
                }
            }
        }

创建一个args对象并通过ActivityThread的post执行args中的广播发送任务。args.getRunnabl方法:

public final Runnable getRunnable() {
                return () -> {
                    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 = ActivityManager.getService();
                    final Intent intent = mCurIntent;
                    if (intent == null) {
                        Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
                                + (mRunCalled ? ", run() has already been called" : ""));
                    }

                    mCurIntent = null;
                    mDispatched = true;
                    mRunCalled = true;
                    if (receiver == null || intent == 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);
                        intent.prepareToEnterProcess();
                        setExtrasClassLoader(cl);
                        receiver.setPendingResult(this);
                        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);
                };
            }

上面一大段核心代码就是 receiver.onReceive(mContext, intent);这个receiver就是注册广播时使用的BroadcastReceiver对象,此时符合条件的广播接收者onReceive生命周期会被调用,因此也就接收到了广播消息

8、总体来看大概可以分为两步,两者是异步的通过BroadcastQueue内的handler消息发送BROADCAST_INTENT_MSG消息连接,分别是广播的发送和处理过程

8.1 、sendBroadcast发出广播,IActivityManager把消息通过Binder机制发送给ActivityManagerService(简称AMS),AMS根据广播的intent-filter匹配相应的广播接收者,然后把这个广播放进消息队列BroadcastQueue

8.2、AMS在消息循环中处理广播,并通过Binder机制把这个广播分发给注册的广播接收分发器ReceiverDispatcher的内部类IIntentReceiverperformReceive方法,它借助ReceiverDispatcher的另一个内部类Args处理这个广播,最终将这个广播分发给当初注册的BroadcastReceiver实例的onReceive()方法进行处理。

相关推荐

  1. 展开说说:Android广播BroadcastReceiver浅析

    2023-12-18 06:02:04       38 阅读
  2. 展开说说:Android广播接收者

    2023-12-18 06:02:04       27 阅读
  3. Android BroadcastReceiver广播接收者实现网络连接通知

    2023-12-18 06:02:04       19 阅读
  4. Android:Intent&Activity,Service,BroadcastReceiver

    2023-12-18 06:02:04       25 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-18 06:02:04       14 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-18 06:02:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-18 06:02:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-18 06:02:04       18 阅读

热门阅读

  1. Android共享元素动画

    2023-12-18 06:02:04       35 阅读
  2. C++-LD_PRELOAD

    2023-12-18 06:02:04       29 阅读
  3. android 源码编译android 12

    2023-12-18 06:02:04       48 阅读
  4. Linux 系统开机启动流程

    2023-12-18 06:02:04       31 阅读
  5. 常用登录加密之Shiro与Spring Security的使用对比

    2023-12-18 06:02:04       28 阅读
  6. 大数据之旅-问题反思

    2023-12-18 06:02:04       44 阅读
  7. 复杂指针的声明

    2023-12-18 06:02:04       35 阅读
  8. 安装Docker

    2023-12-18 06:02:04       46 阅读