Android 7.0 ActivityManagerService(5) 广播(Broadcast)相关流程分析(2).doc_第1页
Android 7.0 ActivityManagerService(5) 广播(Broadcast)相关流程分析(2).doc_第2页
Android 7.0 ActivityManagerService(5) 广播(Broadcast)相关流程分析(2).doc_第3页
Android 7.0 ActivityManagerService(5) 广播(Broadcast)相关流程分析(2).doc_第4页
Android 7.0 ActivityManagerService(5) 广播(Broadcast)相关流程分析(2).doc_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Android 7.0 ActivityManagerService(5) 广播(Broadcast)相关流程分析(2)4 broadcastIntentLocked函数Part IV./ Merge into one ir = 0;if (receivers != null) / A special case for PACKAGE_ADDED: do not allow the package / being added to see this broadcast. This prevents them from / using this as a back door to get run as soon as they are / installed. Maybe in the future we want to have a special install / broadcast or such for apps, but wed like to deliberately make / this decision. /处理特殊的Action,例如PACKAGE_ADDED,系统不希望有些应用一安装就能启动 /APP安装后,PKMS将发送PACKAGE_ADDED广播 /若没有这个限制,在刚安装的APP内部静态注册监听该消息的BroadcastReceiver,新安装的APP就能直接启动 String skipPackages = null; if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction() | Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction() | Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction() Uri data = intent.getData(); if (data != null) String pkgName = data.getSchemeSpecificPart(); if (pkgName != null) skipPackages = new String pkgName ; else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction() skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); if (skipPackages != null & (skipPackages.length 0) for (String skipPackage : skipPackages) if (skipPackage != null) int NT = receivers.size(); for (int it=0; itNT; it+) ResolveInfo curt = (ResolveInfo)receivers.get(it); if (curt.activityInfo.packageName.equals(skipPackage) /将skipPackages对应的BroadcastReceiver移出receivers receivers.remove(it); it-; NT-; int NT = receivers != null ? receivers.size() : 0; int it = 0; ResolveInfo curt = null; BroadcastFilter curr = null; /NT对应的是静态BroadcastReceiver的数量 /NR对应的是动态BroadcastReceiver的数量 /若发送的是无序广播,此时NR为0 /若是有序广播,才会进入下面两个while循环 /下面两个while循环就是将静态注册的BroadcastReceiver和动态注册的BroadcastReceiver /按照优先级合并到一起(有序广播才会合并) while (it NT & ir = curt.priority) / Insert this broadcast record into the final list. receivers.add(it, curr); ir+; curr = null; it+; NT+; else / Skip to the next ResolveInfo in the final list. it+; curt = null; while (ir 0) | resultTo != null) BroadcastQueue queue = broadcastQueueForIntent(intent); /构造对应的BroadcastRecord BroadcastRecord r = new BroadcastRecord(.); . /同样判断是否需要替换,这里是Ordered Queue boolean replaced = replacePending & queue.replaceOrderedBroadcastLocked(r); if (!replaced) /没替换时,就加入Ordered Queue queue.enqueueOrderedBroadcastLocked(r); /触发发送流程 queue.scheduleBroadcastsLocked(); else / There was nobody interested in the broadcast, but we still want to record / that it happened. if (intent.getComponent() = null & intent.getPackage() = null & (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) = 0) / This was an implicit broadcast. lets record it for posterity. /没有处理的静态或有序广播,保存起来 /感觉保存起来也没什么用啊 addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0); .简单来说,broadcastIntentLocked的第四部分工作就是为有序广播和静态广播,构造对应的BroadcastRecord(按优先级顺序), 然后将BroadcastRecord加入到Ordered Queue中,并触发广播发送流程。至此,整个broadcastIntentLocked函数分析完毕,除去一些条件判断的细节外,整个工作流程如下图所示:1、处理粘性广播。 由于粘性广播的特性(BroadcastReceiver注册即可接收),系统必须首先保存粘性广播。2、处理普通动态广播。 普通广播是并发的,系统优先为动态注册的BroadcastReceiver发送广播。 动态广播对应的BroadcastRecord加入到Parallel Queue中。3、处理静态广播和有序广播。 这一步主要是为静态注册的BroadcastReceiver发送广播,对应的BroadcastRecord加入到Ordered Queue中。此外,需要注意的是: 如果广播是有序的,那么第2步不会为动态注册的BroadcastReceiver发送广播,而是在第3步统一发送。 发送有序广播时,AMS将按照BroadcastReceiver的优先级,依次构造BroadcastRecord加入到Ordered Queue中。四、BroadcastQueue的scheduleBroadcastsLocked函数流程分析 从上面的代码,我们知道广播发送方调用sendBroadcast后,AMS会构造对应的BroadcastRecord加入到BroadcastQueue中, 然后调用BroadcastQueue的scheduleBroadcastsLocked函数。现在,我们就来看一下scheduleBroadcastsLocked相关的流程。public void scheduleBroadcastsLocked() . /避免短时间内重复发送BROADCAST_INTENT_MSG if (mBroadcastsScheduled) return; mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this); mBroadcastsScheduled = true;上面的代码将发送BROADCAST_INTENT_MSG,触发BroadcastQueue调用processNextBroadcast进行处理。 processNextBroadcast函数同样非常的长,大概有500多行。我们还是分段进行分析。1 processNextBroadcast函数Part Ifinal void processNextBroadcast(boolean fromMsg) synchronized(mService) BroadcastRecord r; . /更新CPU的使用情况 /处理静态广播时,可能需要拉起对应进程,因此在这里先记录一下CPU情况 mService.updateCpuStats(); if (fromMsg) /处理BROADCAST_INTENT_MSG后,将mBroadcastsScheduled置为false /scheduleBroadcastsLocked就可以再次被调用了 mBroadcastsScheduled = false; / First, deliver any non-serialized broadcasts right away. /先处理“并发”发送的普通广播 while (mParallelBroadcasts.size() 0) /依次取出BroadcastRecord r = mParallelBroadcasts.remove(0); /记录发送的时间 r.dispatchTime = SystemClock.uptimeMillis(); r.dispatchClockTime = System.currentTimeMillis(); final int N = r.receivers.size(); . for (int i=0; i 0) for (int i = 0; i 0) long now = SystemClock.uptimeMillis(); if (numReceivers 0) & /单个广播处理的超时时间,定义为2 * 每个接收者处理的最长时间(10s)* 接收者的数量 (now r.dispatchTime + (2*mTimeoutPeriod*numReceivers) . /如果超时,则强制结束这条广播的处理 broadcastTimeoutLocked(false); / forcibly finish this broadcast forceReceive = true; r.state = BroadcastRecord.IDLE; if (r.state != BroadcastRecord.IDLE) /BroadcastRecord还未处理或处理完毕后,状态为IDLE态 . 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 . /广播处理完毕,将该广播的处理结果发送给resultTo对应BroadcastReceiver performReceiveLocked(r.callerApp, r.resultTo, new Intent(ent), r.resultCode, r.resultData, r.resultExtras, false, false, r.userId); catch (RemoteException e) . . cancelBroadcastTimeoutLocked(); addBroadcastToHistoryLocked(r); /作一下记录 if (ent.getComponent() = null & ent.getPackage() = null & (ent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) = 0) / This was an implicit broadcast. lets record it for posterity. mService.addBroadcastStatLocked(ent.getAction(), r.callerPackage, r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime); mOrderedBroadcasts.remove(0); /一个BroadcastRecord处理完毕后,将r置为null r = null; /如果一个广播处理完毕,说明可能拉起过进程,于是looped置为true looped = true; continue; /r = null时,可以处理下一个BroadcastRecord/r != null, 继续处理当前BroadcastRecord的下一个BroadReceiver while (r = null);.这一部分代码,乍一看有点摸不着头脑的感觉,其实主要做了两个工作: 1、判断是否有PendingBroadcast。 当存在PendingBroadcast,且当前正在等待启动的进程并没有死亡,那么不能处理下一个BroadcastRecord,必须等待PendingBroadcast处理完毕。2、处理mOrderedBroadcasts中的BroadcastRecord 由于有序广播和静态广播,必须一个接一个的处理。 因此每发送完一个广播后,均会重新调用processNextBroadcast函数。在发送新的BroadcastRecord时,需要先处理旧有BroadcastRecord的状态。于是,这段代码后续部分,主要进行了以下操作: 若所有BroadcastRecord均处理完毕,利用AMS释放掉无用进程; 更新超时BroadcastRecord的状态,同时越过此BroadcastRecord; 当一个BroadcastRecord处理完毕后,将结果发送给指定BroadcastReceiver(指定了接收者,才进行此操作), 同时将该BroadcastRecord从mOrderedBroadcasts中移除。这一系列动作的最终目的,就是选出下一个处理的BroadcastRecord, 然后就可以开始向该BroadcastRecord中下一个BroadcastReceiver发送广播了。这一部分整体的判断逻辑大致上如下图所示:3 processNextBroadcast函数Part III./ Get the next receiver./ 开始处理当前BroadcastRecord的下一个BroadcastReceiverint 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) /记录整个BroadcastRecord的起始时间 r.dispatchTime = r.receiverTime; r.dispatchClockTime = System.currentTimeMillis(); .if (! mPendingBroadcastTimeoutMessage) long timeoutTime = r.receiverTime + mTimeoutPeriod; . /设置广播处理的超时时间为10s setBroadcastTimeoutLocked(timeoutTime);final BroadcastOptions brOp

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论