diff --git a/blogs/Android/Framework/Interview/其他应用组件相关/静态广播的注册和收发原理.md b/blogs/Android/Framework/Interview/其他应用组件相关/静态广播的注册和收发原理.md new file mode 100644 index 0000000..9915e50 --- /dev/null +++ b/blogs/Android/Framework/Interview/其他应用组件相关/静态广播的注册和收发原理.md @@ -0,0 +1,217 @@ +--- +静态广播的注册和收发原理 +--- + +```java +//... +else if(tagName.equals("receiver")) { + // class Activity extends Component{} + Activity a = parseActivity(owner, res, parser, attrs, flags, ...); + owner.receivers.add(a); +} +``` + +#### 广播的发送 + +```java +@Override +public void sendBroadcast(Intent intent) { + ActivityManagerNative.getDrfault().broadcastIntent(mMainThread.getApplicationThread(), intent, ...); +} +int broadcastIntent(IApplicationThread caller, Intent intent, ...) { + int res = broadcastIntentLocked(callerApp, ...); + return res; +} +int broadcastIntentLocked(ProcessRecord callerApp, ...) { + // 找静态注册的 receiver + List receivers = collectReceiverComponents(intent, resolvedType, ...); + // 找动态注册的 receiver + List registeredReceivers = mReceiverResolver.queryIntent(intent, ...); + if(!ordered && registeredReceivers.size()>0) { + // 处理动态 receiver,加到并行分发队列 + } + // 给没有处理完的动态 receiver,跟静态 receiver 合并到一起 + if((receivers != null && receivers.size() > 0)){ + // 处理剩下的 receiver,加到串行分发队列 + BroadcastQueue queue = boradcastQueueForIntent(intent); + BroadcastRecord r = new BroadcastRecord(queue, intent, ...); + queue.enqueueOrderedBroadcastLocked(r); + queue.scheduleBroadcast(); + } + return ActivityManager.BROADCAST_SUCCESS; +} +final void processNextBroadcast(boolean formMsg){ + // 先给并行分发的广播分发完,然后接下来分发串行广播 + // 如果有 pending 的广播,就先直接返回,这个广播在等待应用进程启动 + // 如果当前广播分发超时了,就废弃这个广播,处理下一个广播 + // 如果没有超时,并且正在分发中,就先返回,什么也不做 + // 如果当前的广播已经分发完一个 receive 了,就继续分发下一个 receive + // 如果这个 receive 是动态注册的 receive,就直接分发 + // 如果这个 receive 是静态注册的 receive,就先看进程启动没有 + // 如果进程启动了,就直接分发 + // 没启动的话就先启动进程,然后给广播标记为 pending + // 进程启动后 attachApplication 时继续处理这个 pending 的广播 +} +// 超时 +do{ + r = mOrderedBroadcasts.get(0); + if(now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers)){ + // 超时善后工作 + boradcastTimeoutLocked(false); + forceReceive = true; + r.state = BroadcastRecord.IDLE; + } + if(r.state != BroadcastRecord.IDLE){ + return; + } + if(r.receivers == null || r.nextReceiver >= numReceivers || forceReceive) { + cancelBroadcastTimeoutLocked(); + mOrderBroadcasts.remove(0); + continue; + } +} while(r == null); + +final void boradcastTimeoutLocked(boolean fromMsg) { + BroadcastRecord r = mOrderedBroadcasts.get(0); + Object curReceiver = r.receivers.get(r.nextReceiver - 1); + // 找到当前分发的 receiver 对应的进程 + + if(mPendingBroadcast == r){ + mPendingBroadcast = null; + } + finishReceiverLocked(r, r.resultCode, ...); + scheduleBroadcastsLocked(); + mHandler.post(new AppNotResponding(app, anrMessage)); +} + +// 没有超时的情况 +int recldx = r.nextReceiver++; +r.receiverTime = SystemClock.uptimeMillis(); +if(recldx == 0){ + r.dispatchTime = r.receiverTime; + r.dispatchClockTime = System.currentTimeMillis(); +} +if(!mPendingBroadcastTimeoutMessage) { + long timeoutTime = r.receiverTime + mTimeoutPeriod; + setBroadcastTimeoutLocked(timeoutTime); +} +final Object nextReceiver = r.receivers.get(index); +if(nextReceiver instanceof BroadcastFilter) { + // 如果是动态 receiver,直接分发 + BroadcastFilter filter = (BroadcastFilter)nextReceiver; + deliverToRegisterReceiverLocked(r, filter, r.ordered); + return; +} +// 静态 receiver,分发之前先判断进程是否已经启动 +r.state = BroadcastRecord.APP_RECEIVE; +ProcessRecord app = mService.getProcessRecordLocked(targetProcess, ...); +if(app != null && app.thread != null){ + // 进程已经启动,直接分发 + processCurBroadcastLocked(r, app); + return; +} +// 启动进程,并且设置 pending 状态 +r.curApp = mService.startProcessLocked(targetProcess, ...); +mPendingBroadcast = r; +mPendingBroadcastRecvIndex = recldx; +``` + +#### 广播的接收 + +```java +// 动态 receiver +void deliverToRegisteredReceiverLocked(BroadcastRecord r, ...) { + performReceiveLocked(filter.receiverList.app, ...); + if(ordered) { + r.state = BroadcastRecord.CALL_DONE_RECEIVE; + } +} +void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, ...) { + app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, ...); +} +// 调到应用端处理 +void scheduleRegisteredReceiver(){ + final BroadcastReceiver receiver = mReceiver; + final boolean ordered = mOrdered; + final Intent intent = mCurIntent; + mCurIntent = null; + receiver.setPendingResult(this); + receiver.onReceive(mContext, intent); + if(receiver.getPendingResult() != null){ + finish(); + } +} +// 通知 AMS 广播已经分发完了 +void finish(){ + IActivityManager mgr = ActivityManagerNative.getDefault(); + mgr.finishReceiver(...); +} +void finishReceiver(IBinder who, int resultCode, ...) { + boolean doNext = false; + BroadcastRecord r = queue.getMatchingOrderedReceiver(who); + doNext = r.queue.finishReceiverLocked(r, resultCode, ...); + if(doNext){ + r.queue.processNextBroadcast(false); + } +} +public boolean finishReceiverLocked(BroadcastRecord r, ...) { + final int state = r.state; + return state == BroadcastRecord.APP_RECEIVE + || state == BroadcastRecord.CALL_DONE_RECEIVE; +} +``` + +静态 receiver 分发: + +```java +void processCurBroadcastLocked(BroadcastRecord r, ...) { + r.receiver = app.thread.asBinder(); + r.curApp = app; + app.curReceiver = r; + app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver, ...); +} +void scheduleReceiver(Intent intent, ActivityInfo info, ...) { + ReceiverData r = new ReceiverData(intent, resultCode, data, ...); + r.info = info; + r.compatInfo = compatInfo; + sendMessage(H.RECEIVER, r); +} +private void handleReceiver(ReceiverData data) { + LoadedApk pakcageInfo = getPackageInfoNoCheck(...); + BroadcastReceiver receiver; + receiver = cl.loadClass(component).newInstance(); + Application app = packageInfo.makeApplication(false, ...); + ContextImpl context = app.getBaseContext(); + receiver.setPendingResult(data); + receiver.onReceive(context.getReceiverRestrictedContext(), data.intent); + if(receiver.getPendingResult() != null) { + data.finish(); + } +} +``` + +应用进程启动之后,向 AMS 报告,然后启动 pengdingBroadcast: + +```java +boolean attachApplicationLocked(IApplicationThread thread, ...) { + sendPendingBroadcastsLocked(app); +} +boolean sendPendingBroadcastsLocked(ProcessRecord app) { + for(BroadcastQueue queue : mBroadcastQueues){ + queue.sendPendingBroadcastsLocked(app); + } +} +boolean sendPendingBroadcastsLocked(ProcessRecord app) { + final BroadcastRecord br = mPendingBroadcast; + if(br != null && br.curApp.pid == app.pid) { + mPendingBroadcast = null; + processCurBroadcastLocked(br, app); + } +} +``` + +#### 说说静态广播的注册和收发原理 + +1. 静态广播是怎么注册的 +2. 静态广播是串行分发的 +3. 静态广播的生命周期及上下文 \ No newline at end of file