在上篇文章中,介绍了InputDispatcher Timeout的流程。本篇文章将介绍Broadcast Timeout的流程。 我们知道广播根据注册的方式的可以分为静态注册广播和动态注册广播,根据发送方式可以分为普通广播、有序广播、Sticky广播以及APP内广播。广播执行的方式有两种,一种是串行执行,另外一种是并发执行。并发执行的广播是不存在超时的情况,例如动态注册的非有序的广播。而串行执行的广播是有超时时间的,前台广播是10s,后台广播是60s。可以通过设置Intent.FLAG_RECEIVER_FOREGROUND标志位,将广播设置为前台广播,默认情况下,广播都是后台广播。静态注册的和有序的广播都是串行执行的。
Broadcast Timeout的整体流程如下图所示:
1.sendBroadcast方法(ContextImpl.java)
广播的发送是通过context.sendBroadcast()方法来实现的,Context类是一个抽象的类,具体的由ContextImpl类来实现。
framework/core/java/android/app/ContextImpl.java
/*
* 发送广播
*/
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess(this);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
2.broadcastIntent方法(ActivityManagerService.java)
frameworks/base/core/java/com/android/server/am/ActivityManagerService.java
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, int appOp, Bundle bOptions,
boolean serialized, boolean sticky, int userId) {
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
//验证广播intent是否有效
intent = verifyBroadcastLocked(intent);
//获取调用者进程记录对象
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
在broadcastIntent方法中有两个布尔值参数serialized和sticky来共同决定是普通广播,有序广播还是sticky广播,参数如下:
类型 | serialized | sticky |
sendBroadcast | false | false |
sendOrderedBroadcast | true | false |
sendStickyBroadcast | false | true |
3.broadcastIntentLocked方法(ActivityManagerService.java)
final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
intent = new Intent(intent);
// 增加该标志,则广播不会发送到已停止的package
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
// 当没有启动完成,不允许启动新的进程
if (!mProcesse