赞
踩
广播作为Android四大组件之一,是Android进程间通信或者进程内通信的一种方式。
广播一般分为标准广播、有序广播和粘性广播。
PS:粘性广播 API 存在许多与安全性相关的缺点,因此它在 Android 5.0(API 级别 21)中已废弃。所以下文不对粘性广播做分析。
标准广播是最常用的广播类型,它是无序的,一旦广播发送,接收端不分先后顺序接收到广播,该类型广播不可被拦截。
我们发广播最常用的是调用contxt.sendBroadcast(intent)发送一个标准广播,context是Context对象,最终实现类是ContextImpl
- public void sendBroadcast(Intent intent) {
- ...
- try {
- //做一些离开进程的准备工作
- intent.prepareToLeaveProcess(this);
- //跨进程调用AMS的broadcastIntentWithFeature函数继续发送广播流程
- ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
- null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/,
- null, AppOpsManager.OP_NONE, null, false, false, getUserId());
- }
- }
做一些权限检查,调用broadcastIntentLockedTraced继续发送广播流程
- public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
- Intent intent, String resolvedType, IIntentReceiver resultTo,
- int resultCode, String resultData, Bundle resultExtras,
- String[] requiredPermissions, String[] excludedPermissions,
- String[] excludedPackages, int appOp, Bundle bOptions,
- boolean serialized, boolean sticky, int userId) {
- //检测是否属于被隔离的对象
- enforceNotIsolatedCaller("broadcastIntent");
- synchronized(this) {
- ...
-
- //确保只有系统可以发送alarm类型的广播;如果是交互类型的广播,则必须有android.Manifest.permission.BROADCAST_OPTION_INTERACTIVE权限
- enforceBroadcastOptionPermissionsInternal(bOptions, callingUid);
-
- try {
- //调用broadcastIntentLocked继续发送广播流程
- return broadcastIntentLocked(callerApp,
- callerApp != null ? callerApp.info.packageName : null, callingFeatureId,
- intent, resolvedType, resultToApp, resultTo, resultCode, resultData,
- resultExtras, requiredPermissions, excludedPermissions, excludedPackages,
- appOp, bOptions, serialized, sticky, callingPid, callingUid, callingUid,
- callingPid, userId, BackgroundStartPrivileges.NONE, null, null);
- }
- }
- }
-
- final int broadcastIntentLocked(ProcessRecord callerApp,
- String callerPackage, String callerFeatureId, Intent intent, String resolvedType,
- IIntentReceiver resultTo, int resultCode, String resultData,
- Bundle resultExtras, String[] requiredPermissions, String[] excludedPermissions,
- String[] excludedPackages, int appOp, Bundle bOptions, boolean ordered,
- boolean sticky, int callingPid,
- int callingUid, int realCallingUid, int realCallingPid, int userId) {
- return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent,
- resolvedType, null, resultTo, resultCode, resultData, resultExtras,
- requiredPermissions, excludedPermissions, excludedPackages, appOp, bOptions,
- ordered, sticky, callingPid, callingUid, realCallingUid, realCallingPid, userId,
- BackgroundStartPrivileges.NONE,
- null /* broadcastAllowList */, null /* filterExtrasForReceiver */);
- }
-
- @GuardedBy("this")
- final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,
- @Nullable String callerFeatureId, Intent intent, String resolvedType,
- ProcessRecord resultToApp, IIntentReceiver resultTo, int resultCode, String resultData,
- Bundle resultExtras, String[] requiredPermissions,
- String[] excludedPermissions, String[] excludedPackages, int appOp, Bundle bOptions,
- boolean ordered, boolean sticky, int callingPid, int callingUid,
- int realCallingUid, int realCallingPid, int userId,
- BackgroundStartPrivileges backgroundStartPrivileges,
- @Nullable int[] broadcastAllowList,
- @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) {
- final int cookie = BroadcastQueue.traceBegin("broadcastIntentLockedTraced");
- final int res = broadcastIntentLockedTraced(callerApp, callerPackage, callerFeatureId,
- intent, resolvedType, resultToApp, resultTo, resultCode, resultData, resultExtras,
- requiredPermissions, excludedPermissions, excludedPackages, appOp,
- BroadcastOptions.fromBundleNullable(bOptions), ordered, sticky,
- callingPid, callingUid, realCallingUid, realCallingPid, userId,
- backgroundStartPrivileges, broadcastAllowList, filterExtrasForReceiver);
- BroadcastQueue.traceEnd(cookie);
- return res;
- }

此函数代码较多,主要做以下几个事情
1. 判断是否是系统广播,不同的系统广播做不同的处理
2. 粘性广播的处理
3. 发送动态注册的无序广播列表
4. 合并动态注册的有序广播列表和静态注册的广播列表,并发送
- final int broadcastIntentLockedTraced(ProcessRecord callerApp, String callerPackage,
- @Nullable String callerFeatureId, Intent intent, String resolvedType,
- ProcessRecord resultToApp, IIntentReceiver resultTo, int resultCode, String resultData,
- Bundle resultExtras, String[] requiredPermissions,
- String[] excludedPermissions, String[] excludedPackages, int appOp,
- BroadcastOptions brOptions, boolean ordered, boolean sticky, int callingPid,
- int callingUid, int realCallingUid, int realCallingPid, int userId,
- BackgroundStartPrivileges backgroundStartPrivileges,
- @Nullable int[] broadcastAllowList,
- @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) {
- // Ensure all internal loopers are registered for idle checks
- BroadcastLoopers.addMyLooper();
-
- ...
- final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
- // Instant Apps cannot use FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS
- // 所有的instant应用,都不能使用FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS这个flag
- if (callerInstantApp) {
- intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
- }
- ...
- // By default broadcasts do not go to stopped apps.
- // 默认情况下,广播不会发送到已经停止的应用
- intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
-
- // If we have not finished booting, don't allow this to launch new processes.
- //如果系统还没启动完成,不允许启动新的进程
- if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- }
-
- ...
- // Make sure that the user who is receiving this broadcast or its parent is running.
- // If not, we will just skip it. Make an exception for shutdown broadcasts, upgrade steps.
- // 确保将要接收此广播的用户正在运行
- if (userId != UserHandle.USER_ALL && !mUserController.isUserOrItsParentRunning(userId)) {
- if ((callingUid != SYSTEM_UID
- || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
- && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
- Slog.w(TAG, "Skipping broadcast of " + intent
- + ": user " + userId + " and its parent (if any) are stopped");
- scheduleCanceledResultTo(resultToApp, resultTo, intent, userId,
- brOptions, callingUid, callerPackage);
- return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
- }
- }
-
- final String action = intent.getAction();
- if (brOptions != null) {
- ...
- // 不允许发送广播给受限的应用
- if (brOptions.isDontSendToRestrictedApps()
- && !isUidActiveLOSP(callingUid)
- && isBackgroundRestrictedNoCheck(callingUid, callerPackage)) {
- return ActivityManager.START_CANCELED;
- }
- // 如果是允许后台活动启动的广播,判断是否有START_ACTIVITIES_FROM_BACKGROUND权限
- if (brOptions.allowsBackgroundActivityStarts()) {
- if (checkComponentPermission(
- android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
- realCallingPid, realCallingUid, -1, true)
- != PackageManager.PERMISSION_GRANTED) {
- String msg = "Permission Denial: " + intent.getAction()
- + " broadcast from " + callerPackage + " (pid=" + callingPid
- + ", uid=" + callingUid + ")"
- + " requires "
- + android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- } else {
- // We set the token to null since if it wasn't for it we'd allow anyway here
- backgroundStartPrivileges = BackgroundStartPrivileges.ALLOW_BAL;
- }
- }
- ...
- }
-
- // Verify that protected broadcasts are only being sent by system code,
- // and that system code is only sending protected broadcasts.
- // 受保护的广播只能由系统发送且系统也只能发送受保护的广播
- final boolean isProtectedBroadcast;
- try {
- isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
- }
-
- final boolean isCallerSystem;
- switch (UserHandle.getAppId(callingUid)) {
- case ROOT_UID:
- case SYSTEM_UID:
- case PHONE_UID:
- case BLUETOOTH_UID:
- case NFC_UID:
- case SE_UID:
- case NETWORK_STACK_UID:
- isCallerSystem = true;
- break;
- default:
- isCallerSystem = (callerApp != null) && callerApp.isPersistent();
- break;
- }
-
- // 非系统
- if (!isCallerSystem) {
- // 受保护广播,直接抛异常
- if (isProtectedBroadcast) {
- ...
- throw new SecurityException(msg);
- // 如果是更新widget相关广播,则必须显式的指明包名且包名只能是该应用本身
- } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
- || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
- ...
- if (callerPackage == null) {
- ...
- throw new SecurityException(msg);
- } else if (intent.getComponent() != null) {
- if (!intent.getComponent().getPackageName().equals(
- callerPackage)) {
- ...
- throw new SecurityException(msg);
- }
- } else {
- // Limit broadcast to their own package.
- intent.setPackage(callerPackage);
- }
- }
- }
-
- boolean timeoutExempt = false;
-
- if (action != null) {
- // 后台启动广播,必须有FLAG_RECEIVER_INCLUDE_BACKGROUND flag
- if (getBackgroundLaunchBroadcasts().contains(action)) {
- intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
- }
-
- // 处理一些系统广播
- switch (action) {
- case Intent.ACTION_MEDIA_SCANNER_SCAN_FILE:
- ...
- break;
- case Intent.ACTION_UID_REMOVED:
- case Intent.ACTION_PACKAGE_REMOVED:
- case Intent.ACTION_PACKAGE_CHANGED:
- case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
- case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
- case Intent.ACTION_PACKAGES_SUSPENDED:
- case Intent.ACTION_PACKAGES_UNSUSPENDED:
- ...
- break;
- case Intent.ACTION_PACKAGE_REPLACED:
- {
- ...
- break;
- }
- case Intent.ACTION_PACKAGE_ADDED:
- {
- ...
- break;
- }
- case Intent.ACTION_PACKAGE_DATA_CLEARED:
- {
- ...
- break;
- }
- case Intent.ACTION_TIMEZONE_CHANGED:
- ...
- break;
- case Intent.ACTION_TIME_CHANGED:
- ...
- break;
- case ConnectivityManager.ACTION_CLEAR_DNS_CACHE:
- ...
- break;
- case Proxy.PROXY_CHANGE_ACTION:
- ...
- break;
- case android.hardware.Camera.ACTION_NEW_PICTURE:
- case android.hardware.Camera.ACTION_NEW_VIDEO:
- ...
- break;
- case android.security.KeyChain.ACTION_TRUST_STORE_CHANGED:
- ...
- break;
- case "com.android.launcher.action.INSTALL_SHORTCUT":
- ...
- return ActivityManager.BROADCAST_SUCCESS;
- case Intent.ACTION_PRE_BOOT_COMPLETED:
- ...
- break;
- case Intent.ACTION_CLOSE_SYSTEM_DIALOGS:
- ...
- break;
- }
- }
-
- // Add to the sticky list if requested.
- // 粘性广播,不做分析
- if (sticky) {
- ...
- }
-
- ...
- // 用于存储所有静态注册的广播
- List receivers = null;
- // 用于存储所有动态注册的广播
- List<BroadcastFilter> registeredReceivers = null;
- // Need to resolve the intent to interested receivers...
- if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
- // 通过PMS的queryIntentReceivers函数获取系统所有静态注册此广播的应用列表
- receivers = collectReceiverComponents(
- intent, resolvedType, callingUid, users, broadcastAllowList);
- }
- // 如果intent没有指明广播接受者的组件名,说明是发给所有已注册并且需要接收该广播的接收者的
- if (intent.getComponent() == null) {
- ...
- // 通过mReceiverResolver获取动态注册广播。mReceiverResolver是在registerReceiver时更新的。
- registeredReceivers = mReceiverResolver.queryIntent(snapshot, intent,
- resolvedType, false /*defaultOnly*/, userId);
- ...
- }
- ...
-
- // 在给定的广播筛选器列表中筛选出non-exported的组件
- filterNonExportedComponents(intent, callingUid, callingPid, registeredReceivers,
- mPlatformCompat, callerPackage, resolvedType);
- int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
- // 当前发送的是无序广播且存在动态注册的广播接收者
- if (!ordered && NR > 0 && !mEnableModernQueue) {
- // 发送方是系统
- if (isCallerSystem) {
- // 检查广播是否合规
- checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
- isProtectedBroadcast, registeredReceivers);
- }
- // 寻找符合该intent要求的广播队列
- final BroadcastQueue queue = broadcastQueueForIntent(intent);
- // 创建BroadcastRecord对象并将当前所有通过动态注册的广播接收者传进去
- BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
- callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
- requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
- registeredReceivers, resultToApp, resultTo, resultCode, resultData,
- resultExtras, ordered, sticky, false, userId,
- backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
- callerAppProcessState);
- // 发送广播
- queue.enqueueBroadcastLocked(r);
- ...
- }
-
- // Merge into one list.
- int 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 we'd like to deliberately make
- // this decision.
- // 需要跳过的广播接收者
- String skipPackages[] = null;
- // 对于ACTION_PACKAGE_ADDED广播而言,如果是自己被add了,那么这个广播只能别人收到,自己即使注册了这个静态广播也接收不到
- 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; it<NT; it++) {
- ResolveInfo curt = (ResolveInfo)receivers.get(it);
- if (curt.activityInfo.packageName.equals(skipPackage)) {
- receivers.remove(it);
- it--;
- NT--;
- }
- }
- }
- }
- }
-
- int NT = receivers != null ? receivers.size() : 0;
- int it = 0;
- // 静态注册的广播接收者
- ResolveInfo curt = null;
- // 动态注册的广播接收者
- BroadcastFilter curr = null;
- // 静态广播队列不为空
- while (it < NT && ir < NR) {
- if (curt == null) {
- curt = (ResolveInfo)receivers.get(it);
- }
- if (curr == null) {
- curr = registeredReceivers.get(ir);
- }
- // 如果动态注册的广播接收者的优先级大于等于静态注册的广播接收者的优先级
- if (curr.getPriority() >= 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 < NR) {
- if (receivers == null) {
- receivers = new ArrayList();
- }
- receivers.add(registeredReceivers.get(ir));
- ir++;
- }
-
- ...
- // 合并后的列表不为空
- if ((receivers != null && receivers.size() > 0)
- || resultTo != null) {
- // 寻找符合该intent要求的广播队列
- BroadcastQueue queue = broadcastQueueForIntent(intent);
- filterNonExportedComponents(intent, callingUid, callingPid, receivers,
- mPlatformCompat, callerPackage, resolvedType);
- // 创建BroadcastRecord对象并将合并后的列表传进去
- BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
- callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
- requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
- receivers, resultToApp, resultTo, resultCode, resultData, resultExtras,
- ordered, sticky, false, userId,
- backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
- callerAppProcessState);
-
- // 发送广播
- queue.enqueueBroadcastLocked(r);
- } 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... let's record it for posterity.
- addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
- }
- }
-
- return ActivityManager.BROADCAST_SUCCESS;
- }

把有序广播和无序广播添加到不同的队列中,调用scheduleBroadcastsLocked函数继续发送广播流程
- public abstract void enqueueBroadcastLocked(@NonNull BroadcastRecord r);
-
- public void enqueueBroadcastLocked(BroadcastRecord r) {
- r.applySingletonPolicy(mService);
-
- // 判断广播是否需要替换
- final boolean replacePending = (r.intent.getFlags()
- & Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
-
- // 判断是否有序发送
- boolean serialDispatch = r.ordered;
- if (!serialDispatch) {
- // 如果无序广播,但是是静态注册的广播接收者,serialDispatch会被设置成true,按照有序广播发送流程来发送
- final int N = (r.receivers != null) ? r.receivers.size() : 0;
- for (int i = 0; i < N; i++) {
- if (r.receivers.get(i) instanceof ResolveInfo) {
- serialDispatch = true;
- break;
- }
- }
- }
-
- // 有序发送
- if (serialDispatch) {
- final BroadcastRecord oldRecord =
- replacePending ? replaceOrderedBroadcastLocked(r) : null;
- ...
- // 将BroadcastRecord添加到有序广播队列中(BroadcastDispatcher.mOrderedBroadcasts)
- enqueueOrderedBroadcastLocked(r);
- // 发送广播
- scheduleBroadcastsLocked();
- } else {
- ...
- // 将BroadcastRecord添加到无序广播队列中(mParallelBroadcasts)
- enqueueParallelBroadcastLocked(r);
- // 发送广播
- scheduleBroadcastsLocked();
- ...
- }
- }

通过Handler调用processNextBroadcastLocked继续发送广播流程
- public void scheduleBroadcastsLocked() {
- if (mBroadcastsScheduled) {
- return;
- }
- mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
- mBroadcastsScheduled = true;
- }
-
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case BROADCAST_INTENT_MSG: {
- processNextBroadcast(true);
- } break;
- }
- }
-
- private void processNextBroadcast(boolean fromMsg) {
- synchronized (mService) {
- processNextBroadcastLocked(fromMsg, false);
- }
- }

调用deliverToRegisteredReceiverLocked继续标准广播发送流程
- public void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
- BroadcastRecord r;
- // 更新CPU信息
- mService.updateCpuStats();
-
- if (fromMsg) {
- mBroadcastsScheduled = false;
- }
-
- // First, deliver any non-serialized broadcasts right away.
- // 首先发送无序广播
- while (mParallelBroadcasts.size() > 0) {
- r = mParallelBroadcasts.remove(0);
- r.dispatchTime = SystemClock.uptimeMillis();
- r.dispatchRealTime = SystemClock.elapsedRealtime();
- r.dispatchClockTime = System.currentTimeMillis();
- r.mIsReceiverAppRunning = true;
-
- final int N = r.receivers.size();
- for (int i=0; i<N; i++) {
- Object target = r.receivers.get(i);
- // 发送无序广播流程
- deliverToRegisteredReceiverLocked(r,
- (BroadcastFilter) target, false, i);
- }
- addBroadcastToHistoryLocked(r);
- }
-
- // Now take care of the next serialized one...
-
- // If we are waiting for a process to come up to handle the next
- // broadcast, then do nothing at this point. Just in case, we
- // check that the process we're waiting for still exists.
- // 判断待发送广播所在进程是否还存在,不存在则直接return,保持等待
- if (mPendingBroadcast != null) {
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
- "processNextBroadcast [" + mQueueName + "]: waiting for "
- + mPendingBroadcast.curApp);
-
- boolean isDead;
- if (mPendingBroadcast.curApp.getPid() > 0) {
- synchronized (mService.mPidsSelfLocked) {
- ProcessRecord proc = mService.mPidsSelfLocked.get(
- mPendingBroadcast.curApp.getPid());
- isDead = proc == null || proc.mErrorState.isCrashing();
- }
- } else {
- final ProcessRecord proc = mService.mProcessList.getProcessNamesLOSP().get(
- mPendingBroadcast.curApp.processName, mPendingBroadcast.curApp.uid);
- isDead = proc == null || !proc.isPendingStart();
- }
- if (!isDead) {
- // It's still alive, so keep waiting
- return;
- } else {
- Slog.w(TAG, "pending app ["
- + mQueueName + "]" + mPendingBroadcast.curApp
- + " died before responding to broadcast");
- mPendingBroadcast.state = BroadcastRecord.IDLE;
- mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
- mPendingBroadcast = null;
- }
- }
-
- boolean looped = false;
-
- do {
- final long now = SystemClock.uptimeMillis();
- r = mDispatcher.getNextBroadcastLocked(now);
-
- //当前没有广播需要发送,直接return
- if (r == null) {
- // No more broadcasts are deliverable right now, so all done!
- mDispatcher.scheduleDeferralCheckLocked(false);
- synchronized (mService.mAppProfiler.mProfilerLock) {
- mService.mAppProfiler.scheduleAppGcsLPf();
- }
- if (looped && !skipOomAdj) {
- // If we had finished the last ordered broadcast, then
- // make sure all processes have correct oom and sched
- // adjustments.
- mService.updateOomAdjPendingTargetsLocked(
- OOM_ADJ_REASON_START_RECEIVER);
- }
-
- // when we have no more ordered broadcast on this queue, stop logging
- if (mService.mUserController.mBootCompleted && mLogLatencyMetrics) {
- mLogLatencyMetrics = false;
- }
-
- return;
- }
-
- boolean forceReceive = false;
-
- // Ensure that even if something goes awry with the timeout
- // detection, we catch "hung" broadcasts here, discard them,
- // and continue to make progress.
- //
- // This is only done if the system is ready so that early-stage receivers
- // don't get executed with timeouts; and of course other timeout-
- // exempt broadcasts are ignored.
- int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
- if (mService.mProcessesReady && !r.timeoutExempt && r.dispatchTime > 0) {
- //超时广播强制执行
- if ((numReceivers > 0) &&
- (now > r.dispatchTime + (2 * mConstants.TIMEOUT * numReceivers))) {
- Slog.w(TAG, "Hung broadcast ["
- + mQueueName + "] discarded after timeout failure:"
- + " now=" + now
- + " dispatchTime=" + r.dispatchTime
- + " startTime=" + r.receiverTime
- + " intent=" + r.intent
- + " numReceivers=" + numReceivers
- + " nextReceiver=" + r.nextReceiver
- + " state=" + r.state);
- //出现超时,强制结束
- broadcastTimeoutLocked(false); // forcibly finish this broadcast
- forceReceive = true;
- r.state = BroadcastRecord.IDLE;
- }
- }
-
- if (r.state != BroadcastRecord.IDLE) {
- if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
- "processNextBroadcast("
- + mQueueName + ") called when not idle (state="
- + r.state + ")");
- return;
- }
-
- // 检测广播转发任务是否正在处理中,即AMS正在将一个有序广播转发给它的前一个目标广播接收处理者,
- // 如果是,AMS就会等待这个目标广播接收者处理完该有序广播,然后再转发给下一个广播接收者处理
-
- // r.resultAbort表示广播已经向所有的receiver发送结束或者中途被取消, 如果r.resultAbort为true,会停止处理
- // 当前正在发送的BroadcastRecord,这样优先级比较低的接收者也就收不到这个广播了
- // forceReceive检查BroadcastRecord对象r所描述的广播转发任务是否已经处理完成,或者是否已经被强制结束了。
- // 如果是,那么调用函数cancelBroadcastTimeoutLocked来删除前面发送到AMS所运行在的线程的消息
- // 队列中的一个BROADCAST_TIMEOUT_MSG消息,表示BroadcastRecord对象r所描述的广播转发任务已经
- // 在规定时间内处理完成了。接下来就将该广播BroadcastRecord对象从队列中删除,然后赋值为null
- // Is the current broadcast is done for any reason?
- if (r.receivers == null || r.nextReceiver >= numReceivers
- || r.resultAbort || forceReceive) {
- // Send the final result if requested
- if (r.resultTo != null) {
- boolean sendResult = true;
-
- // if this was part of a split/deferral complex, update the refcount and only
- // send the completion when we clear all of them
- if (r.splitToken != 0) {
- int newCount = mSplitRefcounts.get(r.splitToken) - 1;
- if (newCount == 0) {
- // done! clear out this record's bookkeeping and deliver
- if (DEBUG_BROADCAST_DEFERRAL) {
- Slog.i(TAG_BROADCAST,
- "Sending broadcast completion for split token "
- + r.splitToken + " : " + r.intent.getAction());
- }
- mSplitRefcounts.delete(r.splitToken);
- } else {
- // still have some split broadcast records in flight; update refcount
- // and hold off on the callback
- if (DEBUG_BROADCAST_DEFERRAL) {
- Slog.i(TAG_BROADCAST,
- "Result refcount now " + newCount + " for split token "
- + r.splitToken + " : " + r.intent.getAction()
- + " - not sending completion yet");
- }
- sendResult = false;
- mSplitRefcounts.put(r.splitToken, newCount);
- }
- }
- if (sendResult) {
- if (r.callerApp != null) {
- mService.mOomAdjuster.unfreezeTemporarily(
- r.callerApp,
- CachedAppOptimizer.UNFREEZE_REASON_FINISH_RECEIVER);
- }
- try {
- if (DEBUG_BROADCAST) {
- Slog.i(TAG_BROADCAST, "Finishing broadcast [" + mQueueName + "] "
- + r.intent.getAction() + " app=" + r.callerApp);
- }
- if (r.dispatchTime == 0) {
- // The dispatch time here could be 0, in case it's a parallel
- // broadcast but it has a result receiver. Set it to now.
- r.dispatchTime = now;
- }
- r.mIsReceiverAppRunning = true;
- performReceiveLocked(r, r.resultToApp, r.resultTo,
- new Intent(r.intent), r.resultCode,
- r.resultData, r.resultExtras, false, false, r.shareIdentity,
- r.userId, r.callingUid, r.callingUid, r.callerPackage,
- r.dispatchTime - r.enqueueTime,
- now - r.dispatchTime, 0,
- r.resultToApp != null
- ? r.resultToApp.mState.getCurProcState()
- : ActivityManager.PROCESS_STATE_UNKNOWN);
- logBootCompletedBroadcastCompletionLatencyIfPossible(r);
- // Set this to null so that the reference
- // (local and remote) isn't kept in the mBroadcastHistory.
- r.resultTo = null;
- } catch (RemoteException e) {
- r.resultTo = null;
- Slog.w(TAG, "Failure ["
- + mQueueName + "] sending broadcast result of "
- + r.intent, e);
- }
- }
- }
-
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");
- cancelBroadcastTimeoutLocked();
-
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
- "Finished with ordered broadcast " + r);
-
- // ... and on to the next...
- addBroadcastToHistoryLocked(r);
- if (r.intent.getComponent() == null && r.intent.getPackage() == null
- && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
- // This was an implicit broadcast... let's record it for posterity.
- mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
- r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
- }
- mDispatcher.retireBroadcastLocked(r);
- r = null;
- looped = true;
- continue;
- }
-
- // Check whether the next receiver is under deferral policy, and handle that
- // accordingly. If the current broadcast was already part of deferred-delivery
- // tracking, we know that it must now be deliverable as-is without re-deferral.
- // 检查下一个接收者是否处于延期政策之下,并相应地进行处理。如果当前的广播已经是延迟交付跟踪的一部分,那么我们知道它现在必须可以按原样交付,而不需要重新延迟。
- if (!r.deferred) {
- final int receiverUid = r.getReceiverUid(r.receivers.get(r.nextReceiver));
- if (mDispatcher.isDeferringLocked(receiverUid)) {
- if (DEBUG_BROADCAST_DEFERRAL) {
- Slog.i(TAG_BROADCAST, "Next receiver in " + r + " uid " + receiverUid
- + " at " + r.nextReceiver + " is under deferral");
- }
- // If this is the only (remaining) receiver in the broadcast, "splitting"
- // doesn't make sense -- just defer it as-is and retire it as the
- // currently active outgoing broadcast.
- BroadcastRecord defer;
- if (r.nextReceiver + 1 == numReceivers) {
- if (DEBUG_BROADCAST_DEFERRAL) {
- Slog.i(TAG_BROADCAST, "Sole receiver of " + r
- + " is under deferral; setting aside and proceeding");
- }
- defer = r;
- mDispatcher.retireBroadcastLocked(r);
- } else {
- // Nontrivial case; split out 'uid's receivers to a new broadcast record
- // and defer that, then loop and pick up continuing delivery of the current
- // record (now absent those receivers).
-
- // The split operation is guaranteed to match at least at 'nextReceiver'
- defer = r.splitRecipientsLocked(receiverUid, r.nextReceiver);
- if (DEBUG_BROADCAST_DEFERRAL) {
- Slog.i(TAG_BROADCAST, "Post split:");
- Slog.i(TAG_BROADCAST, "Original broadcast receivers:");
- for (int i = 0; i < r.receivers.size(); i++) {
- Slog.i(TAG_BROADCAST, " " + r.receivers.get(i));
- }
- Slog.i(TAG_BROADCAST, "Split receivers:");
- for (int i = 0; i < defer.receivers.size(); i++) {
- Slog.i(TAG_BROADCAST, " " + defer.receivers.get(i));
- }
- }
- // Track completion refcount as well if relevant
- if (r.resultTo != null) {
- int token = r.splitToken;
- if (token == 0) {
- // first split of this record; refcount for 'r' and 'deferred'
- r.splitToken = defer.splitToken = nextSplitTokenLocked();
- mSplitRefcounts.put(r.splitToken, 2);
- if (DEBUG_BROADCAST_DEFERRAL) {
- Slog.i(TAG_BROADCAST,
- "Broadcast needs split refcount; using new token "
- + r.splitToken);
- }
- } else {
- // new split from an already-refcounted situation; increment count
- final int curCount = mSplitRefcounts.get(token);
- if (DEBUG_BROADCAST_DEFERRAL) {
- if (curCount == 0) {
- Slog.wtf(TAG_BROADCAST,
- "Split refcount is zero with token for " + r);
- }
- }
- mSplitRefcounts.put(token, curCount + 1);
- if (DEBUG_BROADCAST_DEFERRAL) {
- Slog.i(TAG_BROADCAST, "New split count for token " + token
- + " is " + (curCount + 1));
- }
- }
- }
- }
- mDispatcher.addDeferredBroadcast(receiverUid, defer);
- r = null;
- looped = true;
- continue;
- }
- }
- } while (r == null);
-
- // Get the next receiver...
- // 获取下一个将要处理的广播接收者在其列表中的位置
- int 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();
- r.scheduledTime[recIdx] = r.receiverTime;
- // 表示第一个开始处理的接收者,也就是BroadcastRecord对象r所描述的广播任务刚被处理,要记录开始时间来计算是否超过超时时间
- if (recIdx == 0) {
- r.dispatchTime = r.receiverTime;
- r.dispatchRealTime = SystemClock.elapsedRealtime();
- r.dispatchClockTime = System.currentTimeMillis();
-
- if (mLogLatencyMetrics) {
- FrameworkStatsLog.write(
- FrameworkStatsLog.BROADCAST_DISPATCH_LATENCY_REPORTED,
- r.dispatchClockTime - r.enqueueClockTime);
- }
-
- if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
- Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
- createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
- System.identityHashCode(r));
- Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
- createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
- System.identityHashCode(r));
- }
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
- + mQueueName + "] " + r);
- }
- if (! mPendingBroadcastTimeoutMessage) {
- long timeoutTime = r.receiverTime + mConstants.TIMEOUT;
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "Submitting BROADCAST_TIMEOUT_MSG ["
- + mQueueName + "] for " + r + " at " + timeoutTime);
- // 设置超时,传入参数是r.receiverTime + mConstants.TIMEOUT,也就是开始时间加上超时时间
- // BROADCAST_FG_TIMEOUT = 10 * 1000和BROADCAST_BG_TIMEOUT = 60 * 1000,
- // ANR埋雷
- setBroadcastTimeoutLocked(timeoutTime);
- }
-
- final BroadcastOptions brOptions = r.options;
- final Object nextReceiver = r.receivers.get(recIdx);
-
- // 如果当前nextReceiver是一个BroadcastFilter类型,说明是一个动态注册接收者,直接调用deliverToRegisteredReceiverLocked函数发送广播
- if (nextReceiver instanceof BroadcastFilter) {
- // Simple case: this is a registered receiver who gets
- // a direct call.
- BroadcastFilter filter = (BroadcastFilter)nextReceiver;
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "Delivering ordered ["
- + mQueueName + "] to registered "
- + filter + ": " + r);
- r.mIsReceiverAppRunning = true;
-
- deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
- if ((r.curReceiver == null && r.curFilter == null) || !r.ordered) {
- // The receiver has already finished, so schedule to
- // process the next one.
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Quick finishing ["
- + mQueueName + "]: ordered=" + r.ordered
- + " curFilter=" + r.curFilter
- + " curReceiver=" + r.curReceiver);
- r.state = BroadcastRecord.IDLE;
- scheduleBroadcastsLocked();
- } else {
- if (filter.receiverList != null) {
- maybeAddBackgroundStartPrivileges(filter.receiverList.app, r);
- // r is guaranteed ordered at this point, so we know finishReceiverLocked()
- // will get a callback and handle the activity start token lifecycle.
- }
- }
- return;
- }
-
- // Hard case: need to instantiate the receiver, possibly
- // starting its application process to host it.
-
- final ResolveInfo info =
- (ResolveInfo)nextReceiver;
- final ComponentName component = new ComponentName(
- info.activityInfo.applicationInfo.packageName,
- info.activityInfo.name);
- final int receiverUid = info.activityInfo.applicationInfo.uid;
-
- final String targetProcess = info.activityInfo.processName;
- final ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
- info.activityInfo.applicationInfo.uid);
-
- boolean skip = mSkipPolicy.shouldSkip(r, info);
-
- // Filter packages in the intent extras, skipping delivery if none of the packages is
- // visible to the receiver.
- // 是否跳过该广播接收者不处理
- Bundle filteredExtras = null;
- if (!skip && r.filterExtrasForReceiver != null) {
- final Bundle extras = r.intent.getExtras();
- if (extras != null) {
- filteredExtras = r.filterExtrasForReceiver.apply(receiverUid, extras);
- if (filteredExtras == null) {
- if (DEBUG_BROADCAST) {
- Slog.v(TAG, "Skipping delivery to "
- + info.activityInfo.packageName + " / " + receiverUid
- + " : receiver is filtered by the package visibility");
- }
- skip = true;
- }
- }
- }
-
- if (skip) {
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "Skipping delivery of ordered [" + mQueueName + "] "
- + r + " for reason described above");
- r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
- r.curFilter = null;
- r.state = BroadcastRecord.IDLE;
- r.manifestSkipCount++;
- scheduleBroadcastsLocked();
- return;
- }
- r.manifestCount++;
-
- r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
- r.state = BroadcastRecord.APP_RECEIVE;
- r.curComponent = component;
- r.curReceiver = info.activityInfo;
- r.curFilteredExtras = filteredExtras;
- if (DEBUG_MU && r.callingUid > UserHandle.PER_USER_RANGE) {
- Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, "
- + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = "
- + receiverUid);
- }
- final boolean isActivityCapable =
- (brOptions != null && brOptions.getTemporaryAppAllowlistDuration() > 0);
- maybeScheduleTempAllowlistLocked(receiverUid, r, brOptions);
-
- // Report that a component is used for explicit broadcasts.
- if (r.intent.getComponent() != null && r.curComponent != null
- && !TextUtils.equals(r.curComponent.getPackageName(), r.callerPackage)) {
- mService.mUsageStatsService.reportEvent(
- r.curComponent.getPackageName(), r.userId, Event.APP_COMPONENT_USED);
- }
-
- // Broadcast is being executed, its package can't be stopped.
- try {
- mService.mPackageManagerInt.setPackageStoppedState(
- r.curComponent.getPackageName(), false, r.userId);
- } catch (IllegalArgumentException e) {
- Slog.w(TAG, "Failed trying to unstop package "
- + r.curComponent.getPackageName() + ": " + e);
- }
-
- // Is this receiver's application already running?
- // 如果当前进程已经运行,则直接发给该进程,然后return
- if (app != null && app.getThread() != null && !app.isKilled()) {
- try {
- app.addPackage(info.activityInfo.packageName,
- info.activityInfo.applicationInfo.longVersionCode, mService.mProcessStats);
- maybeAddBackgroundStartPrivileges(app, r);
- r.mIsReceiverAppRunning = true;
- processCurBroadcastLocked(r, app);
- return;
- } catch (RemoteException e) {
- final String msg = "Failed to schedule " + r.intent + " to " + info
- + " via " + app + ": " + e;
- Slog.w(TAG, msg);
- app.killLocked("Can't deliver broadcast", ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_UNDELIVERED_BROADCAST, true);
- } catch (RuntimeException e) {
- Slog.wtf(TAG, "Failed sending broadcast to "
- + r.curComponent + " with " + r.intent, e);
- // If some unexpected exception happened, just skip
- // this broadcast. At this point we are not in the call
- // from a client, so throwing an exception out from here
- // will crash the entire system instead of just whoever
- // sent the broadcast.
- logBroadcastReceiverDiscardLocked(r);
- finishReceiverLocked(r, r.resultCode, r.resultData,
- r.resultExtras, r.resultAbort, false);
- scheduleBroadcastsLocked();
- // We need to reset the state if we failed to start the receiver.
- r.state = BroadcastRecord.IDLE;
- return;
- }
-
- // If a dead object exception was thrown -- fall through to
- // restart the application.
- }
-
- // Registered whether we're bringing this package out of a stopped state
- r.mWasReceiverAppStopped =
- (info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0;
- // Not running -- get it started, to be executed when the app comes up.
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "Need to start app ["
- + mQueueName + "] " + targetProcess + " for broadcast " + r);
-
- // 如果app进程不存在,会调用AMS的startProcessLocked函数创建该进程
- r.curApp = mService.startProcessLocked(targetProcess,
- info.activityInfo.applicationInfo, true,
- r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
- new HostingRecord(HostingRecord.HOSTING_TYPE_BROADCAST, r.curComponent,
- r.intent.getAction(), r.getHostingRecordTriggerType()),
- isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY,
- (r.intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false);
- r.curAppLastProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
- if (r.curApp == null) {
- // Ah, this recipient is unavailable. Finish it if necessary,
- // and mark the broadcast record as ready for the next.
- Slog.w(TAG, "Unable to launch app "
- + info.activityInfo.applicationInfo.packageName + "/"
- + receiverUid + " for broadcast "
- + r.intent + ": process is bad");
- logBroadcastReceiverDiscardLocked(r);
- // 进程启动失败,结束发广播流程
- finishReceiverLocked(r, r.resultCode, r.resultData,
- r.resultExtras, r.resultAbort, false);
- scheduleBroadcastsLocked();
- r.state = BroadcastRecord.IDLE;
- return;
- }
-
- maybeAddBackgroundStartPrivileges(r.curApp, r);
-
- // 将BroadcastRecord赋值为mPendingBroadcast,等待应用启动完成后处理
- // 正在启动接收者进程,将正在启动的BroadcastRecord记录存储到mPendingBroadcast中,同时将当前正在
- // 启动的接收者进程在所有接收者中的索引存储到mPendingBroadcastRecvIndex,如果当前广播接收者处理
- // 完,需要继续从mPendingBroadcastRecvIndex计算到下一个接收者发送当前广播
- mPendingBroadcast = r;
- mPendingBroadcastRecvIndex = recIdx;
- }

调用performReceiveLocked继续发送广播流程
- private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
- BroadcastFilter filter, boolean ordered, int index) {
- boolean skip = mSkipPolicy.shouldSkip(r, filter);
-
- // Filter packages in the intent extras, skipping delivery if none of the packages is
- // visible to the receiver.
- // 是否跳过该广播接收者不处理
- Bundle filteredExtras = null;
- if (!skip && r.filterExtrasForReceiver != null) {
- final Bundle extras = r.intent.getExtras();
- if (extras != null) {
- filteredExtras = r.filterExtrasForReceiver.apply(filter.receiverList.uid, extras);
- if (filteredExtras == null) {
- if (DEBUG_BROADCAST) {
- Slog.v(TAG, "Skipping delivery to "
- + filter.receiverList.app
- + " : receiver is filtered by the package visibility");
- }
- skip = true;
- }
- }
- }
-
- if (skip) {
- r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
- return;
- }
-
- r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;
-
- // If this is not being sent as an ordered broadcast, then we
- // don't want to touch the fields that keep track of the current
- // state of ordered broadcasts.
- // 有序广播,保存对应的状态
- if (ordered) {
- r.curFilter = filter;
- filter.receiverList.curBroadcast = r;
- r.state = BroadcastRecord.CALL_IN_RECEIVE;
- if (filter.receiverList.app != null) {
- // Bump hosting application to no longer be in background
- // scheduling class. Note that we can't do that if there
- // isn't an app... but we can only be in that case for
- // things that directly call the IActivityManager API, which
- // are already core system stuff so don't matter for this.
- r.curApp = filter.receiverList.app;
- r.curAppLastProcessState = r.curApp.mState.getCurProcState();
- filter.receiverList.app.mReceivers.addCurReceiver(r);
- mService.enqueueOomAdjTargetLocked(r.curApp);
- mService.updateOomAdjPendingTargetsLocked(
- OOM_ADJ_REASON_START_RECEIVER);
- }
- } else if (filter.receiverList.app != null) {
- mService.mOomAdjuster.unfreezeTemporarily(filter.receiverList.app,
- CachedAppOptimizer.UNFREEZE_REASON_START_RECEIVER);
- }
-
- try {
- if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
- "Delivering to " + filter + " : " + r);
- final boolean isInFullBackup = (filter.receiverList.app != null)
- && filter.receiverList.app.isInFullBackup();
- final boolean isKilled = (filter.receiverList.app != null)
- && filter.receiverList.app.isKilled();
- if (isInFullBackup || isKilled) {
- // Skip delivery if full backup in progress
- // If it's an ordered broadcast, we need to continue to the next receiver.
- // 如果是有序广播,则跳过,执行下一个广播
- if (ordered) {
- skipReceiverLocked(r);
- }
- } else {
- r.receiverTime = SystemClock.uptimeMillis();
- r.scheduledTime[index] = r.receiverTime;
- maybeAddBackgroundStartPrivileges(filter.receiverList.app, r);
- maybeScheduleTempAllowlistLocked(filter.owningUid, r, r.options);
- maybeReportBroadcastDispatchedEventLocked(r, filter.owningUid);
- // 调用performReceiveLocked,继续发送广播流程
- performReceiveLocked(r, filter.receiverList.app, filter.receiverList.receiver,
- prepareReceiverIntent(r.intent, filteredExtras), r.resultCode, r.resultData,
- r.resultExtras, r.ordered, r.initialSticky, r.shareIdentity, r.userId,
- filter.receiverList.uid, r.callingUid, r.callerPackage,
- r.dispatchTime - r.enqueueTime,
- r.receiverTime - r.dispatchTime, filter.getPriority(),
- filter.receiverList.app != null
- ? filter.receiverList.app.mState.getCurProcState()
- : ActivityManager.PROCESS_STATE_UNKNOWN);
- // parallel broadcasts are fire-and-forget, not bookended by a call to
- // finishReceiverLocked(), so we manage their activity-start token here
- if (filter.receiverList.app != null
- && r.mBackgroundStartPrivileges.allowsAny()
- && !r.ordered) {
- postActivityStartTokenRemoval(filter.receiverList.app, r);
- }
- }
- if (ordered) {
- r.state = BroadcastRecord.CALL_DONE_RECEIVE;
- }
- } catch (RemoteException e) {
- Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
- // Clean up ProcessRecord state related to this broadcast attempt
- if (filter.receiverList.app != null) {
- filter.receiverList.app.removeBackgroundStartPrivileges(r);
- if (ordered) {
- filter.receiverList.app.mReceivers.removeCurReceiver(r);
- // Something wrong, its oom adj could be downgraded, but not in a hurry.
- mService.enqueueOomAdjTargetLocked(r.curApp);
- }
- }
- // And BroadcastRecord state related to ordered delivery, if appropriate
- if (ordered) {
- r.curFilter = null;
- filter.receiverList.curBroadcast = null;
- }
- }
- }

如果进程已经启动,则通过Binder调用ActivityThread.ApplicationThread.scheduleRegisteredReceiver函数继续发送广播流程;如果进程没有启动,则直接调用与它关联的一个InnerReceiver对象的Binder代理对象的成员函数performReceive来向它发送广播
- public void performReceiveLocked(BroadcastRecord r, ProcessRecord app, IIntentReceiver receiver,
- Intent intent, int resultCode, String data, Bundle extras,
- boolean ordered, boolean sticky, boolean shareIdentity, int sendingUser,
- int receiverUid, int callingUid, String callingPackage,
- long dispatchDelay, long receiveDelay, int priority,
- int receiverProcessState) throws RemoteException {
- // If the broadcaster opted-in to sharing their identity, then expose package visibility for
- // the receiver.
- if (shareIdentity) {
- mService.mPackageManagerInt.grantImplicitAccess(sendingUser, intent,
- UserHandle.getAppId(receiverUid), callingUid, true);
- }
- // Send the intent to the receiver asynchronously using one-way binder calls.
- if (app != null) {
- final IApplicationThread thread = app.getThread();
- if (thread != null) {
- // If we have an app thread, do the call through that so it is
- // correctly ordered with other one-way calls.
- try {
- final boolean assumeDelivered = !ordered;
- // 进程已经启动,调用IApplicationThread的scheduleRegisteredReceiver继续发送广播流程
- thread.scheduleRegisteredReceiver(
- receiver, intent, resultCode,
- data, extras, ordered, sticky, assumeDelivered, sendingUser,
- app.mState.getReportedProcState(),
- shareIdentity ? callingUid : Process.INVALID_UID,
- shareIdentity ? callingPackage : null);
- } catch (RemoteException ex) {
- // Failed to call into the process. It's either dying or wedged. Kill it gently.
- synchronized (mService) {
- final String msg = "Failed to schedule " + intent + " to " + receiver
- + " via " + app + ": " + ex;
- Slog.w(TAG, msg);
- app.killLocked("Can't deliver broadcast", ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_UNDELIVERED_BROADCAST, true);
- }
- throw ex;
- }
- } else {
- // Application has died. Receiver doesn't exist.
- throw new RemoteException("app.thread must not be null");
- }
- } else {
- // 直接调用与它关联的一个InnerReceiver对象的Binder代理对象的成员函数performReceive来向它发送广播
- receiver.performReceive(intent, resultCode, data, extras, ordered,
- sticky, sendingUser);
- }
- if (!ordered) {
- FrameworkStatsLog.write(BROADCAST_DELIVERY_EVENT_REPORTED,
- receiverUid == -1 ? Process.SYSTEM_UID : receiverUid,
- callingUid == -1 ? Process.SYSTEM_UID : callingUid,
- intent.getAction(),
- BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__RUNTIME,
- BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM,
- dispatchDelay, receiveDelay, 0 /* finish_delay */,
- SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
- app != null ? app.info.packageName : null, callingPackage,
- r.calculateTypeForLogging(), r.getDeliveryGroupPolicy(), r.intent.getFlags(),
- priority, r.callerProcState, receiverProcessState);
- }
- }

传入的receiver是LoadedApk.ReceiverDispatcher.InnerReceiver类型的,会执行LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive继续发送广播流程
- public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
- int resultCode, String dataStr, Bundle extras, boolean ordered,
- boolean sticky, boolean assumeDelivered, int sendingUser, int processState,
- int sendingUid, String sendingPackage)
- throws RemoteException {
- updateProcessState(processState, false);
-
- // We can't modify IIntentReceiver due to UnsupportedAppUsage, so
- // try our best to shortcut to known subclasses, and alert if
- // registered using a custom IIntentReceiver that isn't able to
- // report an expected delivery event
- if (receiver instanceof LoadedApk.ReceiverDispatcher.InnerReceiver) {
- ((LoadedApk.ReceiverDispatcher.InnerReceiver) receiver).performReceive(intent,
- resultCode, dataStr, extras, ordered, sticky, assumeDelivered, sendingUser,
- sendingUid, sendingPackage);
- } else {
- if (!assumeDelivered) {
- Log.wtf(TAG, "scheduleRegisteredReceiver() called for " + receiver
- + " and " + intent + " without mechanism to finish delivery");
- }
- if (sendingUid != Process.INVALID_UID || sendingPackage != null) {
- Log.wtf(TAG,
- "scheduleRegisteredReceiver() called for " + receiver + " and " + intent
- + " from " + sendingPackage + " (UID: " + sendingUid
- + ") without mechanism to propagate the sender's identity");
- }
- if (DEBUG_BROADCAST) {
- Log.d(TAG,"scheduleRegisteredReceiver() called for " + receiver + " and " + intent
- + " from " + sendingPackage + " (UID: " + sendingUid + ")");
- }
- receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky,
- sendingUser);
- }
- }

调用LoadedApk.ReceiverDispatcher的performRecoive函数继续发送广播流程
- public void performReceive(Intent intent, int resultCode, String data,
- Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered,
- int sendingUser, int sendingUid, String sendingPackage) {
- final LoadedApk.ReceiverDispatcher rd;
- if (intent == null) {
- Log.wtf(TAG, "Null intent received");
- rd = null;
- } else {
- rd = mDispatcher.get();
- }
- if (ActivityThread.DEBUG_BROADCAST) {
- int seq = intent.getIntExtra("seq", -1);
- Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
- + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
- }
- if (rd != null) {
- // 如果rd不为空,则调用LoadedApk.ReceiverDispatcher的performReceive方法继续发送广播流程
- rd.performReceive(intent, resultCode, data, extras,
- ordered, sticky, assumeDelivered, sendingUser,
- sendingUid, sendingPackage);
- } else if (!assumeDelivered) {
- // The activity manager dispatched a broadcast to a registered
- // receiver in this process, but before it could be delivered the
- // receiver was unregistered. Acknowledge the broadcast on its
- // behalf so that the system's broadcast sequence can continue.
- if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
- "Finishing broadcast to unregistered receiver");
- IActivityManager mgr = ActivityManager.getService();
- try {
- if (extras != null) {
- extras.setAllowFds(false);
- }
- // rd为空,调用AMS的finishReceiver结束发送广播流程
- mgr.finishReceiver(mApplicationThread.asBinder(), resultCode, data,
- extras, false, intent.getFlags());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }

调用LoadedApk.ReceiverDispatcher.Args.getRunnable()函数继续发送广播流程
- public void performReceive(Intent intent, int resultCode, String data,
- Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered,
- int sendingUser, int sendingUid, String sendingPackage) {
- final Args args = new Args(intent, resultCode, data, extras, ordered,
- sticky, assumeDelivered, sendingUser, sendingUid, sendingPackage);
- if (intent == null) {
- Log.wtf(TAG, "Null intent received");
- } else {
- if (ActivityThread.DEBUG_BROADCAST) {
- int seq = intent.getIntExtra("seq", -1);
- Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
- + " seq=" + seq + " to " + mReceiver);
- }
- }
- // 调用LoadedApk.ReceiverDispatcher.Args.getRunnable()函数继续发送广播流程
- if (intent == null || !mActivityThread.post(args.getRunnable())) {
- IActivityManager mgr = ActivityManager.getService();
- if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
- "Finishing sync broadcast to " + mReceiver);
- // 调用BroadcastReceiver.PendingResult.sendFinished函数结束发送广播流程
- args.sendFinished(mgr);
- }
- }

调用BroadcastReceiver.onReceive函数,完成一次无序广播发送-接收流程
- public final Runnable getRunnable() {
- return () -> {
- final BroadcastReceiver receiver = mReceiver;
-
- if (ActivityThread.DEBUG_BROADCAST) {
- int seq = mCurIntent.getIntExtra("seq", -1);
- Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
- + " seq=" + seq + " to " + mReceiver);
- }
-
- final IActivityManager mgr = ActivityManager.getService();
- final Intent intent = mCurIntent;
- if (intent == null) {
- Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
- + (mRunCalled ? ", run() has already been called" : ""));
- }
-
- mCurIntent = null;
- mDispatched = true;
- mRunCalled = true;
- if (receiver == null || intent == null || mForgotten) {
- if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
- "Finishing null broadcast to " + mReceiver);
- sendFinished(mgr);
- return;
- }
-
- if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
- "broadcastReceiveReg: " + intent.getAction());
- }
-
- try {
- ClassLoader cl = mReceiver.getClass().getClassLoader();
- intent.setExtrasClassLoader(cl);
- // TODO: determine at registration time if caller is
- // protecting themselves with signature permission
- intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent),
- mContext.getAttributionSource());
- setExtrasClassLoader(cl);
- receiver.setPendingResult(this);
- // 调用BroadcastReceiver的onReceive函数
- receiver.onReceive(mContext, intent);
- } catch (Exception e) {
- if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
- "Finishing failed broadcast to " + mReceiver);
- sendFinished(mgr);
- if (mInstrumentation == null ||
- !mInstrumentation.onException(mReceiver, e)) {
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- throw new RuntimeException(
- "Error receiving broadcast " + intent
- + " in " + mReceiver, e);
- }
- }
-
- if (receiver.getPendingResult() != null) {
- finish();
- }
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- };
- }

标准广播同步发送,广播发出后,按照注册了的广播接收器的优先级按序接收广播,优先级的范围是-1000~1000,数字越大,优先级越高,最先接收到该广播,先收到广播的可以修改或者拦截该广播。同级别的广播,动态优先于静态;同级别同类型的广播,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。
静态注册:通过在AndroidManifest.xml中设置android:priority
动态注册:intentFilter.setPriority(1000);
调用AMS的broadcastIntentWithFeature继续发送广播流程。这里和标准广播的区别是,给broadcastIntentWithFeature传的serialized是true,表示是有序广播
- public void sendOrderedBroadcast(Intent intent, String receiverPermission) {
- sendOrderedBroadcast(intent, receiverPermission, /*options=*/ null);
- }
-
- @Override
- public void sendOrderedBroadcast(Intent intent, String receiverPermission, Bundle options) {
- warnIfCallingFromSystemProcess();
- String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
- String[] receiverPermissions = receiverPermission == null ? null
- : new String[] {receiverPermission};
- try {
- intent.prepareToLeaveProcess(this);
- // 调用AMS的broadcastIntentWithFeature继续发送广播流程
- ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
- null, Activity.RESULT_OK, null, null, receiverPermissions,
- null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, options, true,
- false, getUserId());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }

参考上面 2.1.2.2 - 2.1.2.6 ActivityManagerService.broadcastIntentWithFeature - BroadcastQueueImpl.processNextBroadcastLocked。如果进程不存在,则触发进程启动流程,本文不详细描述,进程存在时会调用BroadcastQueueImpl的processCurBroadcastLocked继续有序广播的发送流程
调用ActivityThread.ApplicationThread.scheduleReceiver函数继续发送有序广播流程
- private final void processCurBroadcastLocked(BroadcastRecord r,
- ProcessRecord app) throws RemoteException {
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "Process cur broadcast " + r + " for app " + app);
- final IApplicationThread thread = app.getThread();
- if (thread == null) {
- throw new RemoteException();
- }
- if (app.isInFullBackup()) {
- skipReceiverLocked(r);
- return;
- }
-
- r.curApp = app;
- r.curAppLastProcessState = app.mState.getCurProcState();
- final ProcessReceiverRecord prr = app.mReceivers;
- prr.addCurReceiver(r);
- // 更新进程状态
- app.mState.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
- // Don't bump its LRU position if it's in the background restricted.
- if (mService.mInternal.getRestrictionLevel(app.info.packageName, app.userId)
- < RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
- mService.updateLruProcessLocked(app, false, null);
- }
- // Make sure the oom adj score is updated before delivering the broadcast.
- // Force an update, even if there are other pending requests, overall it still saves time,
- // because time(updateOomAdj(N apps)) <= N * time(updateOomAdj(1 app)).
- mService.enqueueOomAdjTargetLocked(app);
- // 更新进程优先级
- mService.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_START_RECEIVER);
-
- // Tell the application to launch this receiver.
- maybeReportBroadcastDispatchedEventLocked(r, r.curReceiver.applicationInfo.uid);
- r.intent.setComponent(r.curComponent);
-
- // See if we need to delay the freezer based on BroadcastOptions
- if (r.options != null
- && r.options.getTemporaryAppAllowlistDuration() > 0
- && r.options.getTemporaryAppAllowlistType()
- == TEMPORARY_ALLOW_LIST_TYPE_APP_FREEZING_DELAYED) {
- mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(app,
- CachedAppOptimizer.UNFREEZE_REASON_START_RECEIVER,
- r.options.getTemporaryAppAllowlistDuration());
- }
-
- boolean started = false;
- try {
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
- "Delivering to component " + r.curComponent
- + ": " + r);
- mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
- PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
- final boolean assumeDelivered = false;
- // 调用ActivityThread.ApplicationThread.scheduleReceiver函数继续发送有序广播流程
- thread.scheduleReceiver(
- prepareReceiverIntent(r.intent, r.curFilteredExtras),
- r.curReceiver, null /* compatInfo (unused but need to keep method signature) */,
- r.resultCode, r.resultData, r.resultExtras, r.ordered, assumeDelivered,
- r.userId, r.shareIdentity ? r.callingUid : Process.INVALID_UID,
- app.mState.getReportedProcState(),
- r.shareIdentity ? r.callerPackage : null);
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "Process cur broadcast " + r + " DELIVERED for app " + app);
- started = true;
- } finally {
- if (!started) {
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "Process cur broadcast " + r + ": NOT STARTED!");
- r.curApp = null;
- r.curAppLastProcessState = ActivityManager.PROCESS_STATE_UNKNOWN;
- prr.removeCurReceiver(r);
- }
- }
-
- // if something bad happens here, launch the app and try again
- if (app.isKilled()) {
- throw new RemoteException("app gets killed during broadcasting");
- }
- }

调用ActivityThread的handleReceiver继续发送有序广播流程
- public final void scheduleReceiver(Intent intent, ActivityInfo info,
- CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
- boolean ordered, boolean assumeDelivered, int sendingUser, int processState,
- int sendingUid, String sendingPackage) {
- updateProcessState(processState, false);
- ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
- ordered, false, assumeDelivered, mAppThread.asBinder(), sendingUser,
- sendingUid, sendingPackage);
- r.info = info;
- sendMessage(H.RECEIVER, r);
- }
-
- public void handleMessage(Message msg) {
- if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
- switch (msg.what) {
- case RECEIVER:
- if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
- ReceiverData rec = (ReceiverData) msg.obj;
- if (rec.intent != null) {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
- "broadcastReceiveComp: " + rec.intent.getAction());
- } else {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
- "broadcastReceiveComp");
- }
- }
- // 调用ActivityThread的handleReceiver继续发送广播流程
- handleReceiver((ReceiverData)msg.obj);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- break;
- }
- }
- }

调用ActivityThread.ReceiverData的finish函数,结束发送广播流程,ActivityThread.ReceiverData继承BroadcastReceiver.PendingResult,所以会调用到BroadcastReceiver.PendingResult的finish函数
- private void handleReceiver(ReceiverData data) {
- // If we are getting ready to gc after going to the background, well
- // we are back active so skip it.
- unscheduleGcIdler();
-
- String component = data.intent.getComponent().getClassName();
-
- final LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo);
-
- IActivityManager mgr = ActivityManager.getService();
-
- Application app;
- BroadcastReceiver receiver;
- ContextImpl context;
- try {
- app = packageInfo.makeApplicationInner(false, mInstrumentation);
- context = (ContextImpl) app.getBaseContext();
- if (data.info.splitName != null) {
- context = (ContextImpl) context.createContextForSplit(data.info.splitName);
- }
- if (data.info.attributionTags != null && data.info.attributionTags.length > 0) {
- final String attributionTag = data.info.attributionTags[0];
- context = (ContextImpl) context.createAttributionContext(attributionTag);
- }
- java.lang.ClassLoader cl = context.getClassLoader();
- data.intent.setExtrasClassLoader(cl);
- data.intent.prepareToEnterProcess(
- isProtectedComponent(data.info) || isProtectedBroadcast(data.intent),
- context.getAttributionSource());
- data.setExtrasClassLoader(cl);
- receiver = packageInfo.getAppFactory()
- .instantiateReceiver(cl, data.info.name, data.intent);
- } catch (Exception e) {
- if (DEBUG_BROADCAST) Slog.i(TAG,
- "Finishing failed broadcast to " + data.intent.getComponent());
- data.sendFinished(mgr);
- throw new RuntimeException(
- "Unable to instantiate receiver " + component
- + ": " + e.toString(), e);
- }
-
- try {
- if (localLOGV) Slog.v(
- TAG, "Performing receive of " + data.intent
- + ": app=" + app
- + ", appName=" + app.getPackageName()
- + ", pkg=" + packageInfo.getPackageName()
- + ", comp=" + data.intent.getComponent().toShortString()
- + ", dir=" + packageInfo.getAppDir());
-
- sCurrentBroadcastIntent.set(data.intent);
- receiver.setPendingResult(data);
- // 调用BroadcastReceiver的onReceive函数,完成一次广播发送-接收流程
- receiver.onReceive(context.getReceiverRestrictedContext(),
- data.intent);
- } catch (Exception e) {
- if (DEBUG_BROADCAST) Slog.i(TAG,
- "Finishing failed broadcast to " + data.intent.getComponent());
- data.sendFinished(mgr);
- if (!mInstrumentation.onException(receiver, e)) {
- throw new RuntimeException(
- "Unable to start receiver " + component
- + ": " + e.toString(), e);
- }
- } finally {
- sCurrentBroadcastIntent.set(null);
- }
-
- if (receiver.getPendingResult() != null) {
- // 有序广播会走这里,调用ActivityThread.ReceiverData的finish函数,结束发送广播流程
- data.finish();
- }
- }

有序广播会把mType设置成TYPE_COMPONENT,会继续调用BroadcastReceiver.PendingResult的sendFinished函数继续发送广播流程
- public final void finish() {
- if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
- Trace.traceCounter(Trace.TRACE_TAG_ACTIVITY_MANAGER,
- "PendingResult#finish#ClassName:" + mReceiverClassName,
- 1);
- }
-
- if (mType == TYPE_COMPONENT) {
- final IActivityManager mgr = ActivityManager.getService();
- if (QueuedWork.hasPendingWork()) {
- // If this is a broadcast component, we need to make sure any
- // queued work is complete before telling AM we are done, so
- // we don't have our process killed before that. We now know
- // there is pending work; put another piece of work at the end
- // of the list to finish the broadcast, so we don't block this
- // thread (which may be the main thread) to have it finished.
- //
- // Note that we don't need to use QueuedWork.addFinisher() with the
- // runnable, since we know the AM is waiting for us until the
- // executor gets to it.
- QueuedWork.queue(new Runnable() {
- @Override public void run() {
- if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
- "Finishing broadcast after work to component " + mToken);
- sendFinished(mgr);
- }
- }, false);
- } else {
- if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
- "Finishing broadcast to component " + mToken);
- // 调用sendFinished继续发送有序广播流程
- sendFinished(mgr);
- }
- } else {
- if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
- "Finishing broadcast to " + mToken);
- final IActivityManager mgr = ActivityManager.getService();
- sendFinished(mgr);
- }
- }

有序广播会把mAssumeDeliveredHint设置成false,会调用ActivityManager的finishReceiver函数继续发送有序广播流程
- public void sendFinished(IActivityManager am) {
- synchronized (this) {
- if (mFinished) {
- throw new IllegalStateException("Broadcast already finished");
- }
- mFinished = true;
-
- try {
- if (mResultExtras != null) {
- mResultExtras.setAllowFds(false);
- }
-
- // When the OS didn't assume delivery, we need to inform
- // it that we've actually finished the delivery
- if (!mAssumeDeliveredHint) {
- if (mOrderedHint) {
- // 调用AMS的finishReceiver
- am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
- mAbortBroadcast, mFlags);
- } else {
- am.finishReceiver(mToken, 0, null, null, false, mFlags);
- }
- }
- } catch (RemoteException ex) {
- }
- }
- }

调用BroadcastQueueImpl的finishReceiverLocked继续发送有序广播流程
- public void finishReceiver(IBinder caller, int resultCode, String resultData,
- Bundle resultExtras, boolean resultAbort, int flags) {
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Finish receiver: " + caller);
-
- // Refuse possible leaked file descriptors
- if (resultExtras != null && resultExtras.hasFileDescriptors()) {
- throw new IllegalArgumentException("File descriptors passed in Bundle");
- }
-
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized(this) {
- final ProcessRecord callerApp = getRecordForAppLOSP(caller);
- if (callerApp == null) {
- Slog.w(TAG, "finishReceiver: no app for " + caller);
- return;
- }
-
- final BroadcastQueue queue = broadcastQueueForFlags(flags);
- // 调用BroadcastQueueImpl的finishReceiverLocked继续发送有序广播流程
- queue.finishReceiverLocked(callerApp, resultCode,
- resultData, resultExtras, resultAbort, true);
- // updateOomAdjLocked() will be done here
- trimApplicationsLocked(false, OOM_ADJ_REASON_FINISH_RECEIVER);
- }
-
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }

根据广播状态,决定是否要继续分发下一个广播
- public boolean finishReceiverLocked(ProcessRecord app, int resultCode,
- String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
- final BroadcastRecord r = getMatchingOrderedReceiver(app);
- if (r != null) {
- return finishReceiverLocked(r, resultCode,
- resultData, resultExtras, resultAbort, waitForServices);
- } else {
- return false;
- }
- }
-
- public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
- String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
- final int state = r.state;
- final ActivityInfo receiver = r.curReceiver;
- final long finishTime = SystemClock.uptimeMillis();
- final long elapsed = finishTime - r.receiverTime;
- r.state = BroadcastRecord.IDLE;
- final int curIndex = r.nextReceiver - 1;
-
- final int packageState = r.mWasReceiverAppStopped
- ? SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_STOPPED
- : SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL;
-
- if (curIndex >= 0 && curIndex < r.receivers.size() && r.curApp != null) {
- final Object curReceiver = r.receivers.get(curIndex);
- FrameworkStatsLog.write(BROADCAST_DELIVERY_EVENT_REPORTED, r.curApp.uid,
- r.callingUid == -1 ? Process.SYSTEM_UID : r.callingUid,
- r.intent.getAction(),
- curReceiver instanceof BroadcastFilter
- ? BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__RUNTIME
- : BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST,
- r.mIsReceiverAppRunning
- ? BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM
- : BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD,
- r.dispatchTime - r.enqueueTime,
- r.receiverTime - r.dispatchTime,
- finishTime - r.receiverTime,
- packageState,
- r.curApp.info.packageName,
- r.callerPackage,
- r.calculateTypeForLogging(),
- r.getDeliveryGroupPolicy(),
- r.intent.getFlags(),
- BroadcastRecord.getReceiverPriority(curReceiver),
- r.callerProcState,
- r.curAppLastProcessState);
- }
- if (state == BroadcastRecord.IDLE) {
- Slog.w(TAG_BROADCAST, "finishReceiver [" + mQueueName + "] called but state is IDLE");
- }
- if (r.mBackgroundStartPrivileges.allowsAny() && r.curApp != null) {
- if (elapsed > mConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT) {
- // if the receiver has run for more than allowed bg activity start timeout,
- // just remove the token for this process now and we're done
- r.curApp.removeBackgroundStartPrivileges(r);
- } else {
- // It gets more time; post the removal to happen at the appropriate moment
- postActivityStartTokenRemoval(r.curApp, r);
- }
- }
- // If we're abandoning this broadcast before any receivers were actually spun up,
- // nextReceiver is zero; in which case time-to-process bookkeeping doesn't apply.
- if (r.nextReceiver > 0) {
- r.terminalTime[r.nextReceiver - 1] = finishTime;
- }
-
- // if this receiver was slow, impose deferral policy on the app. This will kick in
- // when processNextBroadcastLocked() next finds this uid as a receiver identity.
- if (!r.timeoutExempt) {
- // r.curApp can be null if finish has raced with process death - benign
- // edge case, and we just ignore it because we're already cleaning up
- // as expected.
- if (r.curApp != null
- && mConstants.SLOW_TIME > 0 && elapsed > mConstants.SLOW_TIME) {
- // Core system packages are exempt from deferral policy
- if (!UserHandle.isCore(r.curApp.uid)) {
- if (DEBUG_BROADCAST_DEFERRAL) {
- Slog.i(TAG_BROADCAST, "Broadcast receiver " + (r.nextReceiver - 1)
- + " was slow: " + receiver + " br=" + r);
- }
- mDispatcher.startDeferring(r.curApp.uid);
- } else {
- if (DEBUG_BROADCAST_DEFERRAL) {
- Slog.i(TAG_BROADCAST, "Core uid " + r.curApp.uid
- + " receiver was slow but not deferring: "
- + receiver + " br=" + r);
- }
- }
- }
- } else {
- if (DEBUG_BROADCAST_DEFERRAL) {
- Slog.i(TAG_BROADCAST, "Finished broadcast " + r.intent.getAction()
- + " is exempt from deferral policy");
- }
- }
-
- r.intent.setComponent(null);
- if (r.curApp != null && r.curApp.mReceivers.hasCurReceiver(r)) {
- r.curApp.mReceivers.removeCurReceiver(r);
- mService.enqueueOomAdjTargetLocked(r.curApp);
- }
- if (r.curFilter != null) {
- r.curFilter.receiverList.curBroadcast = null;
- }
- r.curFilter = null;
- r.curReceiver = null;
- r.curApp = null;
- r.curAppLastProcessState = ActivityManager.PROCESS_STATE_UNKNOWN;
- r.curFilteredExtras = null;
- r.mWasReceiverAppStopped = false;
- mPendingBroadcast = null;
-
- r.resultCode = resultCode;
- r.resultData = resultData;
- r.resultExtras = resultExtras;
- if (resultAbort && (r.intent.getFlags()&Intent.FLAG_RECEIVER_NO_ABORT) == 0) {
- r.resultAbort = resultAbort;
- } else {
- r.resultAbort = false;
- }
-
- // If we want to wait behind services *AND* we're finishing the head/
- // active broadcast on its queue
- if (waitForServices && r.curComponent != null && r.queue.isDelayBehindServices()
- && ((BroadcastQueueImpl) r.queue).getActiveBroadcastLocked() == r) {
- ActivityInfo nextReceiver;
- if (r.nextReceiver < r.receivers.size()) {
- Object obj = r.receivers.get(r.nextReceiver);
- nextReceiver = (obj instanceof ActivityInfo) ? (ActivityInfo)obj : null;
- } else {
- nextReceiver = null;
- }
- // Don't do this if the next receive is in the same process as the current one.
- if (receiver == null || nextReceiver == null
- || receiver.applicationInfo.uid != nextReceiver.applicationInfo.uid
- || !receiver.processName.equals(nextReceiver.processName)) {
- // In this case, we are ready to process the next receiver for the current broadcast,
- // but are on a queue that would like to wait for services to finish before moving
- // on. If there are background services currently starting, then we will go into a
- // special state where we hold off on continuing this broadcast until they are done.
- if (mService.mServices.hasBackgroundServicesLocked(r.userId)) {
- Slog.i(TAG, "Delay finish: " + r.curComponent.flattenToShortString());
- r.state = BroadcastRecord.WAITING_SERVICES;
- return false;
- }
- }
- }
-
- r.curComponent = null;
-
- // We will process the next receiver right now if this is finishing
- // an app receiver (which is always asynchronous) or after we have
- // come back from calling a receiver.
- final boolean doNext = (state == BroadcastRecord.APP_RECEIVE)
- || (state == BroadcastRecord.CALL_DONE_RECEIVE);
- if (doNext) {
- // 继续分发下一个广播
- processNextBroadcastLocked(/* fromMsg= */ false, /* skipOomAdj= */ true);
- }
- return doNext;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。