Broadcast组件研究
Broadcast组件研究注册简介广播分为三种:普通广播:这种广播可以依次传递给各个处理器去处理有序广播:这种广播在处理器端的处理顺序是按照处理器的不同优先级来区分的,高优先级的处理器会优先截获这个消息,并且可以将这个消息删除粘性广播:粘性消息在发送后就一直存在于系统的消息容器里面,等待对应的处理器去处理,如果暂时没有处理器处理这个消息则一直在消息容器里面处于等待状态,粘性广播的Rece
Broadcast组件研究
注册
简介
广播分为三种:
普通广播:这种广播可以依次传递给各个处理器去处理
有序广播:这种广播在处理器端的处理顺序是按照处理器的不同优先级来区分的,高优先级的处理器会优先截获这个消息,并且可以将这个消息删除
粘性广播:粘性消息在发送后就一直存在于系统的消息容器里面,等待对应的处理器去处理,如果暂时没有处理器处理这个消息则一直在消息容器里面处于等待状态,粘性广播的Receiver如果被销毁,那么下次重建时会自动接收到消息数据
粘性广播补充说明:
- 所有的注册者随时随地都能收到。(随时的意思是从他发出开始直到他的下次更新为止这段时间内所有注册该广播的都能收到)
- 这条广播会更新,而且一直会维持最新的广播发送给接受者
IntentFilter相关说明
IntentFilter中具有和Intent对应的用于过滤Action,Data和Category的字段,一个隐式Intent要想被一个组件处理,必须通过这三个环节的检查。
- 检查 Action 尽管一个Intent只可以设置一个Action,但一个Intentfilter可以持有一个或多个Action用于过滤,到达的Intent只需要匹配其中一个Action即可。 深入思考: 如果一个Intentfilter没有设置Action的值,那么,任何一个Intent都不会被通过;反之,如果一个Intent对象没有设置Action值,那么它能通过所有的Intentfilter的Action检查 。
- 检查 Data 同Action一样,Intentfilter中的Data部分也可以是一个或者多个,而且可以没有。每个Data包含的内容为URL和数据类型,进行Data检查时主要也是对这两点进行比较,比较规则: 如果一个Intent对象没有设置Data,只有Intentfilter也没有设置Data时才可通过检查。 如果一个Intent对象包含URI,但不包含数据类型:仅当Intentfilter也不指定数据类型,同时它们的URI匹配,才能通过检测。 如果一个Intent对象包含数据类型,但不包含URI:仅当Intentfilter也没指定URL,而只包含数据类型且与Intent相同,才通过检测。 如果一个Intent对象既包含URI,也包含数据类型(或数据类型能够从URI推断出),只有当其数据类型匹配Intentfilter中的数据类型,并且通过了URL检查时,该Intent对象才能通过检查。
其中URL由四部分组成:它有四个属性scheme、host、port、path对应于URI的每个部分。 - 检查 Category Intentfilter中可以设置多个Category,Intent中也可以含有多个Category,只有Intent中的所有Category都能匹配到Intentfilter中的Category,Intent才能通过检查。也就是说,如果Intent中的Category集合是Intentfilter中Category的集合的子集时,Intent才能通过检查。如果Intent中没有设置Category,则它能通过所有Intentfilter的Category检查。 如果一个Intent能够通过不止一个组件的Intentfilter,用户可能会被问那个组件被激活。如果没有目标找到,会产生一个异常。
其他: registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)
- 如果需要另开线程做receiver的事情,需要指定scheduler。否则会在主线程做receiver
- 参数三指定一个广播权限,只有拥有该权限的broadcaster才能发广播给receiver
sendOrderedBroadcast(Intent intent, String receiverPermission)参数二即为发送广播权限
//新开线程接收广播范例
HandlerThread handlerThread = new HandlerThread("ht");
handlerThread.start();
Looper looper = handlerThread.getLooper();
Handler handler = new Handler(looper);
context.registerReceiver(receiver, filter, null, handler); // Will not run on main thread
//添加广播权限范例
//sender方
Intent broadcast = new Intent(this, MyBroadcastReceiver.class);
sendBroadcast(broadcast, "andro.jf.mypermission");
//Manifest增加权限
<permission android:name="andro.jf.mypermission"
android:label="my_permission"
android:protectionLevel="dangerous"></permission>
//receiver方
//增加权限
<uses-permission android:name="andro.jf.mypermission"/>
//receiver权限
<receiver android:name="MyBroadcastReceiver" android:exported="true" />
//registerReceiver中不用多说
ReceiverDispatcher: 封装用户自定义的receiver对象。内部类InnerReceiver为binder对象,用于与AMS的传递与通信。
ReceiverList: 继承自ArrayList,存放了Receiver的binder对象以及其注册的BroadcastFilter列表。AMS中的mRegisteredReceivers为一个hashmap,key为receiver的binder对象。ProcessRecord的receivers中也记录了其内部的receiver对象。
BroadcastFilter: 封装了IntentFilter,增加了注册Broadcast时的来源信息。
IntentResolver: 解析Intent,在addFilter时即进行解析。其内部有mSchemeToFilter,mActionToFilter,mTypedActionToFilter三个map对象。key为对应的action(scheme或者type),value为Filter。
BroadcastRecord: 将intent封装成BroadcastRecord,交给BroadcastQueue进行处理。
BroadcastQueue: BroadcastQueue为Broadcast处理队列,分为Fg和Bg,FgBroadcastQueue会有更高的权限,被优先处理。
流程
发送
简介
流程
BroadcastQueue分发广播消息流程
处理并行广播
final void processNextBroadcast(boolean fromMsg) {
synchronized(mService) {
BroadcastRecord r;
mService.updateCpuStats();if (fromMsg) { mBroadcastsScheduled = false; } //对于并行广播,直接转发 while (mParallelBroadcasts.size() > 0) { r = mParallelBroadcasts.remove(0); r.dispatchTime = SystemClock.uptimeMillis(); r.dispatchClockTime = System.currentTimeMillis(); final int N = r.receivers.size(); for (int i=0; i<N; i++) { Object target = r.receivers.get(i); //处理 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false); } addBroadcastToHistoryLocked(r); }
从有序队列选取需要处理的BroadcastRecord
//处理挂起的广播
boolean isDead;
synchronized (mService.mPidsSelfLocked) {
ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
isDead = proc == null || proc.crashing;
}
if (!isDead) {
//如果该进程还活着,可能出于启动过程中,继续等待
return;
} else {
//该进程没起得来,标记该broadcast为IDLE
//不在优先处理该广播
mPendingBroadcast.state = BroadcastRecord.IDLE;
mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
}
}
选取下一个要处理的broadcast
boolean looped = false;
do {
// 如果队列为空,说明处理完毕,直接返回
if (mOrderedBroadcasts.size() == 0) {
mService.scheduleAppGcsLocked();
if (looped) {
mService.updateOomAdjLocked();
}
return;
}
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))) {
// 超时处理
broadcastTimeoutLocked(false); // forcibly finish this broadcast
// 强行认为已接收
forceReceive = true;
r.state = BroadcastRecord.IDLE;
}
}
//对于有序广播,只有上层调用了finishReceiver,才能进行后续的广播
//finishReceiver会将state设为IDLE,不为IDLE代表该广播尚未处理完毕
if (r.state != BroadcastRecord.IDLE) {
return;
}
// broadcast中的所有receiver都已经处理完毕,发送result
if (r.receivers == null || r.nextReceiver >= numReceivers
|| r.resultAbort || forceReceive) {
if (r.resultTo != null) {
try {
// 如果需要返回result,进行相关处理
performReceiveLocked(r.callerApp, r.resultTo,
new Intent(r.intent), r.resultCode,
r.resultData, r.resultExtras, false, false, r.userId);
r.resultTo = null;
} catch (RemoteException e) {
r.resultTo = null;
}
}
//取消之前预设的Timeout消息
cancelBroadcastTimeoutLocked();
//该broadcast不合要求,remove
addBroadcastToHistoryLocked(r);
mOrderedBroadcasts.remove(0);
r = null;
looped = true;
continue;
}
} while (r == null);
//准备处理该广播,先发送定时超时信息
if (! mPendingBroadcastTimeoutMessage) {
long timeoutTime = r.receiverTime + mTimeoutPeriod;
setBroadcastTimeoutLocked(timeoutTime);
}
Object nextReceiver = r.receivers.get(recIdx);
// 获取下一个需要处理的receiver,如果是动态广播
if (nextReceiver instanceof BroadcastFilter) {
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
//进一步将该广播传递下去
deliverToRegisteredReceiverLocked(r, filter, r.ordered);
if (r.receiver == null || !r.ordered) {
//如果不是有序广播或者receiver已经全部处理完
//接着处理下一个广播
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
}
return;
}
//此为静态广播
ResolveInfo info =
(ResolveInfo)nextReceiver;
ComponentName component = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
boolean skip = false;
int perm = mService.checkComponentPermission(info.activityInfo.permission,
r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
info.activityInfo.exported);
//判断权限
if (perm != PackageManager.PERMISSION_GRANTED) {
......
// 跳过该广播
skip = true;
}
if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
r.requiredPermission != null) {
......
//跳过
}
// 未启用OPS,略过
if (r.appOp != AppOpsManager.OP_NONE) {
......
}
......
//一系列判断是否需要跳过的broadcast
// 需要跳过的broadcast,重新调度处理其他broadcast
if (skip) {
r.receiver = null;
r.curFilter = null;
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
return;
}
// 开始处理静态广播
r.state = BroadcastRecord.APP_RECEIVE;
String targetProcess = info.activityInfo.processName;
r.curComponent = component;
final int receiverUid = info.activityInfo.applicationInfo.uid;
if (r.callingUid != Process.SYSTEM_UID && isSingleton
&& mService.isValidSingletonCall(r.callingUid, receiverUid)) {
info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0);
}
r.curReceiver = info.activityInfo;
//执行过程中的package不允许被stop
try {
AppGlobals.getPackageManager().setPackageStoppedState(
r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
}
// Is this receiver's application already running?
ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
info.activityInfo.applicationInfo.uid, false);
// 判断该app是否在运行,如果已在运行
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) {
} catch (RuntimeException e) {
//有异常,finishReceiver
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
//重新调度
scheduleBroadcastsLocked();
r.state = BroadcastRecord.IDLE;
return;
}
//启动app
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) {
//启动app失败
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
//重新调度
scheduleBroadcastsLocked();
r.state = BroadcastRecord.IDLE;
return;
}
// 由于等待新启动的app处理广播消息,该广播被置为pendingBroadcast
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;
}
重新调度scheduleBroadcastsLocked
//只能调度一次 if (mBroadcastsScheduled) { return; } //通过Handler,调用processNextBroadcast mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this)); mBroadcastsScheduled = true;
处理超时信息 broadcastTimeoutLocked
if (fromMsg) { // 代表handle中是否有timeout message // 如果有的话,置为false,代表timeout message已经被处理 mPendingBroadcastTimeoutMessage = false; } long now = SystemClock.uptimeMillis(); BroadcastRecord r = mOrderedBroadcasts.get(0); // 是否从时限消息处理函数过来 if (fromMsg) { if (mService.mDidDexOpt) { // Delay timeouts until dexopt finishes. // 等待dexopt结束,重设超时信息 mService.mDidDexOpt = false; long timeoutTime = SystemClock.uptimeMillis() + mTimeoutPeriod; setBroadcastTimeoutLocked(timeoutTime); return; } if (!mService.mProcessesReady) { //系统尚未启动好 return; } long timeoutTime = r.receiverTime + mTimeoutPeriod; if (timeoutTime > now) { //过早的超时广播,重设 setBroadcastTimeoutLocked(timeoutTime); return; } BroadcastRecord br = mOrderedBroadcasts.get(0); // 该broadcast还在等待service结束,但是已经等了很久,因此结束整个过程,跳到下一个广播 if (br.state == BroadcastRecord.WAITING_SERVICES) { br.curComponent = null; br.state = BroadcastRecord.IDLE; // 跳转到下一个广播的执行 // processNextBroadcast的仍然是当前的广播, // 由于state发生变化,不会再进该处。 // 会放弃该广播,并处理下一个广播,然后返回 processNextBroadcast(false); return; } r.receiverTime = now; r.anrCount++; // Current receiver has passed its expiration date. if (r.nextReceiver <= 0) { Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0"); return; } ProcessRecord app = null; String anrMessage = null; // 找到当前receiver对应的app,弹窗提示 Object curReceiver = r.receivers.get(r.nextReceiver-1); Slog.w(TAG, "Receiver during timeout: " + curReceiver); logBroadcastReceiverDiscardLocked(r); if (curReceiver instanceof BroadcastFilter) { BroadcastFilter bf = (BroadcastFilter)curReceiver; if (bf.receiverList.pid != 0 && bf.receiverList.pid != ActivityManagerService.MY_PID) { synchronized (mService.mPidsSelfLocked) { app = mService.mPidsSelfLocked.get( bf.receiverList.pid); } } } else { app = r.curApp; } if (app != null) { anrMessage = "Broadcast of " + r.intent.toString(); } // 如果挂起的broadcast即为该broadcast,直接清空 if (mPendingBroadcast == r) { mPendingBroadcast = null; } // 结束并且重新调度下一个receiver finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false); scheduleBroadcastsLocked(); if (anrMessage != null) { // 弹出对话框提示ANR mHandler.post(new AppNotResponding(app, anrMessage)); }
正常处理动态广播 deliverToRegisteredReceiverLocked
//双向检查权限,如果权限不够,skip 为 true if (!skip) { // 以下设置为跟踪有序广播,非有序广播则不做设置 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) { r.curApp = filter.receiverList.app; filter.receiverList.app.curReceiver = r; mService.updateOomAdjLocked(r.curApp); } } try { // 处理广播信息的函数 performReceiveLocked(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; } }
performReceiveLocked:
//application自己处理广播信息, if (app != null) { if (app.thread != null) { app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser, app.repProcState); } else { throw new RemoteException("app.thread must not be null"); } } else { receiver.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); }
- 正常处理静态广播 processCurBroadcastLocked
该函数与deliverToRegisteredReceiverLocked类似,只是由于是静态广播,app未必已经启动,因此多了 ensure dexopt完成,和 receiver class的load工作。
由广播唤醒的app,处理广播信息
启动app后有一步为,调用ActivityManagerService attachApplicationLocked函数// 判断当前启动app是否为pending的broadcast的receiver if (!badApp && isPendingBroadcastProcessLocked(pid)) { try { // 如果是,发送pending的broadcast didSomething |= sendPendingBroadcastsLocked(app); } catch (Exception e) { badApp = true; } }
执行完广播会调用finish函数,通知AMS广播执行完毕,在AMS的finishReceiverLocked函数中会根据broadcast的state判断是否继续处理广播消息,有序广播的state为CALL_DONE_RECEIVE,返回值为true,执行processNextBroadcast,从而完成一个循环的有序广播处理流程。
更多推荐
所有评论(0)