【Broadcast】sendBroadcast流程(二)

上节:sendBroadcat流程(一)中分析了AMS.broadcastIntentLocked中的处理。

接下来分析广播的派发过程,即分析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;
}
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: {
                processNextBroadcast(true);
            } break;
            case BROADCAST_TIMEOUT_MSG: {
                synchronized (mService) {
                    broadcastTimeoutLocked(true);
                }
           } break;
        }
    }
}

接下来看processNextBroadcast函数

第一阶段,处理非串行广播:

final void processNextBroadcast(boolean fromMsg) {
     synchronized(mService) {
         BroadcastRecord r;
         mService.updateCpuStats();
         if (fromMsg) {
            mBroadcastsScheduled = false;
         }
         
         // 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();
            for (int i=0; i<N; i++) {
                 Object target = r.receivers.get(i);
                 【1.1】
                 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
            }
            addBroadcastToHistoryLocked(r);
        }

【1.1】deliverToRegisteredReceiverLocked

private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
                         BroadcastFilter filter, booleanordered) {
   booleanskip = false;
   //检查发送进程是否有filter要求的权限
   if(filter.requiredPermission != null) {
       intperm = checkComponentPermission(filter.requiredPermission,
                   r.callingPid, r.callingUid, -1, true);
       if(perm != PackageManager.PERMISSION_GRANTED) skip = true;
  }
   //检查接收者是否有发送者要求的权限
   if(r.requiredPermission != null) {
       intperm = checkComponentPermission(r.requiredPermission,
               filter.receiverList.pid, filter.receiverList.uid, -1, true);
       if(perm != PackageManager.PERMISSION_GRANTED) skip = true;
    }
 
   if(!skip) {
     if(ordered) {
     ......//设置一些状态,成员变量等信息,不涉及广播发送
      }
     try {
         //发送广播
        performReceiveLocked(filter.receiverList.app,   
              filter.receiverList.receiver,new Intent(r.intent), r.resultCode,
              r.resultData, r.resultExtras, r.ordered, r.initialSticky);
 
         if(ordered) r.state = BroadcastRecord.CALL_DONE_RECEIVE;
       }......
     }
   }
 }

再看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) {
            //如果app及app.thread不为null,则调度scheduleRegisteredReceiver
            // If we have an app thread, do the call through that so it is
            // correctly ordered with other one-way calls.
            try {
                //scheduleRegisteredReceiver仅针对动态receiver
                app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                        data, extras, ordered, sticky, sendingUser, app.repProcState);
				// 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 {
       //否则调用IIntentReceiver的performReceive函数
        receiver.performReceive(intent, resultCode, data, extras, ordered,
                sticky, sendingUser);
    }
}

对于动态receiver而言,大部分情况下会执行if分支,所以应用进程ApplicationThread的scheduleRegisteredReceiver函数将被调用。

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

此处的reciever是registerReceiver时传入的,实际类型是LoadedApk.ReceiverDispatcher.InnerReceiver,来看它的performReceive函数:

@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 {
        // 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.

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

又调用了LoadedApk.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 {
        //log 信息
    }
    //mActivityThread是一个Handler,SDK中的两个同名registerReceiver,
    //没有传递Handler,则使用主线程的Handler
    if (intent == null || !mActivityThread.post(args.getRunnable())) {
        if (mRegistered && ordered) {
            IActivityManager mgr = ActivityManager.getService();
            args.sendFinished(mgr);
        }
    }
}

scheduleRegisteredReceiver最终向主线程的Handler投递了一个Runnable对象,该Runnable中会在主线程中运行:

public final Runnable getRunnable() {
    return () -> {
        final BroadcastReceiver receiver = mReceiver;
        final boolean ordered = mOrdered;

        final IActivityManager mgr = ActivityManager.getService();
        final Intent intent = mCurIntent;
        if (intent == null) {
            Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
                                    + ": run() previously called at "
                                    + Log.getStackTraceString(mPreviousRunStacktrace));
        }

        mCurIntent = null;
        mDispatched = true;
        mPreviousRunStacktrace = new Throwable("Previous stacktrace");
        if (receiver == null || intent == null || mForgotten) {
            if (mRegistered && ordered) {
                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函数
             receiver.onReceive(mContext, intent);
        } catch (Exception e) {
             if (mRegistered && ordered) {
                 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) {
            //调用BroadcastReceiver的finish完成工作,通知AMS
            finish();
        }
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    };
}
/**
* Finish the broadcast.  The current result will be sent and the
* next broadcast will proceed.
*/
public final void finish() {
    if (mType == TYPE_COMPONENT) {
        final IActivityManager mgr = ActivityManager.getService();
        if (QueuedWork.hasPendingWork()) {
            // If this is a broadcast component, we need to make sure any
            // queued work is complete before telling AM we are done, so
            // we don't have our process killed before that.  We now know
            // there is pending work; put another piece of work at the end
            // of the list to finish the broadcast, so we don't block this
            // thread (which may be the main thread) to have it finished.
            //
            // Note that we don't need to use QueuedWork.addFinisher() with the
            // runnable, since we know the AM is waiting for us until the
            // executor gets to it.
            QueuedWork.queue(new Runnable() {
                @Override public void run() {
                    sendFinished(mgr);
                }
            }, false);
        } else {
            sendFinished(mgr);
        }
    } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
        final IActivityManager mgr = ActivityManager.getService();
        sendFinished(mgr);
    }
}
/** @hide */
public void sendFinished(IActivityManager am) {
    synchronized (this) {
        if (mFinished) {
            throw new IllegalStateException("Broadcast already finished");
        }
        mFinished = true;

        try {
            if (mResultExtras != null) {
                mResultExtras.setAllowFds(false);
            }
            if (mOrderedHint) {
                am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
                mAbortBroadcast, mFlags);
            } else {
                // This broadcast was sent to a component; it is not ordered,
                // but we still need to tell the activity manager we are done.
                am.finishReceiver(mToken, 0, null, null, false, mFlags);
            }
        } catch (RemoteException ex) {
        }
    }
}

会调用到ActivityManagerService的finishReceiver函数:

public void finishReceiver(IBinder who, int resultCode, String resultData,
                    Bundle resultExtras, boolean resultAbort, int flags) {

    // Refuse possible leaked file descriptors
    if (resultExtras != null && resultExtras.hasFileDescriptors()) {
        throw new IllegalArgumentException("File descriptors passed in Bundle");
     }

    final long origId = Binder.clearCallingIdentity();
    try {
        boolean doNext = false;
        BroadcastRecord r;

        synchronized(this) {
            BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                                                ? mFgBroadcastQueue : mBgBroadcastQueue;
            r = queue.getMatchingOrderedReceiver(who);
            if (r != null) {
                //判断是否需要继续调度后续的广播发送
                doNext = r.queue.finishReceiverLocked(r, resultCode,
                                    resultData, resultExtras, resultAbort, true);
            }
        }

        if (doNext) {
            r.queue.processNextBroadcast(false);
        }
         trimApplications();
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
}

processNextBroadcast第二阶段,处理串行广播:

final void processNextBroadcast(boolean fromMsg) {
     synchronized(mService) {
         BroadcastRecord r;
        ...//第一阶段处理串行广播
    
        //第二阶段
        // Now take care of the next serialized one...
        // If we are waiting for a process to come up to handle the next
        // broadcast, then do nothing at this point.  Just in case, we
        // check that the process we're waiting for still exists.
        /*
        接下来处理mOrderedBroadcasts中的成员,如果接收者所在的进程还未启动,则需等待。
        mPendingBrodcast用于标识因为应用进程还未启动而处于等待状态的BrodcastRecord。
         */
        if (mPendingBroadcast != null) {
            boolean isDead;
            synchronized (mService.mPidsSelfLocked) {
                ProcessRecord proc =         
                           mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
                isDead = proc == null || proc.crashing;
            }
            /*重要说明
             判断要等待的进程是否为dead进程,如果没有dead进程,则继续等待。仔细思考,此处直接
             返回会有什么问题。
             问题不小!假设有两个ordered广播A和B,有两个接收者,AR和BR,并且BR所
             在进程已经启动并完成初始化Android运行环境。如果processNextBroadcast先处理A,
             再处理B,那么此处B的处理将因为mPendingBroadcast不为空而被延后。虽然B和A
             之间没有任何关系(例如完全是两个不同的广播消息),
             但是事实上,大多数开发人员理解的order是针对单个广播的,例如A有5个接收者,那么对这
             5个接收者的广播的处理是串行的。通过此处的代码发现,系统竟然串行处理A和B广播,即
             B广播要待到A的5个接收者都处理完了才能处理。
           */
            if (!isDead) {
                // It's still alive, so keep waiting
                return;
            } else {
                mPendingBroadcast.state = BroadcastRecord.IDLE;
                mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
                mPendingBroadcast = null;
            }
        }

        boolean looped = false;
    
        do {
            //mOrderedBroadcasts处理完毕
            if (mOrderedBroadcasts.size() == 0) {
                // No more broadcasts pending, so all done!
                mService.scheduleAppGcsLocked();
                if (looped) {
                    // If we had finished the last ordered broadcast, then
                    // make sure all processes have correct oom and sched
                    // adjustments.
                    mService.updateOomAdjLocked();
                 }
                return;
            }
            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();
                ///如果总耗时超过2倍的接收者个数*每个接收者最长处理时间(10秒),则
                 //强制结束这条广播的处理
                if ((numReceivers > 0) &&
                            (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
                     broadcastTimeoutLocked(false); // forcibly finish this broadcast
                     forceReceive = true;
                     r.state = BroadcastRecord.IDLE;
                }
            }
            if (r.state != BroadcastRecord.IDLE) {
                return;
            }
            //如果下面这个if条件满足,则表示该条广播要么已经全部被处理,要么被中途取消
            if (r.receivers == null || r.nextReceiver >= numReceivers
                    || r.resultAbort || forceReceive) { //没有接收此广播的receiver了
                 if (r.resultTo != null) {
                    try {
                        //将该广播的处理结果传给设置了resultTo的接收者
                         performReceiveLocked(r.callerApp, r.resultTo,
                                new Intent(r.intent), r.resutCode,
                                r.resultData, r.resultExtras, false, false, r.userId);
                    catch (RemoteException e) {
                        r.resultTo = null;
                    }
            }
            cancelBroadcastTimeoutLocked();
            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);

        ....
    } //end of synchronized(mService)
}       

第二阶段的工作总结:

  1. 首先根据是否处于pending状态进行相关操作
  2. 处理超时的广播记录。超时时间是2*BROADCAST_TIMEOUT*numReceivers,BROADCAST_TIMEOUT默认为10秒。由于涉及到创建进程,初始化Android运行环境等操作,所以此处的超时时间还乘以一个固定倍数2。

第三阶段

        // 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();
        }
        //设置广播处理超时时间,BROADCAST_TIMEOUT为10秒
        if (!mPendingBroadcastTimeoutMessage) {
            long timeoutTime = r.receiverTime + mTimeoutPeriod;
            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.
            //如果是动态接收者,则直接调用deliverToRegisteredReceiverLocked处理
            BroadcastFilter filter = (BroadcastFilter)nextReceiver;
            deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
            if (r.receiver == null || !r.ordered) {
                // The receiver has already finished, so schedule to
                // process the next one.
                r.state = BroadcastRecord.IDLE;
                scheduleBroadcastsLocked();
            } else {
               if (brOptions!=null&&brOptions.getTemporaryAppWhitelistDuration()> 0) {
                 scheduleTempWhitelistLocked(filter.owningUid,
                 brOptions.getTemporaryAppWhitelistDuration(), r);
               }
            }
            return;//已经通知一个接收者去处理该广播,需要等它的处理结果,所以此处直接返回
        }
        
        // Hard case: need to instantiate the receiver, possibly
        // starting its application process to host it.
         ResolveInfo info =(ResolveInfo)nextReceiver;
         ComponentName component = new ComponentName(
                            info.activityInfo.applicationInfo.packageName,
                            info.activityInfo.name);
        ......//检测是否为skip的package
        String targetProcess = info.activityInfo.processName;
        ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
                            info.activityInfo.applicationInfo.uid, false);
        .....
        r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
        r.state = BroadcastRecord.APP_RECEIVE;
        r.curComponent = component;
        r.curReceiver = info.activityInfo;
        .....//正在处理广播,package不能被stop
        
        // Is this receiver's application already running?
        //如果接收者所在的进程已经启动
         if (app != null && app.thread != null && !app.killed) {
            try {
                app.addPackage(info.activityInfo.packageName,                                 
                               info.activityInfo.applicationInfo.versionCode, 
                               mService.mProcessStats);
                processCurBroadcastLocked(r, app);
                return;//已经触发接收者处理本广播,需要等待处理结果
            } catch (RemoteException e) {

            } catch (RuntimeException e) {                    
                Slog.wtf(TAG, "Failed sending broadcast to "
                            + r.curComponent + " with " + r.intent, e);
                // If some unexpected exception happened, just skip
                // this broadcast.  At this point we are not in the call
                // from a client, so throwing an exception out from here
                // will crash the entire system instead of just whoever
                // sent the broadcast.
                logBroadcastReceiverDiscardLocked(r);
                finishReceiverLocked(r, r.resultCode, r.resultData,
                                     r.resultExtras, r.resultAbort, false);
                scheduleBroadcastsLocked();
                // We need to reset the state if we failed to start the receiver.
                r.state = BroadcastRecord.IDLE;
                return;
            }

               // 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.
        //如果进程没启动,则要先启动进程
        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) {
            //进程启动失败的处理
            // Ah, this recipient is unavailable.  Finish it if necessary,
            // and mark the broadcast record as ready for the next.
            Slog.w(TAG, "Unable to launch app "
                        + info.activityInfo.applicationInfo.packageName + "/"
                        + info.activityInfo.applicationInfo.uid + " for broadcast "
                        + r.intent + ": process is bad");
            logBroadcastReceiverDiscardLocked(r);
            finishReceiverLocked(r, r.resultCode, r.resultData,
                                     r.resultExtras, r.resultAbort, false);
            scheduleBroadcastsLocked();
            r.state = BroadcastRecord.IDLE;
            return;
        }
        mPendingBroadcast = r; //设置mPendingBroadcast
        mPendingBroadcastRecvIndex = recIdx;

第三阶段的处理总结:

  1. 如果广播接收者为动态注册对象,则直接调用deliverToRegisteredReceiverLocked处理它;
  2. 如果广播接收者为静态注册对象,并且该对象对应的进程已经存在,则调用processCurBroadcastLocked处理它;
  3. 如果广播接收者为静态注册对象,并且该对象对应的进程还不存在,则需要创建该进程,这是最糟糕的情况。

sendBroadcast流程图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值