在SDK中同样定义了好几个函数用于发送广播。不过,根据之前的经验,最终和AMS交互的函数可能通过一个接口就能完成。来看最简单的广播发送函数sendBroadcast,其代码如下:
**ContextImpl.java::sendBroadcast**
~~~
public void sendBroadcast(Intent intent) {
StringresolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.setAllowFds(false);
//调用AMS的brodcastIntent,在SDK中定义的广播发送函数最终都会调用它
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, false, false);
}......
}
~~~
AMS的broadcastIntent函数的主要工作将交由AMS的broadcastIntentLocked来完成,故此处直接分析broadcastIntentLocked。
1. broadcastIntentLocked分析
我们分阶段来分析broadcastIntentLocked的工作,先来看第一阶段工作。
(1) broadcastIntentLocked分析之一
**ActivityManagerService.java::broadcastIntentLocked**
~~~
private final int broadcastIntentLocked(ProcessRecordcallerApp,
StringcallerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundlemap, String requiredPermission,
boolean ordered, boolean sticky, int callingPid, int callingUid) {
intent =new Intent(intent);
//为Intent增加FLAG_EXCLUDE_STOPPED_PACKAGES标志,表示该广播不会传递给被STOPPED
//的Package
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
//处理一些特殊的广播,包括UID_REMOVED,PACKAGE_REMOVED和PACKAGE_ADDED等
finalboolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
intent.getAction());
......//处理特殊的广播,主要和PACKAGE相关,例如接收到PACKAGE_REMOVED广播后,AMS
//需将该Package的组件从相关成员中删除,相关代码可自行阅读
//处理TIME_ZONE变化广播
if(intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction()))
mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
//处理CLEAR_DNS_CACHE广播
if(intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction()))
mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
//处理PROXY_CHANGE广播
if(Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
ProxyProperties proxy = intent.getParcelableExtra("proxy");
mHandler.sendMessage(mHandler.obtainMessage(
UPDATE_HTTP_PROXY,proxy));
}
~~~
从以上代码可知,broadcastIntentLocked第一阶段的工作主要是处理一些特殊的广播消息。
下面来看broadcastIntentLocked第二阶段的工作。
(2) broadcastIntentLocked分析之二
**ActivityManagerService.java::broadcastIntentLocked**
~~~
//处理发送sticky广播的情况
if(sticky) {
......//检查发送进程是否有BROADCAST_STICKY权限
if(requiredPermission != null) {
//在发送Sticky广播的时候,不能携带权限信息
returnBROADCAST_STICKY_CANT_HAVE_PERMISSION;
}
//在发送Stikcy广播的时候,也不能指定特定的接收对象
if(intent.getComponent() != null) ......//抛异常
//将这个Sticky的Intent保存到mStickyBroadcasts中
ArrayList<Intent> list =mStickyBroadcasts.get(intent.getAction());
if (list== null) {
list= new ArrayList<Intent>();
mStickyBroadcasts.put(intent.getAction(), list);
}
......//如果list中已经有该intent,则直接用新的intent替换旧的intent
//否则将该intent加入到list中保存
if (i >= N) list.add(new Intent(intent));
}
//定义两个变量,其中receivers用于保存匹配该Intent的所有广播接收者,包括静态或动态
//注册的广播接收者,registeredReceivers用于保存符合该Intent的所有动态注册者
Listreceivers = null;
List<BroadcastFilter>registeredReceivers = null;
try {
if(intent.getComponent() != null) {
......//如果指定了接收者,则从PKMS中查询它的信息
}else {
//FLAG_RECEIVER_REGISTERED_ONLY标签表明该广播只能发给动态注册者
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)== 0) {
//如果没有设置前面的标签,则需要查询PKMS,获得那些在AndroidManifest.xml
//中声明的广播接收者,即静态广播接收者的信息,并保存到receivers中
receivers =
AppGlobals.getPackageManager().queryIntentReceivers(
intent, resolvedType,STOCK_PM_FLAGS);
}
//再从AMS的mReceiverResolver中查询符合条件的动态广播接收者
registeredReceivers =mReceiverResolver.queryIntent(intent,
resolvedType, false);
}
}......
/*
判断该广播是否设置了REPLACE_PENDING标签。如果设置了该标签,并且之前的那个Intent还
没有被处理,则可以用新的Intent替换旧的Intent。这么做的目的是为了减少不必要的广播发送,
但笔者感觉,这个标签的作用并不靠谱,因为只有旧的Intent没被处理的时候,它才能被替换。
因为旧Intent被处理的时间不能确定,所以不能保证广播发送者的一番好意能够实现。因此,
在发送广播时,千万不要以为设置了该标志就一定能节约不必要的广播发送。
*/
final boolean replacePending =
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
//先处理动态注册的接收者
int NR =registeredReceivers != null ? registeredReceivers.size() : 0;
//如果此次广播为非串行化发送,并且符合条件的动态注册接收者个数不为零
if(!ordered && NR > 0) {
//创建一个BroadcastRecord对象即可,注意,一个BroadcastRecord对象可包括所有的
//接收者(可参考图6-19)
BroadcastRecord r = new BroadcastRecord(intent, callerApp,
callerPackage, callingPid, callingUid, requiredPermission,
registeredReceivers, resultTo, resultCode, resultData, map,
ordered, sticky, false);
boolean replaced = false;
if (replacePending) {
......//从mParalledBroadcasts中查找是否有旧的Intent,如果有就替代它,并设置
//replaced为true
}
if(!replaced) {//如果没有被替换,则保存到mParallelBroadcasts中
mParallelBroadcasts.add(r);
scheduleBroadcastsLocked();//调度一次广播发送
}
//至此,动态注册的广播接收者已处理完毕,设置registeredReceivers为null
registeredReceivers = null;//
NR =0;
}
~~~
broadcastIntentLocked第二阶段的工作有两项:
- 查询满足条件的动态广播接收者及静态广播接收者。
- 当本次广播不为ordered时,需要尽快发送该广播。另外,非ordered的广播都被AMS保存在mParallelBroadcasts中。
(3) broadcastIntentLocked分析之三
下面来看broadcastIntentLocked最后一阶段的工作,其代码如下:
**ActivityManagerService.java::broadcastIntentLocked**
~~~
int ir = 0;
if(receivers != null) {
StringskipPackages[] = null;
......//处理PACKAGE_ADDED的Intent,系统不希望有些应用程序一安装就启动。
//这类程序的工作原理是什么呢?即在该程序内部监听PACKAGE_ADDED广播。如果系统
//没有这一招防备,则PKMS安装完程序后所发送的PAKCAGE_ADDED消息将触发该应用的启动
......//处理ACTION_EXTERNAL_APPLICATIONS_AVAILABLE广播
......//将动态注册的接收者registeredReceivers的元素合并到receivers中去
//处理完毕后,所有的接收者(无论动态还是静态注册的)都存储到receivers变量中了
if((receivers != null && receivers.size() > 0) || resultTo != null) {
//创建一个BroadcastRecord对象,注意它的receivers中包括所有的接收者
BroadcastRecord r = new BroadcastRecord(intent, callerApp,
callerPackage, callingPid, callingUid, requiredPermission,
receivers, resultTo, resultCode, resultData, map, ordered,
sticky, false);
booleanreplaced = false;
if (replacePending) {
......//替换mOrderedBroadcasts中旧的Intent
}//
if(!replaced) {//如果没有替换,则添加该条广播记录到mOrderedBroadcasts中
mOrderedBroadcasts.add(r);
scheduleBroadcastsLocked();//调度AMS进行广播发送工作
}
}
returnBROADCAST_SUCCESS;
}
~~~
由以上代码可知,AMS将动态注册者和静态注册者都合并到receivers中去了。注意,如果本次广播不是ordered,那么表明动态注册者就已经在第二阶段工作中被处理了。因此在合并时,将不会有动态注册者被加到receivers中。最终所创建的广播记录存储在mOrderedBroadcasts中,也就是说,不管是否串行化发送,静态接收者对应的广播记录都将保存在mOrderedBroadcasts中。
为什么不将它们保存在mParallelBroadcasts中呢?
结合代码会发现,保存在mParallelBroadcasts中的BroadcastRecord所包含的都是动态注册的广播接收者信息,这是因为动态接收者所在的进程是已经存在的(如果该进程不存在,如何去注册动态接收者呢?),而静态广播接收者就不能保证它已经和一个进程绑定在一起了(静态广播接收者此时可能还仅仅是在AndroidManifest.xml中声明的一个信息,相应的进程并未创建和启动)。根据前一节所分析的Activity启动流程,AMS还需要进行创建应用进程,初始化Android运行环境等一系列复杂的操作。读到后面内容时会发现,AMS将在一个循环中逐条处理mParallelBroadcasts中的成员(即派发给接收者)。如果将静态广播接收者也保存到mParallelBroadcasts中,会有什么后果呢?假设这些静态接收者所对应的进程全部未创建和启动,那么AMS将在那个循环中创建多个进程!结果让人震惊,系统压力一下就上去了。所以,对于静态注册者,它们对应的广播记录都被放到mOrderedBroadcasts中保存。AMS在处理这类广播信息时,一个进程一个进程地处理,只有处理完一个接收者,才继续下一个接收者。这种做法的好处是,避免了惊群效应的出现,坏处则是延时较长。
下面进入AMS的BROADCAST_INTENT_MSG消息处理函数,看看情况是否如上所说。
- 前言
- 第1章 搭建Android源码工作环境
- 1.1 Android系统架构
- 1.2 搭建开发环境
- 1.2.1 下载源码
- 1.2.2 编译源码
- 1.2.3 利用Eclipse调试system_process
- 1.3 本章小结
- 第2章 深入理解Java Binder和MessageQueue
- 2.1 概述
- 2.2 Java层中的Binder架构分析
- 2.2.1 Binder架构总览
- 2.2.2 初始化Java层Binder框架
- 2.2.3 addService实例分析
- 2.2.4 Java层Binder架构总结
- 2.3 心系两界的MessageQueue
- 2.3.1 MessageQueue的创建
- 2.3.2 提取消息
- 2.3.3 nativePollOnce函数分析
- 2.3.4 MessageQueue总结
- 2.4 本章小结
- 第3章 深入理解SystemServer
- 3.1 概述
- 3.2 SystemServer分析
- 3.2.1 main函数分析
- 3.2.2 Service群英会
- 3.3 EntropyService分析
- 3.4 DropBoxManagerService分析
- 3.4.1 DBMS构造函数分析
- 3.4.2 dropbox日志文件的添加
- 3.4.3 DBMS和settings数据库
- 3.5 DiskStatsService和DeviceStorageMonitorService分析
- 3.5.1 DiskStatsService分析
- 3.5.2 DeviceStorageManagerService分析
- 3.6 SamplingProfilerService分析
- 3.6.1 SamplingProfilerService构造函数分析
- 3.6.2 SamplingProfilerIntegration分析
- 3.7 ClipboardService分析
- 3.7.1 复制数据到剪贴板
- 3.7.2 从剪切板粘贴数据
- 3.7.3 CBS中的权限管理
- 3.8 本章小结
- 第4章 深入理解PackageManagerService
- 4.1 概述
- 4.2 初识PackageManagerService
- 4.3 PKMS的main函数分析
- 4.3.1 构造函数分析之前期准备工作
- 4.3.2 构造函数分析之扫描Package
- 4.3.3 构造函数分析之扫尾工作
- 4.3.4 PKMS构造函数总结
- 4.4 APK Installation分析
- 4.4.1 adb install分析
- 4.4.2 pm分析
- 4.4.3 installPackageWithVerification函数分析
- 4.4.4 APK 安装流程总结
- 4.4.5 Verification介绍
- 4.5 queryIntentActivities分析
- 4.5.1 Intent及IntentFilter介绍
- 4.5.2 Activity信息的管理
- 4.5.3 Intent 匹配查询分析
- 4.5.4 queryIntentActivities总结
- 4.6 installd及UserManager介绍
- 4.6.1 installd介绍
- 4.6.2 UserManager介绍
- 4.7 本章学习指导
- 4.8 本章小结
- 第5章 深入理解PowerManagerService
- 5.1 概述
- 5.2 初识PowerManagerService
- 5.2.1 PMS构造函数分析
- 5.2.2 init分析
- 5.2.3 systemReady分析
- 5.2.4 BootComplete处理
- 5.2.5 初识PowerManagerService总结
- 5.3 PMS WakeLock分析
- 5.3.1 WakeLock客户端分析
- 5.3.2 PMS acquireWakeLock分析
- 5.3.3 Power类及LightService类介绍
- 5.3.4 WakeLock总结
- 5.4 userActivity及Power按键处理分析
- 5.4.1 userActivity分析
- 5.4.2 Power按键处理分析
- 5.5 BatteryService及BatteryStatsService分析
- 5.5.1 BatteryService分析
- 5.5.2 BatteryStatsService分析
- 5.5.3 BatteryService及BatteryStatsService总结
- 5.6 本章学习指导
- 5.7 本章小结
- 第6章 深入理解ActivityManagerService
- 6.1 概述
- 6.2 初识ActivityManagerService
- 6.2.1 ActivityManagerService的main函数分析
- 6.2.2 AMS的 setSystemProcess分析
- 6.2.3 AMS的 installSystemProviders函数分析
- 6.2.4 AMS的 systemReady分析
- 6.2.5 初识ActivityManagerService总结
- 6.3 startActivity分析
- 6.3.1 从am说起
- 6.3.2 AMS的startActivityAndWait函数分析
- 6.3.3 startActivityLocked分析
- 6.4 Broadcast和BroadcastReceiver分析
- 6.4.1 registerReceiver流程分析
- 6.4.2 sendBroadcast流程分析
- 6.4.3 BROADCAST_INTENT_MSG消息处理函数
- 6.4.4 应用进程处理广播分析
- 6.4.5 广播处理总结
- 6.5 startService之按图索骥
- 6.5.1 Service知识介绍
- 6.5.2 startService流程图
- 6.6 AMS中的进程管理
- 6.6.1 Linux进程管理介绍
- 6.6.2 关于Android中的进程管理的介绍
- 6.6.3 AMS进程管理函数分析
- 6.6.4 AMS进程管理总结
- 6.7 App的 Crash处理
- 6.7.1 应用进程的Crash处理
- 6.7.2 AMS的handleApplicationCrash分析
- 6.7.3 AppDeathRecipient binderDied分析
- 6.7.4 App的Crash处理总结
- 6.8 本章学习指导
- 6.9 本章小结
- 第7章 深入理解ContentProvider
- 7.1 概述
- 7.2 MediaProvider的启动及创建
- 7.2.1 Context的getContentResolver函数分析
- 7.2.2 MediaStore.Image.Media的query函数分析
- 7.2.3 MediaProvider的启动及创建总结
- 7.3 SQLite创建数据库分析
- 7.3.1 SQLite及SQLiteDatabase家族
- 7.3.2 MediaProvider创建数据库分析
- 7.3.3 SQLiteDatabase创建数据库的分析总结
- 7.4 Cursor 的query函数的实现分析
- 7.4.1 提取query关键点
- 7.4.2 MediaProvider 的query分析
- 7.4.3 query关键点分析
- 7.4.4 Cursor query实现分析总结
- 7.5 Cursor close函数实现分析
- 7.5.1 客户端close的分析
- 7.5.2 服务端close的分析
- 7.5.3 finalize函数分析
- 7.5.4 Cursor close函数总结
- 7.6 ContentResolver openAssetFileDescriptor函数分析
- 7.6.1 openAssetFileDescriptor之客户端调用分析
- 7.6.2 ContentProvider的 openTypedAssetFile函数分析
- 7.6.3 跨进程传递文件描述符的探讨
- 7.6.4 openAssetFileDescriptor函数分析总结
- 7.7 本章学习指导
- 7.8 本章小结
- 第8章 深入理解ContentService和AccountManagerService
- 8.1 概述
- 8.2 数据更新通知机制分析
- 8.2.1 初识ContentService
- 8.2.2 ContentResovler 的registerContentObserver分析
- 8.2.3 ContentResolver的 notifyChange分析
- 8.2.4 数据更新通知机制总结和深入探讨
- 8.3 AccountManagerService分析
- 8.3.1 初识AccountManagerService
- 8.3.2 AccountManager addAccount分析
- 8.3.3 AccountManagerService的分析总结
- 8.4 数据同步管理SyncManager分析
- 8.4.1 初识SyncManager
- 8.4.2 ContentResolver 的requestSync分析
- 8.4.3 数据同步管理SyncManager分析总结
- 8.5 本章学习指导
- 8.6 本章小结