Android源码解析四大组件系列(七)---广播的发送过程

2024-09-02 14:58

本文主要是介绍Android源码解析四大组件系列(七)---广播的发送过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本篇文章的目录

1、广播数据结构分析
2、线程的切换
3、processNextBroadcast分析
  • 3.1、处理并行广播
  • 3.2、处理Pending广播
  • 3.3、处理有序广播
  • 3.4、获取下一条广播
  • 3.5、检查是否是动态广播
  • 3.6、检查是否是静态广播
  • 3.7、启动进程,处理未发送的静态广播
4、动态广播receiver处理
5、静态广播receiver处理

先了解一下广播的数据结构,然后在分析广播的处理过程。建议看本文,需要先看前面两篇文章

Android源码解析—广播的注册过程
Android源码解析—广播的处理过程

1、广播数据结构分析

final class BroadcastRecord extends Binder {final Intent intent;    // the original intent that generated usfinal ComponentName targetComp; // original component name set on the intentfinal ProcessRecord callerApp; // 广播调用者进程final String[] requiredPermissions; // 调用者需要的权限final List receivers;   //存储广播接收者, 包含 BroadcastFilter 和 ResolveInfoIIntentReceiver resultTo; // who receives final result if non-nulllong enqueueClockTime;  // 加入队列的时间long dispatchTime;      // 分发时间long dispatchClockTime; //分发时间long receiverTime;      // 接收时间.long finishTime;        广播完成时间int nextReceiver;       // 下一个广播接收者IBinder receiver;       //当前广播接收者int state;int anrCount;           //广播ANR次数ProcessRecord curApp;       // hosting application of current receiver.ComponentName curComponent; // the receiver class that is currently running.ActivityInfo curReceiver;   // info about the receiver that is currently running.}

比较重要的数据成员有receivers,存储的都是广播接收器,callerApp是广播调用者进程,还要注意四个时间点,有入队列,分发,接收,完成,另外动态广播节点用BroadcastFilter描述,静态的用ResolveInfo描述。

  • ReceiverDispatcher: 客户端广播分发者对象,第一篇讲的很清楚了,ReceiverDispatcher的内部类InnerReceiver为binder对象,用于与AMS的传递与通信。

  • ReceiverList: 继承自ArrayList,存放了Receiver的binder对象以及其注册的BroadcastFilter列表。AMS中定义了
    final HashMap

2、线程的切换

上篇说到不管是有序广播、无序广播还是粘性广播最终都是调用scheduleBroadcastsLocked处理的。那么scheduleBroadcastsLocked做了什么?

    public void scheduleBroadcastsLocked() {if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["+ mQueueName + "]: current="+ mBroadcastsScheduled);//mBroadcastsScheduled参数是用来标记是否已经向消息队列发送了一个类型为BROADCAST_INTENT_MSG消息if (mBroadcastsScheduled) {return;}//发送一个BROADCAST_INTENT_MSG消息mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));mBroadcastsScheduled = true;}

mHandler是BroadcastQueue的成员变量,定义如下

final BroadcastHandler mHandler;

它在BroadcastQueue构造函数中初始化

   BroadcastQueue(ActivityManagerService service, Handler handler,String name, long timeoutPeriod, boolean allowDelayBehindServices) {mService = service;mHandler = new BroadcastHandler(handler.getLooper());mQueueName = name;mTimeoutPeriod = timeoutPeriod;mDelayBehindServices = allowDelayBehindServices;}

参数中的handler是AMS中的MainHandler,所以BroadcastHandler采用的是ActivityManager线程的Looper,所以通过上面发送一个BROADCAST_INTENT_MSG消息,现在由system_server的binder线程切换到system_server的ActivityManager线程中。

    private final class BroadcastHandler extends Handler {public BroadcastHandler(Looper looper) {super(looper, null, true);}@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case BROADCAST_INTENT_MSG: {if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");// 处理广播processNextBroadcast(true);} break;case BROADCAST_TIMEOUT_MSG: {synchronized (mService) {//超时的时候走这里broadcastTimeoutLocked(true);}} break;case SCHEDULE_TEMP_WHITELIST_MSG: {DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;if (dic != null) {dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),msg.arg2, true, (String)msg.obj);}} break;}}}

所以现在重点分析processNextBroadcast方法。

3、processNextBroadcast分析

processNextBroadcast方法的代码跟broadcastIntentLocked方法一样,也是很长,所以分段来分析。

3.1、处理并行广播
   mService.updateCpuStats();//fromMsg字段标记是否是从handleMessage中调用的该方法  if (fromMsg) {//设置该参数为false,表示前面发送到消息队列中的BROADCAST_INTENT_MSG消息已经被处理了mBroadcastsScheduled = false;}//并行广播在这里循环一次性处理掉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.receivers里面的都是BroadcastFilterdeliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);}addBroadcastToHistoryLocked(r);if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["+ mQueueName + "] " + r);}
3.2、处理Pending广播

如果一个广播在发送的时候,进程还没有启动起来,那么会将它存在mPendingBroadcast中。由于动态广播是不会保证一定能够收到的,所以mPendingBroadcast是用来描述一个正在等待静态注册的目标广播接收者启动的广播。

  // 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.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 waitingreturn;} else {Slog.w(TAG, "pending app  ["+ mQueueName + "]" + mPendingBroadcast.curApp+ " died before responding to broadcast");mPendingBroadcast.state = BroadcastRecord.IDLE;mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;mPendingBroadcast = null;}}boolean looped = false;
3.3、处理有序广播

有序广播是一个接着一个处理的,并且还可以拦截,

do {//有序广播队列为0,不用处理,返回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.//更改一下OOMmService.updateOomAdjLocked();}return;}//获取一个有序广播(最顶部的BroadcastRecord)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();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 broadcastforceReceive = 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;}// 进入下面的条件有以下集中可能,一:广播没有接收者了,二:默认第一次r.nextReceiver = 0,但是它每次都会++,等待最后一个处理完了,再++就会得到一个不存在的nextReceiver,此时r.nextReceiver >= numReceivers,条件成立,三:
广播是否已经被拦截了,四:广播是否已经被强制结束了  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 {if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,"Finishing broadcast [" + mQueueName + "] "+ r.intent.getAction() + " app=" + r.callerApp);//处理广播消息消息,调用到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) {r.resultTo = null;Slog.w(TAG, "Failure ["+ mQueueName + "] sending broadcast result of "+ r.intent, e);}}if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");//r所描述的广播转发任务已经在规定时间内处理完了,需要remove掉前面给mHandler发送的BROADCAST_TIMEOUT_MSG消息。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);}// 将r所描述的广播转发任务从有序广播队列中删除  mOrderedBroadcasts.remove(0);//赋值为null,进入下一次循环r = null;looped = true;continue;}} while (r == null);
 3.4、获取下一条广播
    //通过上面的循环,r就有值了,获取下一条广播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);}ComponentName componentfinal BroadcastOptions brOptions = r.options;final Object nextReceiver = r.receivers.get(recIdx);```####3.5、检查是否是动态广播
 //检查是否是动态广播

if (nextReceiver instanceof BroadcastFilter) {
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设置为IDLE,表示不需要等待它的前一个目标广播接收者处理完成一个广播,
// 就可以将该广播继续发送给它的下一个目标广播接收者处理
r.state = BroadcastRecord.IDLE;
//执行下一个广播,内部也是发送消息
scheduleBroadcastsLocked();
} else {
….
}
//有序广播一次只处理一个,直接返回就行
return;
}


####3.6、检查是否是静态广播

//如果上面没有return,那么肯定是静态注册的广播,静态注册注册的广播节点是ResolveInfo
ResolveInfo info = (ResolveInfo)nextReceiver;
//这个ComponentName会一直传递到ActivityThread,用来反射new广播接收者对象的
ComponentName component = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
//很多的条件判断,skip不满足就为true
boolean skip = false;
…….

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

…….
//如果当前进程存在,调用processCurBroadcastLocked处理,静态广播都是走processCurBroadcastLocked处理的
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) {
Slog.w(TAG, “Exception when sending broadcast to ”
+ r.curComponent, 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.
}

//程序走到这里,说明进程不存在,那么调用startProcessLocked启动进程,
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;
}
//把当前的r存下来,方便下一次处理
mPendingBroadcast = r;
//设置当前的receiver的索引,用来表示将要启动的。
mPendingBroadcastRecvIndex = recIdx;

“`

3.7、启动进程,处理未发送的静态广播

当进程启动完成之后,会回调AMS的attachApplication,然后走到attachApplicationLocked。
“`
// Check if a next-broadcast receiver is in this process…
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
didSomething |= sendPendingBroadcastsLocked(app);
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it ‘bad’
Slog.wtf(TAG, “Exception thrown dispatching broadcasts in ” + app, e);
badApp = true;
}
}



// The app just attached; send any pending broadcasts that it should receive
boolean sendPendingBroadcastsLocked(ProcessRecord app) {
boolean didSomething = false;
for (BroadcastQueue queue : mBroadcastQueues) {
didSomething |= queue.sendPendingBroadcastsLocked(app);
}
return didSomething;
}

public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
boolean didSomething = false;
final BroadcastRecord br = mPendingBroadcast;
if (br != null && br.curApp.pid == app.pid) {
if (br.curApp != app) {
Slog.e(TAG, “App mismatch when sending pending broadcast to ”
+ app.processName + “, intended target is ” + br.curApp.processName);
return false;
}
try {
//目标进程已经成功启动了,那么mPendingBroadcast就可以赋值为null了
mPendingBroadcast = null;
//调用processCurBroadcastLocked处理广播
processCurBroadcastLocked(br, app);
didSomething = true;
} catch (Exception e) {
Slog.w(TAG, “Exception in new application when starting receiver ”
+ br.curComponent.flattenToShortString(), e);
logBroadcastReceiverDiscardLocked(br);
finishReceiverLocked(br, br.resultCode, br.resultData,
br.resultExtras, br.resultAbort, false);
scheduleBroadcastsLocked();
// We need to reset the state if we failed to start the receiver.
br.state = BroadcastRecord.IDLE;
throw new RuntimeException(e.getMessage());
}
}
return didSomething;
}

“`

看完上面的三个小节,到这里总结一下 processNextBroadcast()的代码逻辑:

  • 如果是动态广播接收者(无序),会调用deliverToRegisteredReceiverLocked一次性处理,即遍历并行列表(mParallelBroadcasts)的每一个BroadcastRecord以及其中的receivers列表,是一个双重循环。
  • 如果是静态广播接收者(有序),且对应进程已经创建,会调用processCurBroadcastLocked继续处理;
  • 如果是静态广播接收者(有序),且对应进程尚未创建,会调用startProcessLocked创建进程,之后仍然会调用processCurBroadcastLocked继续处理。

4、动态广播receiver处理

上面主要分析了动态广播接收者和静态广播接收者该如何处理,现在先看动态广播是如何处理的。就是分析deliverToRegisteredReceiverLocked方法实现。
“`
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
boolean skip = false;
//权限判断, 检查发送者是否有权限,检查接收者是否有发送者所需的权限等等,
//此处省略,不符合的skip==true,下面就return。
….

    if (skip) {r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;return;}....//只有有序广播才会进入这个分支if (ordered) {r.receiver = filter.receiverList.receiver.asBinder();r.curFilter = filter;filter.receiverList.curBroadcast = r;r.state = BroadcastRecord.CALL_IN_RECEIVE;if (filter.receiverList.app != null) {// Bump hosting application to no longer be in background// scheduling class.  Note that we can't do that if there// isn't an app...  but we can only be in that case for// things that directly call the IActivityManager API, which// are already core system stuff so don't matter for this.r.curApp = filter.receiverList.app;filter.receiverList.app.curReceiver = r;mService.updateOomAdjLocked(r.curApp);}}try {if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,"Delivering to " + filter + " : " + r);if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {// Skip delivery if full backup in progress// If it's an ordered broadcast, we need to continue to the next receiver.if (ordered) {skipReceiverLocked(r);}} else {//处理广播,filter.receiverList.receiver对应的是客户端ReceiverDispatcher的Binder实体——InnerReceiverperformReceiveLocked(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) {....}
}

“`

 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) {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);}}
       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);//走到ReceiverDispatcher中的performReceive实际是InnerReceiver内部类当中的方法receiver.performReceive(intent, resultCode, dataStr, extras, ordered,sticky, sendingUser);}

终于走到客户端的ReceiverDispatcher(广播分发者)了,ReceiverDispatcher知道我们这个广播要分发给谁。此时正式由SystemServer进程回到客户端进程了。

    @Overridepublic 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 {// 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.if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,"Finishing broadcast to unregistered receiver");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();}}}

可以看到我们调用ReceiverDispatcher中InnerReceiver的performReceive之后,紧接着在内部调用了ReceiverDispatcher的performReceive方法,再看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 {if (ActivityThread.DEBUG_BROADCAST) {int seq = intent.getIntExtra("seq", -1);Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()+ " seq=" + seq + " to " + mReceiver);}}//post了一个消息给主线程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在第一篇文章说过,代表主线程,所以现在会执行args的run方法。

   public void run() {final BroadcastReceiver receiver = mReceiver;final boolean ordered = mOrdered;if (ActivityThread.DEBUG_BROADCAST) {int seq = mCurIntent.getIntExtra("seq", -1);Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()+ " seq=" + seq + " to " + mReceiver);Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered+ " mOrderedHint=" + ordered);}final IActivityManager mgr = ActivityManagerNative.getDefault();final Intent intent = mCurIntent;if (intent == null) {Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);}......try {ClassLoader cl =  mReceiver.getClass().getClassLoader();intent.setExtrasClassLoader(cl);intent.prepareToEnterProcess();setExtrasClassLoader(cl);receiver.setPendingResult(this);//onReceive方法回调receiver.onReceive(mContext, intent);} catch (Exception e) {.....}

到此,deliverToRegisteredReceiverLocked是怎么处理动态广播就分析完毕了。总结一下主要流程

——|-BroadcastQueue.performReceiveLocked()
——|——-|-ActivityThread.ApplicationThread.scheduleRegisteredReceiver()
——|——-|——-|- ReceiverDispatcher.InnerReceiver.performReceive()
——|——-|——-|——-|-Handler.post(args)
——|——-|——-|——-|——-|-Args.run()
——|——-|——-|——-|——-|——-|-BroadcastReceiver.onReceive()

5、静态广播receiver处理

刚刚说了静态广播是processCurBroadcastLocked处理的

    private final void processCurBroadcastLocked(BroadcastRecord r,ProcessRecord app) throws RemoteException {.....r.receiver = app.thread.asBinder();r.curApp = app;app.curReceiver = r;//更新进程状态app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);//更新内存mService.updateLruProcessLocked(app, false, null);//更新adjmService.updateOomAdjLocked();// Tell the application to launch this receiver.告诉客户端启动这个receiverr.intent.setComponent(r.curComponent);boolean started = false;try {.....//走到了ActivityThread中的ApplicationThread中对应的方法。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);if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,"Process cur broadcast " + r + " DELIVERED for app " + app);started = true;} finally {.....}}}

此时正式由SystemServer进程进入了客户端进程了

 public final void scheduleReceiver(Intent intent, ActivityInfo info,CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,boolean sync, int sendingUser, int processState) {updateProcessState(processState, false);ReceiverData r = new ReceiverData(intent, resultCode, data, extras,sync, false, mAppThread.asBinder(), sendingUser);r.info = info;r.compatInfo = compatInfo;sendMessage(H.RECEIVER, r);}

一样的套路,发送一个消息给主线程,进入对应的case,执行 handleReceiver((ReceiverData)msg.obj);

    private void handleReceiver(ReceiverData data) {// 这个最初就是在processNextBroadcast处理静态注册的ResolveInfo时,new的ComponentName。String component = data.intent.getComponent().getClassName();LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo);IActivityManager mgr = ActivityManagerNative.getDefault();BroadcastReceiver receiver;try {//反射出BroadcastReceiverjava.lang.ClassLoader cl = packageInfo.getClassLoader();data.intent.setExtrasClassLoader(cl);data.intent.prepareToEnterProcess();data.setExtrasClassLoader(cl);receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();} catch (Exception e) {if (DEBUG_BROADCAST) Slog.i(TAG,"Finishing failed broadcast to " + data.intent.getComponent());data.sendFinished(mgr);throw new RuntimeException("Unable to instantiate receiver " + component+ ": " + e.toString(), e);}try {Application app = packageInfo.makeApplication(false, mInstrumentation);if (localLOGV) Slog.v(TAG, "Performing receive of " + data.intent+ ": app=" + app+ ", appName=" + app.getPackageName()+ ", pkg=" + packageInfo.getPackageName()+ ", comp=" + data.intent.getComponent().toShortString()+ ", dir=" + packageInfo.getAppDir());ContextImpl context = (ContextImpl)app.getBaseContext();sCurrentBroadcastIntent.set(data.intent);receiver.setPendingResult(data);//这个和动态的不一样,静态的广播onReceive方法中的context是RestrictedContextreceiver.onReceive(context.getReceiverRestrictedContext(),data.intent);} catch (Exception e) {if (DEBUG_BROADCAST) Slog.i(TAG,"Finishing failed broadcast to " + data.intent.getComponent());data.sendFinished(mgr);if (!mInstrumentation.onException(receiver, e)) {throw new RuntimeException("Unable to start receiver " + component+ ": " + e.toString(), e);}} finally {sCurrentBroadcastIntent.set(null);}if (receiver.getPendingResult() != null) {data.finish();}}

到这总结一下静态广播接收者的处理流程,如下:
如果应用程序已经启动(app.thread != null)
——|-ActivityThread.ApplicationThread.scheduleReceiver()
——|——|- ActivityThread.handleReceiver()
——|——-|——-|- BroadcastReceiver.onReceive()
否则
——|-LoadedApk.ReceiverDispatcher.IntentReceiver.performReceive()
——|——-|-LoadedApk.ReceiverDispatcher.performReceiver()
——|——-|——-|- LoadedApk.ReceiverDispatcher.Args.run()
——|——-|——-|——-|-BroadcastReceiver.onReceive()

至此广播的处理过程就结束了,下篇写一下广播细节,加深理解,比如广播有序是怎么保证的?怎么实现广播拦截处理的?广播超时是怎么处理的?onReceive方法中可以在发送广播吗?registerReceiver方法发返回值有什么用?粘性广播等等

这篇关于Android源码解析四大组件系列(七)---广播的发送过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1130279

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

高效录音转文字:2024年四大工具精选!

在快节奏的工作生活中,能够快速将录音转换成文字是一项非常实用的能力。特别是在需要记录会议纪要、讲座内容或者是采访素材的时候,一款优秀的在线录音转文字工具能派上大用场。以下推荐几个好用的录音转文字工具! 365在线转文字 直达链接:https://www.pdf365.cn/ 365在线转文字是一款提供在线录音转文字服务的工具,它以其高效、便捷的特点受到用户的青睐。用户无需下载安装任何软件,只

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo