BroadcastReceiver源码解析(Android12)

1,643 阅读20分钟

Android的知识体系搭建

一 概述

BroadcastReceiver 作为 Android 的四大组件之一,也是出场比较频繁的,今天我们就来看看 BroadcastReceiver 是如何工作的。因为 BroadcastReceiver 分为两个部分,一个是广播发送者,一个是广播接受者,所以本文也会分为两个部分介绍,首先是广播接受者。

二 BroadcastReceiver 简介

首先简单回顾一下 BroadcastReceiver 的两种使用方式,分别是静态注册和动态注册。如下,就是 google 官方提供给我们的 BroadcastReceiver 使用示例。

静态注册

<receiver android:name=".MyBroadcastReceiver"  android:exported="true">
	<intent-filter>
		<action android:name="android.intent.action.BOOT_COMPLETED"/>
		<action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
	</intent-filter>
</receiver>

动态注册

BroadcastReceiver br = new MyBroadcastReceiver();

IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
this.registerReceiver(br, filter);

广播类的定义

    public class MyBroadcastReceiver extends BroadcastReceiver {
        private static final String TAG = "MyBroadcastReceiver";

        @Override
        public void onReceive(Context context, Intent intent) {
            final PendingResult pendingResult = goAsync();
            Task asyncTask = new Task(pendingResult, intent);
            asyncTask.execute();
        }

        private static class Task extends AsyncTask<String, Integer, String> {

            private final PendingResult pendingResult;
            private final Intent intent;

            private Task(PendingResult pendingResult, Intent intent) {
                this.pendingResult = pendingResult;
                this.intent = intent;
            }

            @Override
            protected String doInBackground(String... strings) {
                StringBuilder sb = new StringBuilder();
                sb.append("Action: " + intent.getAction() + "\n");
                sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n");
                String log = sb.toString();
                Log.d(TAG, log);
                return log;
            }

            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                // Must call finish() so the BroadcastReceiver can be recycled.
                pendingResult.finish();
            }
        }
    }

发送广播

android 提供了三种发送广播的方式

  • sendOrderedBroadcast(Intent, String)
  • sendBroadcast(Intent)
  • LocalBroadcastManager.sendBroadcast

如下,就是其中一种发送广播的代码示例。

Intent intent = new Intent();
intent.setAction("com.example.broadcast.MY_NOTIFICATION");
intent.putExtra("data","Notice me senpai!");
sendBroadcast(intent);

// 带权限的广播
sendBroadcast(new Intent("com.example.NOTIFY"),
                  Manifest.permission.SEND_SMS);

// 接收方需要注册以下权限
<uses-permission android:name="android.permission.SEND_SMS"/>

关于广播的使用,这里就介绍这么多,不进行扩展了,这些都属于基础内容,我们接下来看看广播具体的工作原理。

广播因为涉及到发送端和注册端,所以我们需要从两个端进行分析,首先我们分析注册端。

三 动态注册

广播的注册分为两种,静态注册和动态注册,静态注册是由 PMS 完成的,动态注册则是由我们应用自己完成的,所以我们先看动态注册。

动态注册也是从 Context 出发,分别经过以下调用

  • ContextWrapper.java -> registerReceiver
  • ContextImpl.java -> registerReceiver
  • ContextImpl.java -> registerReceiverInternal

3.1 registerReceiver

@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
		int flags) {
	return registerReceiver(receiver, filter, null, null, flags);
}

@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
		String broadcastPermission, Handler scheduler) {
	return registerReceiverInternal(receiver, getUserId(),
			filter, broadcastPermission, scheduler, getOuterContext(), 0);
}

3.2 registerReceiverInternal

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
		IntentFilter filter, String broadcastPermission,
		Handler scheduler, Context context, int flags) {
	// 第一部分就是创建了一个 IIntentReceiver 对象
	IIntentReceiver rd = null;
	if (receiver != null) {
		if (mPackageInfo != null && context != null) {
			if (scheduler == null) {
				scheduler = mMainThread.getHandler();
			}
			rd = mPackageInfo.getReceiverDispatcher(
				receiver, context, scheduler,
				mMainThread.getInstrumentation(), true);
		} else {
			if (scheduler == null) {
				scheduler = mMainThread.getHandler();
			}
			rd = new LoadedApk.ReceiverDispatcher(
					receiver, context, scheduler, null, true).getIIntentReceiver();
		}
	}

	// 第二部分就是调用 AMS 的 registerReceiverWithFeature
	try {
		... // 省略代码
		final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
				mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(),
				AppOpsManager.toReceiverId(receiver), rd, filter, broadcastPermission, userId,
				flags);
		if (intent != null) {
			intent.setExtrasClassLoader(getClassLoader());
			// TODO: determine at registration time if caller is
			// protecting themselves with signature permission
			intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent),
					getAttributionSource());
		}
		return intent;
	} catch (RemoteException e) {
		throw e.rethrowFromSystemServer();
	}
}

这里分为两个部分

第一部分 首先是通过 PackageInfo 获取一个 IIntentReceiver,因为广播一般都设计到了跨进程的传递,所以需要将我们传入的 BroadcastReceiver 封装成一个 IIntentReceiver,用来跨进程传递。

第二部分 然后就和其他的四大组件一样,在 registerReceiverInternal 中调用 AMS 的 registerReceiverWithFeature。到此就通过 Binder 调用到了 AMS 所在的系统进程了。

3.3 IIntentReceiver

在 AMS 中,通过调用 mPackageInfo.getReceiverDispatcher 获得了一个 IIntentReceiver,这个 mPackageInfo 是 LoadedApk。

public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
		Context context, Handler handler,
		Instrumentation instrumentation, boolean registered) {
	synchronized (mReceivers) {
		LoadedApk.ReceiverDispatcher rd = null;
		ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;

		// 首先是从复用的 map 中取
		if (registered) {
			map = mReceivers.get(context);
			if (map != null) {
				rd = map.get(r);
			}
		}

		// 如果没有复用的,就新建一个 ReceiverDispatcher
		if (rd == null) {
			rd = new ReceiverDispatcher(r, context, handler,
					instrumentation, registered);
			if (registered) {
				if (map == null) {
					map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
					mReceivers.put(context, map);
				}
				map.put(r, rd);
			}
		} else {
			rd.validate(context, handler);
		}
		rd.mForgotten = false;
		return rd.getIIntentReceiver();
	}
}

3.4 ReceiverDispatcher 的构造函数

ReceiverDispatcher(BroadcastReceiver receiver, Context context,
		Handler activityThread, Instrumentation instrumentation,
		boolean registered) {
	if (activityThread == null) {
		throw new NullPointerException("Handler must not be null");
	}

	// 返回的 mIIntentReceiver 其实就是 ReceiverDispatcher 的内部类 InnerReceiver
	mIIntentReceiver = new InnerReceiver(this, !registered);
	mReceiver = receiver;
	mContext = context;
	mActivityThread = activityThread;
	mInstrumentation = instrumentation;
	mRegistered = registered;
	mLocation = new IntentReceiverLeaked(null);
	mLocation.fillInStackTrace();
}

所有这里最后拿到的 rd.getIIntentReceiver 其实就是 ReceiverDispatcher 的内部类 InnerReceiver。关于 ReceiverDispatcher 的介绍就先到这里,更详细的介绍见 [10 ReceiverDispatcher]。

四 LoadedApk

4.1 getReceiverDispatcher

public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
		Context context, Handler handler,
		Instrumentation instrumentation, boolean registered) {

	synchronized (mReceivers) {
		LoadedApk.ReceiverDispatcher rd = null;
		ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
		// 首先是从一个 map 的集合里取
		if (registered) {
			map = mReceivers.get(context);
			if (map != null) {
				rd = map.get(r);
			}
		}

		// 如果集合里没有,就构造一个 ReceiverDispatcher
		if (rd == null) {
			rd = new ReceiverDispatcher(r, context, handler,
					instrumentation, registered);
			if (registered) {
				// 然后再存到 map 集合
				if (map == null) {
					map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
					mReceivers.put(context, map);
				}
				map.put(r, rd);
			}
		} else {
			rd.validate(context, handler);
		}
		rd.mForgotten = false;
		return rd.getIIntentReceiver();
	}
}

4.2 ReceiverDispatcher

ReceiverDispatcher 是 LoadedApk 中的一个内部类。

static final class ReceiverDispatcher {

	final static class InnerReceiver extends IIntentReceiver.Stub {
		final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
		final LoadedApk.ReceiverDispatcher mStrongRef;

		InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
			mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
			mStrongRef = strong ? rd : null;
		}

		@Override
		public void performReceive(Intent intent, int resultCode, String data,
				Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
			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.performReceive(intent, resultCode, data, extras,
						ordered, sticky, sendingUser);
			} else {
				if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
						"Finishing broadcast to unregistered receiver");
				IActivityManager mgr = ActivityManager.getService();
				try {
					if (extras != null) {
						extras.setAllowFds(false);
					}
					mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
				} catch (RemoteException e) {
					throw e.rethrowFromSystemServer();
				}
			}
		}
	}

ReceiverDispatcher 中有一个 InnerReceiver 的静态内部类,看来它就是实现 IIntentReceiver.Stub 的类,这个就是用来进行跨进程通信的。再来看一看 AMS 中是如何注册广播的。

五 ActivityManagerService

5.1 registerReceiverWithFeature

public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
		String callerFeatureId, String receiverId, IIntentReceiver receiver,
		IntentFilter filter, String permission, int userId, int flags) {


	... // 省略代码

	synchronized (this) {
		IApplicationThread thread;
		if (callerApp != null && ((thread = callerApp.getThread()) == null
				|| thread.asBinder() != caller.asBinder())) {
			// Original caller already died
			return null;
		}

		// mRegisteredReceivers 是一个 map,首先是从这个 map 中取
		// 看看是否有能够复用的 ReceiverList
		ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
		if (rl == null) {
			// 如果没有,就用传递进来的 receiver 构造出一个 ReceiverList
			rl = new ReceiverList(this, callerApp, callingPid, callingUid,
					userId, receiver);
			if (rl.app != null) {
				final int totalReceiversForApp = rl.app.mReceivers.numberOfReceivers();

				// 这里会有一个广播数量的判断,超出最大数量就会报错
				// MAX_RECEIVERS_ALLOWED_PER_APP 的值是1000
				if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
					throw new IllegalStateException("Too many receivers, total of "
							+ totalReceiversForApp + ", registered for pid: "
							+ rl.pid + ", callerPackage: " + callerPackage);
				}
				rl.app.mReceivers.addReceiver(rl);
			} else {
				try {
					receiver.asBinder().linkToDeath(rl, 0);
				} catch (RemoteException e) {
					return sticky;
				}
				rl.linkedToDeath = true;
			}
			mRegisteredReceivers.put(receiver.asBinder(), rl);
		} else if (rl.uid != callingUid) {
			... // 省略代码
		}

		// 构造出一个广播过滤器,它是 IntentFilter 的子类。
		BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
				receiverId, permission, callingUid, userId, instantApp, visibleToInstantApps);
		if (rl.containsFilter(filter)) {
			Slog.w(TAG, "Receiver with filter " + filter
					+ " already registered for pid " + rl.pid
					+ ", callerPackage is " + callerPackage);
		} else {
			rl.add(bf);
			if (!bf.debugCheck()) {
				Slog.w(TAG, "==> For Dynamic broadcast");
			}
			mReceiverResolver.addFilter(bf);
		}

		// 如果有粘性广播,就把它加到粘性广播的队列里
		if (allSticky != null) {
			ArrayList receivers = new ArrayList();
			receivers.add(bf);

			final int stickyCount = allSticky.size();
			for (int i = 0; i < stickyCount; i++) {
				Intent intent = allSticky.get(i);
				BroadcastQueue queue = broadcastQueueForIntent(intent);
				BroadcastRecord r = new BroadcastRecord(queue, intent, null,
						null, null, -1, -1, false, null, null, null, OP_NONE, null, receivers,
						null, 0, null, null, false, true, true, -1, false, null,
						false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */);
				queue.enqueueParallelBroadcastLocked(r);
				queue.scheduleBroadcastsLocked();
			}
		}

		return sticky;
	}
}

到这里,动态广播的注册流程就算告一段落了,接下来我们看看静态注册是如何完成的。

静态注册

静态注册是由系统的 PMS 完成的,系统会在安装 Apk 的时候解析 Apk 的清单文件,然后调用到 PackageParser 的 parseBaseApplication 中。

5.2 parseBaseApplication

[frameworks/base/core/java/android/content/pm/PackageParser.java]

private boolean parseBaseApplication(Package owner, Resources res,
		XmlResourceParser parser, int flags, String[] outError)
... // 省略代码
	if (tagName.equals("receiver")) {
			Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
					true, false);
			if (a == null) {
				mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
				return false;
			}

			hasReceiverOrder |= (a.order != 0);
			owner.receivers.add(a);

		}
}

首先是将 receiver 解析成一个 Activity,这里的 Activity 并不是我们四大组件之一的 Activity,而是系统中对这四大组件的封装。

然后,将解析处理的 Activity 添加到 owner 的 receivers 集合中。这里的 owner 是 Package,receivers 是一个泛型是 Activity 的广播接受者集合。

[frameworks/base/core/java/android/content/pm/PackageParser.java]

public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
@UnsupportedAppUsage
public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
@UnsupportedAppUsage
public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
@UnsupportedAppUsage
public final ArrayList<Service> services = new ArrayList<Service>(0);

到这,静态注册就完成了。

六 广播的发送

广播的发送有几种类型,首先我们从最常用的 sendBroadcast 开始。

6.1 sendBroadcast

广播的发送也是从 Context 开始,经过以下调用

  • ContextWrapper.java -> sendBroadcast
  • ContextImpl.java -> sendBroadcast
  • ActivityManagerService.java -> broadcastIntentWithFeature

6.2 broadcastIntentWithFeature

public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
		Intent intent, String resolvedType, IIntentReceiver resultTo,
		int resultCode, String resultData, Bundle resultExtras,
		String[] requiredPermissions, String[] excludedPermissions, int appOp, Bundle bOptions,
		boolean serialized, boolean sticky, int userId) {

	synchronized(this) {
		// 首先是校验传入的 intent 是否正确,如果不正确就抛出异常
		intent = verifyBroadcastLocked(intent);

		final ProcessRecord callerApp = getRecordForAppLOSP(caller);
		final int callingPid = Binder.getCallingPid();
		final int callingUid = Binder.getCallingUid();

		final long origId = Binder.clearCallingIdentity();
		try {
			// 然后调用 broadcastIntentLocked 真正执行广播发送
			return broadcastIntentLocked(callerApp,
					callerApp != null ? callerApp.info.packageName : null, callingFeatureId,
					intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
					requiredPermissions, excludedPermissions, appOp, bOptions, serialized,
					sticky, callingPid, callingUid, callingUid, callingPid, userId);
		} finally {
			Binder.restoreCallingIdentity(origId);
		}
	}
}

6.3 broadcastIntentLocked

broadcastIntentLocked 这个函数在 Android 12 中非常长,大约有 800 行,所以这里我将这个函数分为几个部分来进行解析。

下面,我将 broadcastIntentLocked 分为以下几个部分进行说明

6.3.1 设置广播 flag

intent = new Intent(intent);

final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
// FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS 表示此广播无法使用静态注册的方式接收
// 这样做是为了防止一些 app 使用静态注册广播的方式拉起自己,实现保活
if (callerInstantApp) {
	intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
}

if (userId == UserHandle.USER_ALL && broadcastAllowList != null) {
		broadcastAllowList = new int[]{};
}

// 已经停止的应用也不会接收到广播,防止不断拉起
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

// 如果我们尚未完成引导,请不要允许启动新进程
if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
	// 添加标志,此广播只能动态接收
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}


// 获取userId
userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
		ALLOW_NON_FULL, "broadcast", callerPackage);

// 确保正在接收此广播的用户或其 parent 正在运行。如果没有,我们将跳过它。
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())) {
		   // 为关闭广播、升级步骤设置例外。
return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
	}
}

在设置广播 flag 这个阶段,主要给广播添加了如下几个 flag

  • FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS -> 此广播是否对 Instant App 可见
  • FLAG_EXCLUDE_STOPPED_PACKAGES ->此广播只有活着的应用才能接收
  • FLAG_RECEIVER_REGISTERED_ONLY -> 此广播只能通过动态注册接收

Instant App 是谷歌提供的一种免安装应用,有兴趣可以自行了解,这里就不多扩展了。

6.3.2 验证系统权限

final String action = intent.getAction();
BroadcastOptions brOptions = null;

// bOptions 不为空时会检查以下权限,从 AMS 来的 bOptions 都是 null
if (bOptions != null) {
	brOptions = new BroadcastOptions(bOptions);
	if (brOptions.getTemporaryAppAllowlistDuration() > 0) {
		// 检查权限,要求应用有下面三个权限
		// CHANGE_DEVICE_IDLE_TEMP_WHITELIST -> 设备的临时白名单
		// START_ACTIVITIES_FROM_BACKGROUND -> 后台启动 Activity
		// START_FOREGROUND_SERVICES_FROM_BACKGROUND -> 允许配套应用从后台启动前台服务
		if (checkComponentPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
				realCallingPid, realCallingUid, -1, true)
				!= PackageManager.PERMISSION_GRANTED
				&& checkComponentPermission(START_ACTIVITIES_FROM_BACKGROUND,
				realCallingPid, realCallingUid, -1, true)
				!= PackageManager.PERMISSION_GRANTED
				&& checkComponentPermission(START_FOREGROUND_SERVICES_FROM_BACKGROUND,
				realCallingPid, realCallingUid, -1, true)
				!= PackageManager.PERMISSION_GRANTED) {
			throw new SecurityException(msg);
		}
	}
	if (brOptions.isDontSendToRestrictedApps()
			&& !isUidActiveLOSP(callingUid)
			&& isBackgroundRestrictedNoCheck(callingUid, callerPackage)) {
		return ActivityManager.START_CANCELED;
	}
	if (brOptions.allowsBackgroundActivityStarts()) {
		// 检查权限,查应用是否可以后台启动
		if (checkComponentPermission(
				android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
				realCallingPid, realCallingUid, -1, true)
				!= PackageManager.PERMISSION_GRANTED) {
			throw new SecurityException(msg);
		} else {
			allowBackgroundActivityStarts = true;
			backgroundActivityStartsToken = null;
		}
	}
}

// 验证受保护的广播仅由系统代码发送,并且系统代码仅发送受保护的。
final boolean isProtectedBroadcast;
try {
	isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
} catch (RemoteException e) {
	return ActivityManager.BROADCAST_SUCCESS;
}

6.3.3 判断系统广播

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);

	} else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
			|| AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
		// 兼容性处理
		if (callerPackage == null) {
			String msg = "Permission Denial: not allowed to send broadcast "
					+ action + " from unknown caller.";
			throw new SecurityException(msg);
		} else if (intent.getComponent() != null) {
			// 它们足以发送到显式组件。。。验证它是否被发送到呼叫应用程序。
			if (!intent.getComponent().getPackageName().equals(
					callerPackage)) {
				String msg = "Permission Denial: not allowed to send broadcast "
						+ action + " to "
						+ intent.getComponent().getPackageName() + " from "
						+ callerPackage;
				Slog.w(TAG, msg);
				throw new SecurityException(msg);
			}
		} else {
			// Limit broadcast to their own package.
			intent.setPackage(callerPackage);
		}
	}
}

6.3.4 处理广播的 action

取出 action 进行处理,action 是在[6.3.2] 中获得的。

boolean timeoutExempt = false;

if (action != null) {
	if (getBackgroundLaunchBroadcasts().contains(action)) {
		intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
	}

	switch (action) {
		case Intent.ACTION_UID_REMOVED: //uid移除
		case Intent.ACTION_PACKAGE_REMOVED: //package移除
		case Intent.ACTION_PACKAGE_CHANGED: //package改变
		case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:// applications不可用
		case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE: // applications可用
		case Intent.ACTION_PACKAGES_SUSPENDED:  // package暂停
		case Intent.ACTION_PACKAGES_UNSUSPENDED:  // package恢复
			// 权限判断
			if (checkComponentPermission(
					android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
					callingPid, callingUid, -1, true)
					!= PackageManager.PERMISSION_GRANTED) {
				// 移除应用是否可以发送广播
				throw new SecurityException(msg);
			}
		... // 省略代码

	if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
			Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
			Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
		final int uid = getUidFromIntent(intent);
		if (uid != -1) {
			final UidRecord uidRec = mProcessList.getUidRecordLOSP(uid);
			if (uidRec != null) {
				uidRec.updateHasInternetPermission();
			}
		}
	}
}

这里涉及到的 action 多达几十种,代码有几百行,这里就不展开了。

6.3.5 处理粘性广播

关于粘性广播这里简单说一下,粘性广播是一种持久性的广播,只要不主动移除,就一种存在内存中。谷歌现在已经不推荐使用粘性广播了,发送粘性广播的函数 sendStickyBroadcast 也被标记为 Deprecated。

当然,本着学习的原则,这里我们还是了解一下粘性广播的原理。

// 如果是粘性广播
if (sticky) {

	// 首先检查权限
	if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
			callingPid, callingUid)
			!= PackageManager.PERMISSION_GRANTED) {
		...
		throw new SecurityException(msg);
	}
	if (requiredPermissions != null && requiredPermissions.length > 0) {
		return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
	}
	if (intent.getComponent() != null) {
		throw new SecurityException(
				"Sticky broadcasts can't target a specific component");
	}

	// 如果不是针对所有用户的广播,那么久要保证它不与其他用户产生冲突
	if (userId != UserHandle.USER_ALL) {
		// 从粘性广播中,取出针对所有用户的广播,判断是否存在冲突
		ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
				UserHandle.USER_ALL);
		if (stickies != null) {
			ArrayList<Intent> list = stickies.get(intent.getAction());
			if (list != null) {
				int N = list.size();
				int i;
				for (i=0; i<N; i++) {
					if (intent.filterEquals(list.get(i))) {
						throw new IllegalArgumentException(
								"Sticky broadcast " + intent + " for user "
								+ userId + " conflicts with existing global broadcast");
					}
				}
			}
		}
	}
	ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
	if (stickies == null) {
		stickies = new ArrayMap<>();
		mStickyBroadcasts.put(userId, stickies);
	}
	ArrayList<Intent> list = stickies.get(intent.getAction());
	if (list == null) {
		list = new ArrayList<>();
		stickies.put(intent.getAction(), list);
	}
	final int stickiesCount = list.size();
	int i;
	for (i = 0; i < stickiesCount; i++) {
		// 替换已经存在的 intent
		if (intent.filterEquals(list.get(i))) {
			list.set(i, new Intent(intent));
			break;
		}
	}
	// 将 intent 添加到粘性广播的 list 中
	if (i >= stickiesCount) {
		list.add(new Intent(intent));
	}
}

6.3.6 获取广播接受者

终于到处理广播接受者的地方了。

... // 省略代码

 // 查找静态注册的广播
 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                 == 0) {
            receivers = collectReceiverComponents(
                    intent, resolvedType, callingUid, users, broadcastAllowList);
        }

//找出所以需要接收此广播的广播接受者
if (intent.getComponent() == null) {
	if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
		for (int i = 0; i < users.length; i++) {
			if (mUserController.hasUserRestriction(
					UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
				continue;
			}
			List<BroadcastFilter> registeredReceiversForUser =
					mReceiverResolver.queryIntent(intent,
							resolvedType, false /*defaultOnly*/, users[i]);
			if (registeredReceivers == null) {
				registeredReceivers = registeredReceiversForUser;
			} else if (registeredReceiversForUser != null) {
				registeredReceivers.addAll(registeredReceiversForUser);
			}
		}
	} else {
		registeredReceivers = mReceiverResolver.queryIntent(intent,
				resolvedType, false /*defaultOnly*/, userId);
	}
}

在查找广播接受者的过程中,会先判断发送的广播是否有 FLAG_RECEIVER_REGISTERED_ONLY 标志,此标志表示该广播只能被动态注册者接收,只有没有该标志的广播,才会去取静态注册的广播。

然后,通过 mReceiverResolver 解析 Intent,获取广播接受者,获得的对象 registeredReceivers 是一个 BroadcastFilter 的集合。

collectReceiverComponents

我们稍微看一下 静态广播的查找逻辑,之前我们已经说了,静态广播是由 PMS 解析的。

    private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
            int callingUid, int[] users, int[] broadcastAllowList) {

	... // 省略代码
	List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
			.queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();

}

首先,通过 AppGlobals.getPackageManager 获得 PMS 的 Binder 对象,然后调用 PMS 的 queryIntentReceivers。

queryIntentReceivers
    public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent,
            String resolvedType, int flags, int userId) {
        return new ParceledListSlice<>(
                queryIntentReceiversInternal(intent, resolvedType, flags, userId,
                        false /*allowDynamicSplits*/));
    }
queryIntentReceiversInternal
    private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
            String resolvedType, int flags, int userId, boolean allowDynamicSplits) {
        ComponentName comp = intent.getComponent();

	 if (comp != null) {
         final List<ResolveInfo> list = new ArrayList<>(1);
         final ActivityInfo ai = getReceiverInfo(comp, flags, userId);

		... // 省略代码
	   if (!blockResolution) {
			ResolveInfo ri = new ResolveInfo();
			ri.activityInfo = ai;
			list.add(ri);
		}
}
getReceiverInfo

6.3.7 处理并行广播


// 是否用新的Intent 替换旧的 Intent
        final boolean replacePending =
                (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;

        if (registeredReceivers != null && broadcastAllowList != null) {
            // if a uid whitelist was provided, remove anything in the application space that wasn't
            // in it.
            for (int i = registeredReceivers.size() - 1; i >= 0; i--) {
                final int owningAppId = UserHandle.getAppId(registeredReceivers.get(i).owningUid);
                if (owningAppId >= Process.FIRST_APPLICATION_UID
                        && Arrays.binarySearch(broadcastAllowList, owningAppId) < 0) {
                    registeredReceivers.remove(i);
                }
            }
        }

        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
        if (!ordered && NR > 0) {
            // 如果我们没有序列化此广播,请分别发送已注册的接收器,这样它们就不会等待组件启动。
            if (isCallerSystem) {
                checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                        isProtectedBroadcast, registeredReceivers);
            }

// 获取广播接受者的队列
            final BroadcastQueue queue = broadcastQueueForIntent(intent);
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                    callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, excludedPermissions, appOp, brOptions, registeredReceivers,
                    resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId,
                    allowBackgroundActivityStarts, backgroundActivityStartsToken,
                    timeoutExempt);

            final boolean replaced = replacePending
                    && (queue.replaceParallelBroadcastLocked(r) != null);
            // 注意:我们假设resultTo对于非有序广播为空。
            if (!replaced) {
	// 将 BroadcastRecord 添加到并行广播
                queue.enqueueParallelBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
            registeredReceivers = null;
            NR = 0;
        }

6.3.8 合并广播

// Merge into one list.
        int ir = 0;
        if (receivers != null) {
            // PACKAGE_ADDED的特殊情况:不允许添加的包观看此广播。这防止了他们在安装后立即将其用作后门来运行。
            // 也许在未来,我们希望为应用程序提供一个特殊的安装广播或类似服务,但我们想故意做出这个决定。
            String skipPackages[] = null;
            if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
                    || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
                    || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
                Uri data = intent.getData();
                if (data != null) {
                    String pkgName = data.getSchemeSpecificPart();
                    if (pkgName != null) {
                        skipPackages = new String[] { pkgName };
                    }
                }
            } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
                skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
            }
            if (skipPackages != null && (skipPackages.length > 0)) {
                for (String skipPackage : skipPackages) {
                    if (skipPackage != null) {
                        int NT = receivers.size();
                        for (int it=0; 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 (isCallerSystem) {
            checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                    isProtectedBroadcast, receivers);
        }

6.3.9 处理串行广播

 if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            BroadcastQueue queue = broadcastQueueForIntent(intent);
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                    callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, excludedPermissions, appOp, brOptions,
                    receivers, resultTo, resultCode, resultData, resultExtras,
                    ordered, sticky, false, userId, allowBackgroundActivityStarts,
                    backgroundActivityStartsToken, timeoutExempt);

            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);

            final BroadcastRecord oldRecord =
                    replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
            if (oldRecord != null) {
                // Replaced, fire the result-to receiver.
                if (oldRecord.resultTo != null) {
                    final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
                    try {
                        oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
                                oldRecord.intent,
                                Activity.RESULT_CANCELED, null, null,
                                false, false, oldRecord.userId);
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Failure ["
                                + queue.mQueueName + "] sending broadcast result of "
                                + intent, e);

                    }
                }
            } else {
				// 处理串行广播
                queue.enqueueOrderedBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
        } else {
            // 没有人对广播感兴趣,但我们仍然想记录下这件事的发生
            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;

6.3.10 小结

以上,就是所有发送广播的过程了,这里我们总结一下。

  • 动态注册是先于静态注册处理的(也就是动态广播优先级更高)
  • 对于部分系统广播,只可以通过动态注册的方式接收
  • 静态注册是可以拉起应用的(现在系统会限制条件)
  • 并行广播会先处理,然后再是串行广播(无序先于有序)

接下来我们再来看看具体的广播处理过程。

七 BroadcastQueue 处理并行广播

接下来,我们再看看并行广播的处理流程。首先从我们在 [6.3.7] 中看到的 BroadcastQueue 开始。

7.1 enqueueParallelBroadcastLocked

public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
	mParallelBroadcasts.add(r);
	enqueueBroadcastHelper(r);
}

mParallelBroadcasts 是 BroadcastQueue 中的一个 ArrayList,保存的是马上要处理的广播列表。然后我们再看 [6.3.7] 中,处理并行广播的第二个函数 scheduleBroadcastsLocked。

7.2 scheduleBroadcastsLocked

public void scheduleBroadcastsLocked() {
	if (mBroadcastsScheduled) {
		return;
	}
	// 发送处理广播的消息
	mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
	mBroadcastsScheduled = true;
}

7.3 handleMessage

public void handleMessage(Message msg) {
	switch (msg.what) {
		case BROADCAST_INTENT_MSG: {
			// 处理下一条广播
			processNextBroadcast(true);
		} break;
		case BROADCAST_TIMEOUT_MSG: {
			synchronized (mService) {
				broadcastTimeoutLocked(true);
			}
		} break;
	}
}
}

八 处理串行广播

然后我们再看看串行广播的处理流程。首先从我们在 [6.3.9] 中看到的 BroadcastQueue 开始。

queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();

8.1 enqueueOrderedBroadcastLocked

public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
	mDispatcher.enqueueOrderedBroadcastLocked(r);
	enqueueBroadcastHelper(r);
}

在这个函数中,将广播添加进了 mDispatcher 中。,这个 mDispatcher 其实就是 BroadcastDispatcher。

8.2 scheduleBroadcastsLocked

public void scheduleBroadcastsLocked() {
	if (mBroadcastsScheduled) {
		return;
	}
	// 发送处理广播的消息 BROADCAST_INTENT_MSG
	mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
	mBroadcastsScheduled = true;
}

所以不论是串行广播,还是并行广播,最后都会通过消息机制,执行到 processNextBroadcast 中。

九 处理广播的逻辑

9.1 processNextBroadcast

private void processNextBroadcast(boolean fromMsg) {
	synchronized (mService) {
		processNextBroadcastLocked(fromMsg, false);
	}
}

9.2 processNextBroadcastLocked

既然处理广播的逻辑都在一个函数里,所以这个函数肯定会分别对串行广播和并行广播做不同的处理。

final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
	BroadcastRecord r;

	mService.updateCpuStats();

	if (fromMsg) {
		mBroadcastsScheduled = false;
	}

	// 1. mParallelBroadcasts 是并行广播的集合
	// 所以首先处理的并行广播
	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);
			// 2. 调用处理并行广播的函数
			deliverToRegisteredReceiverLocked(r,
					(BroadcastFilter) target, false, i);
		}
		//3. 将处理完的并行广播添加到历史记录中
		addBroadcastToHistoryLocked(r);

	}

	// 4. 等待处理的广播,之前在 Service 中也有类似的 mPendingService
	// 等进程启动后处理,如果进程以及被杀,就会丢弃此 mPendingService
	if (mPendingBroadcast != null) {

		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 {
			mPendingBroadcast.state = BroadcastRecord.IDLE;
			mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
			mPendingBroadcast = null;
		}
	}

	boolean looped = false;

	// 5. 处理串行广播(有序广播),注意,这里是一个循环
	do {
		// 6. 从 mDispatcher 中获取需要处理的串行广播
		final long now = SystemClock.uptimeMillis();
		r = mDispatcher.getNextBroadcastLocked(now);

		// 在循环的开始,会判断广播是否处理完毕
		if (r == null) {
			// r 为空,表示串行广播处理完毕,直接返回
			... // 省略代码

			return;
		}

		boolean forceReceive = false;

		//
		int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
		// 8. 判断广播处理的时间
		// 在处理有序广播时,不仅单个广播会超时,多个广播合起来的时间
		// 超过制定时间也会超时,触发 ANR
		if (mService.mProcessesReady && !r.timeoutExempt && r.dispatchTime > 0) {
			if ((numReceivers > 0) &&
					(now > r.dispatchTime + (2 * mConstants.TIMEOUT * numReceivers))) {

				// 如果广播处理超时,就强制关闭
				broadcastTimeoutLocked(false); // forcibly finish this broadcast
				forceReceive = true;
				r.state = BroadcastRecord.IDLE;
			}
		}

		if (r.state != BroadcastRecord.IDLE) {
			return;
		}

		// 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
						mSplitRefcounts.delete(r.splitToken);
					} else {
						// still have some split broadcast records in flight; update refcount
						// and hold off on the callback
						sendResult = false;
						mSplitRefcounts.put(r.splitToken, newCount);
					}
				}
				if (sendResult) {
					if (r.callerApp != null) {
						mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(
								r.callerApp);
					}
					try {
						// 9. 处理串行广播
						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;
					}
				}
			}

			// 10. 一个广播处理完毕,取消超时消息
			cancelBroadcastTimeoutLocked();

			// 11. 把处理过的广播添加到历史中
			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;
		}

		// 检查下一个接收者是否在延迟策略下,并进行相应处理。 如果当前的广播已经是延缓交付的一部分 追踪的一部分,我们知道它现在一定是可以按原样交付的,不需要重新延期。
		if (!r.deferred) {
			final int receiverUid = r.getReceiverUid(r.receivers.get(r.nextReceiver));
			if (mDispatcher.isDeferringLocked(receiverUid)) {
				// 如果这是广播中唯一的(剩余的)接收器,"分割 "就没有意义了--只需将其原封不动地推迟,并将其作为当前活动的外发广播退役。当前活动的外发广播。
				BroadcastRecord defer;
				if (r.nextReceiver + 1 == numReceivers) {
					defer = r;
					mDispatcher.retireBroadcastLocked(r);
				} else {
					//
					defer = r.splitRecipientsLocked(receiverUid, r.nextReceiver);

					// 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);
						} else {
							// new split from an already-refcounted situation; increment count
							final int curCount = mSplitRefcounts.get(token);
							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);

	// 获得下一个广播接收者的id
	int recIdx = r.nextReceiver++;

	// 记录接收器开始的时间,必要时出现 ANR 的话就杀死它。
	r.receiverTime = SystemClock.uptimeMillis();
	if (recIdx == 0) {
		r.dispatchTime = r.receiverTime;
		r.dispatchClockTime = System.currentTimeMillis();
	}
	if (! mPendingBroadcastTimeoutMessage) {
		// 设置超时时间,当前时间 + TIMEOUT(10秒)
		long timeoutTime = r.receiverTime + mConstants.TIMEOUT;
		setBroadcastTimeoutLocked(timeoutTime);
	}

	final BroadcastOptions brOptions = r.options;
	final Object nextReceiver = r.receivers.get(recIdx);

	if (nextReceiver instanceof BroadcastFilter) {
		// 如果下一个是动态注册的广播接收者
		BroadcastFilter filter = (BroadcastFilter)nextReceiver;
		deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
		if (r.receiver == null || !r.ordered) {
			// 如果接收者已经处理完,就继续处理下一个
			r.state = BroadcastRecord.IDLE;
			scheduleBroadcastsLocked();
		} else {
			if (filter.receiverList != null) {
				maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
			}
		}
		return;
	}

	// 困难情况:需要实例化接收器,可能是 启动它的应用进程来承载它。
	// 权限判断

	ResolveInfo info =
		(ResolveInfo)nextReceiver;
	ComponentName component = new ComponentName(
			info.activityInfo.applicationInfo.packageName,
			info.activityInfo.name);

	... // 省略代码,大量权限判断

	// Broadcast is being executed, its package can't be stopped.
	try {
		AppGlobals.getPackageManager().setPackageStoppedState(
				r.curComponent.getPackageName(), false, r.userId);
	} catch (RemoteException e) {
	} catch (IllegalArgumentException e) {
		Slog.w(TAG, "Failed trying to unstop package "
				+ r.curComponent.getPackageName() + ": " + e);
	}

	// 如果广播所在的进程正在运行,就会在这里处理并返回
	if (app != null && app.getThread() != null && !app.isKilled()) {
		try {
			app.addPackage(info.activityInfo.packageName,
					info.activityInfo.applicationInfo.longVersionCode, mService.mProcessStats);
			maybeAddAllowBackgroundActivityStartsToken(app, r);
			processCurBroadcastLocked(r, app);
			return;
		} catch (RemoteException e) {
			Slog.w(TAG, "Exception when sending broadcast to "
				  + r.curComponent, e);
		} 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.
	}

	// 没有返回,说明进程没有运行,先启动进程
	r.curApp = mService.startProcessLocked(targetProcess,
			info.activityInfo.applicationInfo, true,
			r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
			new HostingRecord("broadcast", r.curComponent), isActivityCapable
			? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY,
			(r.intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false);
	if (r.curApp == null) {
		// 这个接收者的进程启动失败,所以处理下一个广播
		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;
	}

	maybeAddAllowBackgroundActivityStartsToken(r.curApp, r);
	mPendingBroadcast = r;
	mPendingBroadcastRecvIndex = recIdx;
}

9.3 deliverToRegisteredReceiverLocked

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
        BroadcastFilter filter, boolean ordered, int index) {

    ... // 省略代码,大量的权限判断

    try {
        if (filter.receiverList.app != null && filter.receiverList.app.isInFullBackup()) {
            // 如果 app 处于备份状态,就跳过有序广播
            if (ordered) {
                skipReceiverLocked(r);
            }
        } else {
            r.receiverTime = SystemClock.uptimeMillis();
            maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
            maybeScheduleTempAllowlistLocked(filter.owningUid, r, r.options);

            // 调用处理广播的逻辑
            performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                    new Intent(r.intent), r.resultCode, r.resultData,
                    r.resultExtras, r.ordered, r.initialSticky, r.userId);
            // 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.allowBackgroundActivityStarts && !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.removeAllowBackgroundActivityStartsToken(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.receiver = null;
            r.curFilter = null;
            filter.receiverList.curBroadcast = null;
        }
    }
}

9.4 performReceiveLocked

void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
        Intent intent, int resultCode, String data, Bundle extras,
        boolean ordered, boolean sticky, int sendingUser)
        throws RemoteException {
    // 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 {
                thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                        data, extras, ordered, sticky, sendingUser,
                        app.mState.getReportedProcState());

            } catch (RemoteException ex) {
                // Failed to call into the process. It's either dying or wedged. Kill it gently.
                synchronized (mService) {
                    Slog.w(TAG, "Can't deliver broadcast to " + app.processName
                            + " (pid " + app.getPid() + "). Crashing it.");
                    app.scheduleCrashLocked("can't deliver broadcast");
                }
                throw ex;
            }
        } else {
            // Application has died. Receiver doesn't exist.
            throw new RemoteException("app.thread must not be null");
        }
    } else {
        receiver.performReceive(intent, resultCode, data, extras, ordered,
                sticky, sendingUser);
    }
}

接下来经过一下调用逻辑,就又到了我们熟悉的 ReceiverDispatcher 了。

  • ActivityThread -> scheduleRegisteredReceiver
  • IIntentReceiver -> performReceive

10 ReceiverDispatcher

在 ReceiverDispatcher 中,有一个 InnerReceiver,它是 IIntentReceiver.Stub 的子类,所以一开始的跨进程调用,会调用到 InnerReceiver 的 performReceive。

10.1 InnerReceiver.performReceive

@Override
public void performReceive(Intent intent, int resultCode, String data,
		Bundle extras, boolean ordered, boolean sticky, int sendingUser) {

	// 定义一个 rd 对象
	final LoadedApk.ReceiverDispatcher rd;
	... // 省略代码

	if (rd != null) {
		// 调用 rd 的 performReceive
		rd.performReceive(intent, resultCode, data, extras,
				ordered, sticky, sendingUser);
	} else {
			... // 省略代码

		IActivityManager mgr = ActivityManager.getService();
		try {
			if (extras != null) {
				extras.setAllowFds(false);
			}
			// 调用完成广播
			mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
		} catch (RemoteException e) {
			throw e.rethrowFromSystemServer();
		}
	}
}
}

10.2 ReceiverDispatcher.performReceive

public void performReceive(Intent intent, int resultCode, String data,
		Bundle extras, boolean ordered, boolean sticky, int sendingUser) {

	// Args 也是 ReceiverDispatcher 的内部类
	final Args args = new Args(intent, resultCode, data, extras, ordered,
			sticky, sendingUser);
	... // 省略代码

	// 调用 Args 的 run
	if (intent == null || !mActivityThread.post(args.getRunnable())) {
		if (mRegistered && ordered) {
			IActivityManager mgr = ActivityManager.getService();
			// 调用 Args 的 sendFinished
			args.sendFinished(mgr);
		}
	}
}

}

10.3 Args 的 run 函数

final class Args extends BroadcastReceiver.PendingResult {
	public final Runnable getRunnable() {
		return () -> {
			final BroadcastReceiver receiver = mReceiver;
			final boolean ordered = mOrdered;



			final IActivityManager mgr = ActivityManager.getService();
			final Intent intent = mCurIntent;


			mCurIntent = null;
			mDispatched = true;
			mRunCalled = true;

			... // 异常处理

			try {
				ClassLoader cl = mReceiver.getClass().getClassLoader();
				intent.setExtrasClassLoader(cl);
				intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent),
						mContext.getAttributionSource());
				setExtrasClassLoader(cl);
				receiver.setPendingResult(this);

				// 调用广播接收者的 onReceive
				receiver.onReceive(mContext, intent);
			} catch (Exception e) {
				... // 省略代码
	}

10.4 sendFinished

        public void sendFinished(IActivityManager am) {
            synchronized (this) {
                if (mFinished) {
                    throw new IllegalStateException("Broadcast already finished");
                }
                mFinished = true;

                try {
                    if (mResultExtras != null) {
                        mResultExtras.setAllowFds(false);
                    }
                    if (mOrderedHint) {
	                    // 调用 AMS 的 finishReceiver
                        am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
                                mAbortBroadcast, mFlags);
                    } else {
                        // This broadcast was sent to a component; it is not ordered,
                        // but we still need to tell the activity manager we are done.
                        am.finishReceiver(mToken, 0, null, null, false, mFlags);
                    }
                } catch (RemoteException ex) {
                }
            }
        }

十一 ActivityManagerService

11.1 finishReceiver

public void finishReceiver(IBinder who, int resultCode, String resultData,
        Bundle resultExtras, boolean resultAbort, int flags) {

    // Refuse possible leaked file descriptors
    if (resultExtras != null && resultExtras.hasFileDescriptors()) {
        throw new IllegalArgumentException("File descriptors passed in Bundle");
    }

    final long origId = Binder.clearCallingIdentity();
    try {
        boolean doNext = false;
        BroadcastRecord r;
        BroadcastQueue queue;

        synchronized(this) {
            if (isOnFgOffloadQueue(flags)) {
                queue = mFgOffloadBroadcastQueue;
            } else if (isOnBgOffloadQueue(flags)) {
                queue = mBgOffloadBroadcastQueue;
            } else {
                queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                        ? mFgBroadcastQueue : mBgBroadcastQueue;
            }

            r = queue.getMatchingOrderedReceiver(who);
            if (r != null) {
                doNext = r.queue.finishReceiverLocked(r, resultCode,
                    resultData, resultExtras, resultAbort, true);
            }
            if (doNext) {
                // 调用 BroadcastQueue 的 processNextBroadcastLocked,分发下一个有序广播
                r.queue.processNextBroadcastLocked(/*fromMsg=*/ false, /*skipOomAdj=*/ true);
            }

            trimApplicationsLocked(false, OomAdjuster.OOM_ADJ_REASON_FINISH_RECEIVER);
        }

    } finally {
        Binder.restoreCallingIdentity(origId);
    }
}

十二 总结

到此,广播的发送和接受就都梳理完毕了,最后再来做一个简单的梳理。

广播的注册

  • 广播的注册分为两种,静态注册和动态注册。
  • 静态注册的逻辑由 PMS 完成
  • 动态注册的逻辑在代码中完成

广播的发送和接收

广播的发送方式有三种

  1. 有序广播
  2. 无序广播
  3. 粘性广播(已废弃)
  • 发送广播时可以发送有序广播和无序广播
  • 无序传播会优先处理
  • 有序广播会有时间限制,超时时间就会 ANR(也就是说只有有序广播才会 ANR,无序广播不会 ANR)
  • 有序广播 ANR 有两种情况,第一种就是单个广播处理超过了 10 秒(后台 60 秒),另一种是多个广播超过时间 是 2 * mConstants.TIMEOUT * numReceivers(TIMEOUT 前台默认是 10 秒,后台默认是 60 秒)
  • 静态广播可以拉起进程(但现在系统限制较严格)

最后用一张图作为总结

BroadcastReceiver广播~1.png