android framework开发之广播broadcast源码分析-千里马

93 篇文章 64 订阅
93 篇文章 71 订阅

hi,粉丝朋友大家好!
今天是2-8号,也是我春节第一天正式开工的日子,在这里首先祝大家新的一年技术进步,与千里马共同学习共同进步,共同升职加薪。今天要给大家分享的一个课题是大家都很熟悉的广播。
这里将要分为2个部分来对广播进行分析:
在这里插入图片描述
入门课,实战课,跨进程专题
ps需要学习深入framework课程和课程优惠
(可以加我qq:2102309716 优惠购买)
1、广播发送部分
一般我们正常使用发送广播都会有调用一个context的sendBroadcas,方法原型如下:

 public void sendBroadcast(Intent intent)

这里我们一般就是只想要传递一个intent参数既可以,这里调用context方法,其实和上一节讲解service一样,最后都会调用到ContextImpl方法中的sendBroadcast:

    @Override
    public void sendBroadcast(Intent intent) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        try {
            intent.prepareToLeaveProcess(this);//只是对intent进行一下预处理
            ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                    getUserId());//最后调用到了AMS里面的broadcastIntent
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

下面来看AMS的broadcastIntent方法,这里我们暂时只分析最常见的一类平行广播,不看有序部分,感兴趣可以自己分析:

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 realCallingUid,
            int realCallingPid, int userId, boolean allowBackgroundActivityStarts) {
     //省略部分
 // Figure out who all will receive this broadcast.
        List receivers = null;
        List<BroadcastFilter> registeredReceivers = null;//获取接受者的List
        // 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) {
        //具体根据intent进行filter获取接受者的List
            if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
                // Query one target user at a time, excluding shell-restricted users
                for (int i = 0; i < users.length; i++) {
                    if (mUserController.hasUserRestriction(
                            UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
                        continue;
                    }
                    List<BroadcastFilter> registeredReceiversForUser =
                            mReceiverResolver.queryIntent(intent,
                                    resolvedType, false /*defaultOnly*/, users[i]);
                    if (registeredReceivers == null) {
                        registeredReceivers = registeredReceiversForUser;
                    } else if (registeredReceiversForUser != null) {
                        registeredReceivers.addAll(registeredReceiversForUser);
                    }
                }
            } else {
                registeredReceivers = mReceiverResolver.queryIntent(intent,
                        resolvedType, false /*defaultOnly*/, userId);
            }
        }
        
               if (!ordered && NR > 0) {
          
            final BroadcastQueue queue = broadcastQueueForIntent(intent);
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                    resultCode, resultData, resultExtras, ordered, sticky, false, userId,
                    allowBackgroundActivityStarts, timeoutExempt);//构造出一个BroadcastRecord
            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
            final boolean replaced = replacePending
                    && (queue.replaceParallelBroadcastLocked(r) != null);
            // Note: We assume resultTo is null for non-ordered broadcasts.
            if (!replaced) {
                queue.enqueueParallelBroadcastLocked(r);//插入平行广播队列
                queue.scheduleBroadcastsLocked();
            }
            registeredReceivers = null;
            NR = 0;
        }
//省略部分
        return ActivityManager.BROADCAST_SUCCESS;
    }

接下来看看最重要的enqueueParallelBroadcastLocked和scheduleBroadcastsLocked部分:

     public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
        mParallelBroadcasts.add(r);//这里动作很简单就是把BroadcastRecord插入到mParallelBroadcasts这个list
        enqueueBroadcastHelper(r);
    }

接下来看scheduleBroadcastsLocked:

    public void scheduleBroadcastsLocked() {
        //省略部分
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

这里其实就只是发送了一个BROADCAST_INTENT_MSG消息:
来看看对这个消息的处理

    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 ["
                            + mQueueName + "]");
                    processNextBroadcast(true);//调用了processNextBroadcast方法
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
    }

这里我们来看processNextBroadcast:

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


重点看看processNextBroadcastLocked:

   final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
        BroadcastRecord r;
        while (mParallelBroadcasts.size() > 0) {
            r = mParallelBroadcasts.remove(0);//获取平行广播的BroadcastRecord对象

            final int N = r.receivers.size();
            for (int i=0; i<N; i++) {
                Object target = r.receivers.get(i);
                deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);//这里是核心调用了deliverToRegisteredReceiverLocked方法
            }
            addBroadcastToHistoryLocked(r);
            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
                    + mQueueName + "] " + r);
        }
//省略部分
}

下面来看deliverToRegisteredReceiverLocked方法:

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
       //省略部分
        try {
            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                //省略部分
            } else {
                r.receiverTime = SystemClock.uptimeMillis();
                maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
                        //最重要调用了performReceiveLocked
                //省略部分
            }
           //省略部分
        } catch (RemoteException e) {
            //省略部分
        }
    }


接下来重点看performReceiveLocked:

 void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
            Intent intent, int resultCode, String data, Bundle extras,
            boolean ordered, boolean sticky, int sendingUser)
            throws RemoteException {
        //省略
        if (app != null) {
            if (app.thread != null) {
                
                try {
                //调用到了具体应用进程的scheduleRegisteredReceiver方法
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
             
                } catch (RemoteException ex) {
                   //省略
                }
            } else {
                throw new RemoteException("app.thread must not be null");
            }
        } else {
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
        }
    }

这里的scheduleRegisteredReceiver方法是在应用进程的ActivityThread类中实现的:

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

这里会调用到receiver的performReceive方法,其中IIntentReceiver实际实在LoadedApk.java中:

 final static class InnerReceiver extends IIntentReceiver.Stub {
            //省略

            @Override
            public void performReceive(Intent intent, int resultCode, String data,
                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                final LoadedApk.ReceiverDispatcher rd;
               //省略
                if (rd != null) {
                    rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
                } else {
                 //省略
                }
            }
        }

这里就调用了 LoadedApk.ReceiverDispatcher的performReceive方法,其中ReceiverDispatcher也在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);
           //省略
            if (intent == null || !mActivityThread.post(args.getRunnable())) { 
            //这句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);
                }
            }
        }

这里mActivityThread.post(args.getRunnable())是核心,就是往主线程post了一个runnable,我们来看getRunnable这个方法:

public final Runnable getRunnable() {
                return () -> {
                    //省略部分
                    try {
                        ClassLoader cl = mReceiver.getClass().getClassLoader();
                        intent.setExtrasClassLoader(cl);
                        intent.prepareToEnterProcess();
                        setExtrasClassLoader(cl);
                        receiver.setPendingResult(this);
                        receiver.onReceive(mContext, intent);//调用到具体应用广播接收器的onReceive
                    } catch (Exception e) {
                     //省略部分
                };
            }
        }

主要就 receiver.onReceive(mContext, intent)这里就调用到具体应用广播接收器的onReceive,也就是我们经常onReceive写处理业务地方
总结图如下:
在这里插入图片描述

在这里插入图片描述

2、广播注册接受部分
下一节讲解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值