FrameWork源码解析(5)-广播处理过程源码解析

主目录见:Android高级进阶知识(这是总目录索引)

这篇文章主要是接着上面两篇文章的:
1.注册广播接收者的源码分析
2.广播发送过程源码解析
到这里这篇,广播也就完成了,下一篇我们会来说说ContentProvider的相关源码,然后四大组件的源码分析也就完成了,接着我们会来分析资源的加载,类的加载过程等,这些插件化必需的知识,最后我们会来剖析一个插件化的框架,大家敬请期待哈。

一.源码解析

紧接着上一篇讲到BroadcastQueue#processNextBroadcast()方法,我们就从这里开始出发。这个方法很长,我们一步一步来看。

1.处理并行广播

            // First, deliver any non-serialized broadcasts right away.
           //马上处理掉所有的并行广播
            while (mParallelBroadcasts.size() > 0) {
                r = mParallelBroadcasts.remove(0);
                r.dispatchTime = SystemClock.uptimeMillis();
                r.dispatchClockTime = System.currentTimeMillis();
                //并行广播的receivers中是BroadcastFilter类型对象
                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);
                    //这是发送广播,这里的target是BroadcastFilter类型
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
                }
                addBroadcastToHistoryLocked(r);
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
                        + mQueueName + "] " + r);
            }

之前的文章我们知道,我们的动态注册的广播都是放在并行队列里面,所以程序这里会取出所有的并行队列中的BrocastRecord类型对象,然后取出对象里面的receivers,这里是一个BroadcastFilter集合对象。然后一一发送。这里我们具体来看下deliverToRegisteredReceiverLocked()方法的具体处理流程。

2.动态注册广播发送

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
        boolean skip = false;
      //这里省略了权限检查代码。如果设置了权限的话,这里就会检查发送者是否有权限,有的话,就会判断接收者是否有发送者的权限,
      //没有的话就会skip设置为true,如果有的话会调用noteOperation判断是否权限被禁止了
     .........
        
        //有序广播处理逻辑,因为我们这里是无序广播,所以不会进入这个操作
        if (ordered) {
            //这里的filter.receiverList.receiver.asBinder()得到的就是客户端ReceiverDispatcher中的InnerReceiver这个Binder实体
            r.receiver = filter.receiverList.receiver.asBinder();
            r.curFilter = filter;
            filter.receiverList.curBroadcast = r;
            r.state = BroadcastRecord.CALL_IN_RECEIVE;
            if (filter.receiverList.app != null) {
                 r.curApp = filter.receiverList.app;
                filter.receiverList.app.curReceiver = r;
                mService.updateOomAdjLocked(r.curApp);
            }
        }
        try {
            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
           ......
            } else {
               //我们程序会走到这里,这里就是处理广播的地方
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
            }
            if (ordered) {
                r.state = BroadcastRecord.CALL_DONE_RECEIVE;
            }
        } catch (RemoteException e) {
        .......      
        }
    }

如果对上面的权限判断不是很了解,这里推荐一篇Android权限管理原理,这篇文章还是非常不错的,讲的很清楚。我们看到我们无序广播处理的地方是performReceiveLocked()方法,里面filter.receiverList.receiver就是对应的客户端ReceiverDispatcher中的InnerReceiver这个Binder实体。

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) {//判断app.thread(这里是ActivityThread的ApplicationThreadProxy)是否不为空
                try {
                  //实际就是调用ActivityThread的方法
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);
                } catch (RemoteException 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);
        }
    }

我们看到这个方法会调用到ActivityThread中间的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);
        }

这里的receiver我们在注册广播接收者的源码分析这篇文章中可以知道,receiver是LoadedApk#ReceiverDispatcher#InnerReceiver对象。所以这里会调用到InnerReceiverperformReceive()方法:

            @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);
                 }
                if (rd != null) {
                    rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
                } else {
                    IActivityManager mgr = ActivityManagerNative.getDefault();
                    try {
                        if (extras != null) {
                            extras.setAllowFds(false);
                        }
                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
            }

这里看到我们这个方法内部会调用ReceiverDispatcherperformReceive()方法,所以我们继续往下跟:

        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);
                }
            }
            //这里处理消息的方式是通过Handler.post函数进行的,post函数的参数是Runnable类型的,这个消息最终会调用这个这个参数的run成员函数来处理
            if (intent == null || !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);
                }
            }
        }

我们看到这个方法里面会调用mActivityThread即一个Handler的post方法,post方法里面的参数是一个Runnable对象,所以我们知道会调用这个Runnable对象的run方法:

   public void run() {
                final BroadcastReceiver receiver = mReceiver;
                final boolean ordered = mOrdered;
               .....
                final IActivityManager mgr = ActivityManagerNative.getDefault();
                final Intent intent = mCurIntent;
                if (intent == null) {
                    Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
                }

                mCurIntent = null;
                mDispatched = 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 (receiver.getPendingResult() != null) {
                    finish();
                }
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }

这里的mReceiver就是ReceiverDispatcher对象的成员变量,它是一个BroadcastReceiver类型,这里它就是Activity注册广播接收器时创建的BroadcastReceiver实例了。有了ReceiverDispatcher就可以回调他的onReceive方法了。这样的话,到这里动态注册广播的处理也就完成了。这样的话我们继续来看processNextBroadcast()方法。

3.处理pending广播

            //目标进程如果不存在,那么会启动进程,因为启动进程是耗时的工作,则会先把广播放在mPendingBroadcast中
            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 {
                    mPendingBroadcast.state = BroadcastRecord.IDLE;
                    mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
                    mPendingBroadcast = null;
                }
            }

            boolean looped = false;

目标进程如果不存在,那么会启动进程,因为启动进程是耗时的工作,则会先把广播放在mPendingBroadcast中。

4.有序广播处理

          do {
                //是否存在有序广播
                if (mOrderedBroadcasts.size() == 0) {
                    // No more broadcasts pending, so all done!
                    mService.scheduleAppGcsLocked();
                    if (looped) {
                        //这是AMS的内存回收方法
                        mService.updateOomAdjLocked();
                    }
                    return;
                }

                //这里是获取一个有序广播,在循环的最后会remove,也就是说这里是从mOrderedBroadcasts
                //中循环取出有序广播
                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();
                    //dispatchTime为广播发送的起始时间+mTimeoutPeriod这是由BroadcastQueue
                    //类型决定的,为10秒和60秒*2*有序广播数量(也就是说只要整体的广播发送事件不超过这个事件
                    //就不会报ANR)
                    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(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 {
                           ////处理广播消息消息,调用到onReceive()
                            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) {
                        .......  
                        }
                    }

                    if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");
                    //如果前面发送的广播已经完成了,那么需要remove掉前面发送的超时消息
                    cancelBroadcastTimeoutLocked();

                    if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                            "Finished with ordered broadcast " + r);

                    // ... and on to the next...
                    addBroadcastToHistoryLocked(r);
                    if (r.intent.getComponent() == null && r.intent.getPackage() == null
                            && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                        // This was an implicit broadcast... let's record it for posterity.
                        mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
                                r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
                    }
                    mOrderedBroadcasts.remove(0);
                    r = null;
                    looped = true;
                    //进入下一次循环
                    continue;
                }
            } while (r == null);

我们看到这个方法主要是判断是否超时了,如果这些条件都没有的话,就会返回r取到队列中的一个有序广播,然后就会进入处理程序内容。

5.动态广播处理

      // Get the next receiver...
          //获取下一个广播
            int recIdx = r.nextReceiver++;

            // Keep track of when this receiver started, and make sure there
            // is a timeout message pending to kill it if need be.
            r.receiverTime = SystemClock.uptimeMillis();
            if (recIdx == 0) {//没有下一个广播则设置开始时间
                r.dispatchTime = r.receiverTime;
                r.dispatchClockTime = System.currentTimeMillis();
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
                        + mQueueName + "] " + r);
            }
            if (! mPendingBroadcastTimeoutMessage) {//如果已经超时则关闭广播
                long timeoutTime = r.receiverTime + mTimeoutPeriod;
                if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
                        "Submitting BROADCAST_TIMEOUT_MSG ["
                        + mQueueName + "] for " + r + " at " + timeoutTime);
                setBroadcastTimeoutLocked(timeoutTime);
            }

            final BroadcastOptions brOptions = r.options;
            final Object nextReceiver = r.receivers.get(recIdx);

            if (nextReceiver instanceof BroadcastFilter) {//判断是动态注册还是静态注册广播
                // Simple case: this is a registered receiver who gets
                // a direct call.
                BroadcastFilter filter = (BroadcastFilter)nextReceiver;
                if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                        "Delivering ordered ["
                        + mQueueName + "] to registered "
                        + filter + ": " + r);
                //如果是动态注册广播则调用deliverToRegisteredReceiverLocked发送
                deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
                if (r.receiver == null || !r.ordered) {//如果是无序广播
                    // The receiver has already finished, so schedule to
                    // process the next one.
                    if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Quick finishing ["
                            + mQueueName + "]: ordered="
                            + r.ordered + " receiver=" + r.receiver);
                    r.state = BroadcastRecord.IDLE;
                  //则直接执行下一个广播,不需要等待前一个广播完成
                    scheduleBroadcastsLocked();
                } else {
                    if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
                        scheduleTempWhitelistLocked(filter.owningUid,
                                brOptions.getTemporaryAppWhitelistDuration(), r);
                    }
                }
                return;
            }

我们看到这个方法里面会取出下一个广播,然后判断是不是动态注册广播,如果是的话就会直接调用deliverToRegisteredReceiverLocked方法发送,这个方法前面2.动态注册广播发送已经讲过了。

6.静态广播处理

      //因为前面的动态广播处理都完成了,剩下的就是静态广播了
      ResolveInfo info =
                (ResolveInfo)nextReceiver;
            ComponentName component = new ComponentName(
                    info.activityInfo.applicationInfo.packageName,
                    info.activityInfo.name);

            boolean skip = false;
            //省略了很多skip标志位重设的判断
           .......
            String targetProcess = info.activityInfo.processName;
            ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
                    info.activityInfo.applicationInfo.uid, false);
            .......
            if (skip) {
                if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                        "Skipping delivery of ordered [" + mQueueName + "] "
                        + r + " for whatever reason");
                r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
                r.receiver = null;
                r.curFilter = null;
                //如果要跳过的话那么就直接执行下一个广播
                r.state = BroadcastRecord.IDLE;
                scheduleBroadcastsLocked();
                return;
            }
            ......
            // Is this receiver's application already running?
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(info.activityInfo.packageName,
                            info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
                    //如果接收者的应用存在且在运行的话那么就调用这个方法处理这个静态广播
                    processCurBroadcastLocked(r, app);
                    return;
                } catch (RemoteException e) {
               ......  
                } catch (RuntimeException e) {
               ......
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }

            // Not running -- get it started, to be executed when the app comes up.
            //接收者进程没有启动那么就启动进程,当然之后进程启动完毕还是会调用processCurBroadcastLocked来启动
            if ((r.curApp=mService.startProcessLocked(targetProcess,
                    info.activityInfo.applicationInfo, true,
                    r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
                    "broadcast", r.curComponent,
                    (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                            == null) {
                logBroadcastReceiverDiscardLocked(r);
                finishReceiverLocked(r, r.resultCode, r.resultData,
                        r.resultExtras, r.resultAbort, false);
                //执行下一个广播
                scheduleBroadcastsLocked();
                r.state = BroadcastRecord.IDLE;
                return;
            }

            mPendingBroadcast = r;
            mPendingBroadcastRecvIndex = recIdx;
        }

我们看到静态广播处理会调用processCurBroadcastLocked()方法进行发送,所以我们来看看这个方法。

8.静态广播发送

  private final void processCurBroadcastLocked(BroadcastRecord r,
            ProcessRecord app) throws RemoteException {
        .....
        r.receiver = app.thread.asBinder();
        r.curApp = app;
        app.curReceiver = r;
        //更新进程状态为PROCESS_STATE_RECEIVER
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
        //AMS更新内存
        mService.updateLruProcessLocked(app, false, null);
        //该方法的作用是告诉OOMKiller指定进程的优先级,值越小越重要,该函数的返回值是boolean类型,
        //如果底层linux包含OOMKiller则返回true,否则返回false
        //也就是提升优先级
        mService.updateOomAdjLocked();

        // Tell the application to launch this receiver.
        r.intent.setComponent(r.curComponent);

        boolean started = false;
        try {
            mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
                                      PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
          //这里同上面的2.动态广播发送有点类似
            app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
                    mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
                    r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
                    app.repProcState);
              started = true;
        } finally {
            if (!started) {
                r.receiver = null;
                r.curApp = null;
                app.curReceiver = null;
            }
        }
    }

这里我们看到最终静态广播发送也会发送到ActivityThreadscheduleReceiver()方法中,具体流程与动态注册广播类似,这里就不赘述了。到这里动态广播与静态广播发送处理都完成了。

总结:广播的发送和处理还是比较繁琐的,里面的一些东西也有我理解比较浅显的,希望大家体谅,如果大家有更好的理解可以教教我,希望大家共同进步哈。

    原文作者:ZJ_Rocky
    原文地址: https://www.jianshu.com/p/d6577f80cfe6
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞