BroadcastReceiver的工作过程

来源:互联网 发布:视频剪辑配音软件 编辑:程序博客网 时间:2024/05/22 03:41

BroadcastReceiver的工作过程

本篇博客不介绍BroadcastReceiver的具体使用,只对广播的注册过程和发送接收过程进行源码分析。
介绍一下几个重要的概念:
1.Context:http://blog.csdn.net/qinjuning/article/details/7310620
2.ActivityThread、ApplicationThread:http://blog.csdn.net/myarrow/article/details/14223493

广播的注册过程

广播分为静态注册和动态注册,其中静态注册的广播在应用安装时由系统自动完成注册,是由PMS来完成整个注册过程的,其他三大组件都是在应用安装时由PMS解析并注册的。这里只分析广播的动态注册。
这里写图片描述
动态注册的过程从ContextWrapper的registerReceiver()方法开始。

    @Override    public Intent registerReceiver(        BroadcastReceiver receiver, IntentFilter filter) {        return mBase.registerReceiver(receiver, filter);    }

mBase就是ContextImpl。

    @Override    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,            String broadcastPermission, Handler scheduler) {        return registerReceiverInternal(receiver, getUserId(),                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) {            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 {            return ActivityManagerNative.getDefault().registerReceiver(                    mMainThread.getApplicationThread(), mBasePackageName,                    rd, filter, broadcastPermission, userId);        } catch (RemoteException e) {            return null;        }    }

分析:系统首先从mPackageInfo获取IItentReceiver(Binder接口,具体实现是LoadedApk.RecevierDispatcher.InnerRecevier)对象,然后再采用跨进程的方式向AMS发送广播注册的请求。RecevierDispatcher内部保存了BroadcastRecevier和InnerRecevier,这样当接收广播时,RecevierDispatcher可以方便的调用BroadcastRecevier的onReceive方法,和Service的实现原理类似。
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) {                map = mReceivers.get(context);                if (map != null) {                    rd = map.get(r);                }            }            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 {                rd.validate(context, handler);            }            rd.mForgotten = false;            return rd.getIIntentReceiver();        }    }

显然,getReceiverDispatcher方法重新创建了一个ReceiverDispatcher对象并将其保存的InnerReceiver对象作为返回值返回,其中InnerReceiver对象和BroadcastReceiver都是在ReceiverDispatcher的构造方法中被保存下来。
由于注册广播的真正实现过程在AMS中,看一下源码。
AMS#registerReceiver

    public Intent registerReceiver(IApplicationThread caller, String callerPackage,            IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {        ...........                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);             ........    }

上面截取了部分关键代码分析:把远程的InnerReceiver对象以及IntentFilter对象储存起来。这样整个广播的注册过程就完成了。

广播的发送和接受过程

当通过send方法来发送广播时,AMS会查找出匹配的广播接受者并将广播的发送给它们处理。
这里写图片描述
先从发送分析。ContextWrapper的sendBroadcast方法把事情交给ContextImpl去处理。

@Override    public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {        warnIfCallingFromSystemProcess();        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());        String[] receiverPermissions = receiverPermission == null ? null                : new String[] {receiverPermission};        try {            intent.prepareToLeaveProcess();            ActivityManagerNative.getDefault().broadcastIntent(                    mMainThread.getApplicationThread(), intent, resolvedType, null,                    Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false,                    getUserId());        } catch (RemoteException e) {            throw new RuntimeException("Failure from system", e);        }    }

它直接向AMS发起了一个异步请求用于发送广播。
AMS#broadcastIntent

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

broadcastIntent调用了broadcastIntentLocked方法,在broadcastIntentLocked的内部根据intent-filter查找出匹配的广播接受者并经过一系列的条件过滤,最终将满足条件的广播接受者添加到BroadcastQueue中,接着BroadcastQueue就会将广播发送给相应的广播接受者。源码如下

        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;

BroadcastQueue中广播的发送过程的实现:
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;    }

并没有立即发送广播而是发送了BROADCAST_INTENT_MSG消息,BroadcastQueue收到消息后调用processNextBroadcast方法。
对普通广播的处理如下:

// First, deliver any non-serialized broadcasts right away.            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; 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);                }                addBroadcastToHistoryLocked(r);                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["                        + mQueueName + "] " + r);            }

无序广播存储在mParallelBroadcasts中,系统遍历mParallelBroadcasts并将其中的广播通过deliverToRegisteredReceiverLocked发送接受者。
deliverToRegisteredReceiverLocked方法负责将一个广播发送给一个特定的接受者,它内部调用了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.performReceive(intent, resultCode, data, extras, ordered,                    sticky, sendingUser);        }    }

ApplicationThread#scheduleRegisteredReceiver

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

InnerRecevier的performReceive方法会调用LoadedApk.ReceiverDispatcher的performRecieve方法。
LoadedApk.ReceiverDispatcher#performRecieve

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

创建一个Args对象并通过mActivityThread的post方法来执行Args中的逻辑,而Args实现了Runnable接口。mActivityThread就是ActivityThread的Handler H。

final BroadcastReceiver receiver = mReceiver;receiver.setPendingResult(this);receiver.onReceive(mContext, intent);

这时BroadcastReceiver的onReceive方法被执行了,也就是说应用已经接收到广播了,同时onReceive方法是在广播接收者的主线程中被调用的。

0 0
原创粉丝点击