[Android]有序广播是如何实现有序循环(五)

[Android]有序广播是如何实现有序循环(五)

Overview

而对有序广播来说,==原则上每次processNextBroadcast()只会将BroadcastRecord发送给一个receiver而已。当然,此时摘下的receiver既有可能是动态注册的,也有可能是静态的==。
对于动态注册的receiver,目标进程处理完广播之后,会间接调用am.finishReceiver()向AMS发出反馈,关于这一步,前文在讲Args.run()时已有涉及,只是当时主要关心的是里面的receiver.onReceive()一句,现在我们要关心其中的receiver.setPendingResult()一句:
不论任何广播,在APK处理完后,都要通知到AMS做一些收尾工作.

1. 平行广播的循环前面已经讲到过

参考BroadcastQueue如何分发广播(四)

2. 有序广播是如何循环起来的?

2.1 如何将有序广播BroadcastRecord 发送给动态注册的Receiver?

重点是,有序广播是如何循环起来的?

回顾 Ams中创建BroadcastRecord的代码,mReceivers集合中是有两种对象:ResolveInfo/BroadcastFilter

  • BroadcastFilter 即是动态注册的Receiver
if (nextReceiver instanceof BroadcastFilter) {
    // Simple case: this is a registered receiver who gets
    // a direct call.
    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;
}

NOTE:
执行流程类似于平行广播,最终也会进入到LoadedApk.ReceiverDispatcher($Args)
区别在于:
deliverToRegisteredReceiverLocked(r, filter, /order/ r.ordered, recIdx) //

最终还是会进入到Args.run(){}

try {
    ClassLoader cl =  mReceiver.getClass().getClassLoader();
    intent.setExtrasClassLoader(cl);
    intent.prepareToEnterProcess();
    setExtrasClassLoader(cl);
    // 注意,把自己设到BroadcastReceiver的mPendingResult域里了
    receiver.setPendingResult(this);
    receiver.onReceive(mContext, intent);
} catch (Exception e) {}

if (receiver.getPendingResult() != null) {
    finish();
}

frameworks/base/core / java / android / content /BroadcastReceiver.java

if (mType == TYPE_COMPONENT) {
                ...
} else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
    final IActivityManager mgr = ActivityManagerNative.getDefault();
    sendFinished(mgr); 
}
  • mType 对于registed广播来说,在注册时就已经决定
public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
                    boolean ordered, boolean sticky, int sendingUser) {
    super(resultCode, resultData, resultExtras, 
        mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, 
        ordered, sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
    mCurIntent = intent;
    mOrdered = ordered;
}
  • frameworks/base/core / java / android / content /BroadcastReceiver.java
public void sendFinished(IActivityManager am) {
    synchronized (this) {
       ...
        mFinished = true;
        try {
              // 注册此处的区别,对于ordered广播,需要保留resultCode resultData,resultExtras, mAbortBroadcst等信息,而对于
              // 并行广播,无须关注这些
            if (mOrderedHint) {
                // 将广播结束的消息告知Ams
                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.java
public void finishReceiver(IBinder who, int resultCode, String resultData,
            Bundle resultExtras, boolean resultAbort, int flags) {
      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) {
                    // finishReceiverLocked做善后工作,判断该节点是否还需要继续分发
                  doNext = r.queue.finishReceiverLocked(r, resultCode,
                      resultData, resultExtras, resultAbort, true);
              }
          }
          //
          if (doNext) {
              r.queue.processNextBroadcast(false);
          }
      } finally {
      }
}
  • BroadcastQueue.java
public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
            String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
    // 保存之前的状态
    final int state = r.state;
    final ActivityInfo receiver = r.curReceiver;
    r.state = BroadcastRecord.IDLE;

    // 这里为什么要做大量的置空操作?
    r.receiver = null;
    r.intent.setComponent(null);
    if (r.curApp != null && r.curApp.curReceiver == r) {
        r.curApp.curReceiver = null;
    }
    if (r.curFilter != null) {
        r.curFilter.receiverList.curBroadcast = null;
    }
    r.curFilter = null;
    r.curReceiver = null;
    r.curApp = null;
    mPendingBroadcast = null;

    // 保留上个receiver的操作结果
    r.resultCode = resultCode;
    r.resultData = resultData;
    r.resultExtras = resultExtras;

        ...
    r.curComponent = null;
    // We will process the next receiver right now if this is finishing
    // an app receiver (which is always asynchronous) or after we have
    // come back from calling a receiver.
    return state == BroadcastRecord.APP_RECEIVE
            || state == BroadcastRecord.CALL_DONE_RECEIVE;
    }
思考:
这里为何要做大量的置空操作?
每次在deliverToRegisteredReceiverLocked,都会在BroadcastRecord保存当前receiver对应信息,
而当发送完成时置空,释放对之前Receiver对应的内存,
下次在deliver时,重置赋值,而且这些信息只对Ordered广播有效
思考:

最后的state 为什么要== APP_RECEIVE/ CALL_DONE_RECEIVE

针对ordered广播在deliver后,都会重置状态,表示该节点的发送状态;当在finish时重置r.state = Idle,以便将此records分发给下一个receiver.

总结:
==至此,一个动态receive的接收就结束了==

2.2 对于静态注册的Receiver是如何有序循环的?

// 对于静态广播的接收是由ActivityThread来分发的

private void handleReceiver(ReceiverData data) 
{
    . . . . . .
    IActivityManager mgr = ActivityManagerNative.getDefault();
    BroadcastReceiver receiver;
    try {
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        data.intent.setExtrasClassLoader(cl);
        data.setExtrasClassLoader(cl);
        receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
    } catch (Exception e) {
        . . . . . .
    }
    try {
        . . . . . .
        receiver.setPendingResult(data);
        receiver.onReceive(context.getReceiverRestrictedContext(), data.intent);
    } catch (Exception e) {
        . . . . . .
    } finally {
        sCurrentBroadcastIntent.set(null);
    }
    if (receiver.getPendingResult() != null) {
        data.finish();
    }
}
  • ActivityThread.java
public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras,
                boolean ordered, boolean sticky, IBinder token, int sendingUser) {
    super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky,
            token, sendingUser, intent.getFlags());
    this.intent = intent;
}
  • BroadcastReceiver.java
public final void finish() {
    if (mType == TYPE_COMPONENT) {
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        if (QueuedWork.hasPendingWork()) {
            ...
        } else {
            sendFinished(mgr);
        }
    } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
        ...
    }
}

==至此,静态receiver的完整分发流程结束==

总结:
receiver分发完成后,若是需要发送下一个receiver,依然是要回到processNextBroadcast(),而每次process只能发送到一个receiver

3. BroadcastRecord 完整的发送

如何将Broadcast完整的发送给所有的receiver

do{
    int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;

    // nextReceiver > numReceivers,即表示发送到了该节点的最后一条
    if (r.receivers == null || r.nextReceiver >= numReceivers
                            || r.resultAbort || forceReceive) {
        // No more receivers for this broadcast!  Send the final
        // result if requested...
        cancelBroadcastTimeoutLocked();

        // 添加到Broadcast 记录
        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);
        }
            // 并且需要将这个操作完成的节点,从list中移除    
        mOrderedBroadcasts.remove(0);
        r = null;
        looped = true;
        continue;
    }
} while ( r != null)    
总结:
==当执行到此处表示最后一个receive也分发完成,需要将该节点移除,并处理下一个节点==

猜你喜欢

转载自blog.csdn.net/s394500839/article/details/77606753