前言
前面已经介绍过动态注册广播接收者的逻辑,静态注册广播接收者的注册写在manifest中,就不介绍了,下面介绍下发送广播的流程
广播分为以下几类:
1.普通广播
普通广播由发送方调用sendBroadcast及相关重载函数发送。
AMS转发这种类型的广播时,根据BroadcastReceiver的注册方式,进行不同的处理流程。
对于动态注册的广播,理论上可以认为,AMS将在同一时刻,向所有监听此广播的BroadcastReceiver发送消息,因此整体的消息传递的效率比较高。
对于静态注册的广播,AMS将按照有序广播的方式,向BroadcastReceiver发送消息。(因为有可能此时静态注册广播接收者还没起来呢,BroadcastReceiver对象还没创建,也没法向其发送广播,如果同时向静态注册的BroadcastReceiver发送广播,那么可能需要在一段时间内同时创建出大量的进程, 这将对系统造成极大的负担;若以有序广播的方式来发送,那么系统可以依次创建进程, 同时,每次收到上一个广播处理完毕的消息后,都可以尝试清理掉无用的进程。 这样即可以避免突发创建大量的进程,又可以及时回收一些系统资源)
2.有序广播
有序广播由发送方调用sendOrderedBroadcast及相关重载函数发送,是一种串行的广播发送方式。
处理这种类型的广播时,AMS会按照优先级,将广播依次分发给BroadcastReceiver。
AMS收到上一个BroadcastReceiver处理完毕的消息或者超时后,才会将广播发送给下一个BroadcastReceiver。
其中,任意一个BroadcastReceiver,都可以中止后续的广播分发流程。
同时,上一个BroadcastReceiver可以将额外的信息添加到广播中。
3.粘性广播
2321 * @deprecated Sticky broadcasts should not be used. They provide no security (anyone
2322 * can access them), no protection (anyone can modify them), and many other problems.
2323 * The recommended pattern is to use a non-sticky broadcast to report that something
2324 * has changed, with another mechanism for apps to retrieve the current value whenever
2325 * desired.
2334 @Deprecated
2335 @RequiresPermission(android.Manifest.permission.BROADCAST_STICKY)
2336 public abstract void sendStickyBroadcast(@RequiresPermission Intent intent);
google已不再建议使用粘性广播
Android设计这种广播的初衷是:
正常情况下,假设发送方发送了一个普通广播A。 在广播A发送完毕后,系统中新注册了一个BroadcastReceiver,此时这个BroadcastReceiver是无法收到广播A的。
但是,如果发送方发送的是一个粘性广播B,那么系统将负责存储该粘性广播。 于是,即使BroadcastReceiver在广播B发送完后才注册到系统,这个BroadcastReceiver也会立即收到AMS转发的广播B。
粘性广播和有序广播等概念实际上不是冲突的。 粘性仅仅强调系统将会保存这个广播,它的其它处理过程与上文一致
sendBroadcast流程分析
ContextImpl#sendBroadcast
1013 @Override
1014 public void sendBroadcast(Intent intent) {
1015 warnIfCallingFromSystemProcess();
1016 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
1017 try {
1018 intent.prepareToLeaveProcess(this);
1019 ActivityManager.getService().broadcastIntent(
1020 mMainThread.getApplicationThread(), intent, resolvedType, null,
1021 Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
1022 getUserId());
1023 } catch (RemoteException e) {
1024 throw e.rethrowFromSystemServer();
1025 }
1026 }
binder call到AMS,system_server中的binder线程响应broadcastIntent
ActivityManangerService#broadcastIntent
22478 public final int broadcastIntent(IApplicationThread caller,
22479 Intent intent, String resolvedType, IIntentReceiver resultTo,
22480 int resultCode, String resultData, Bundle resultExtras,
22481 String[] requiredPermissions, int appOp, Bundle bOptions,
22482 boolean serialized, boolean sticky, int userId) {
22483 enforceNotIsolatedCaller("broadcastIntent");
22484 synchronized(this) {
22485 intent = verifyBroadcastLocked(intent);
22486
22487 final ProcessRecord callerApp = getRecordForAppLocked(caller);
22488 final int callingPid = Binder.getCallingPid();
22489 final int callingUid = Binder.getCallingUid();
22490 final long origId = Binder.clearCallingIdentity(); //broadcast发送方
22491 int res = broadcastIntentLocked(callerApp,
22492 callerApp != null ? callerApp.info.packageName : null,
22493 intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
22494 requiredPermissions, appOp, bOptions, serialized, sticky,
22495 callingPid, callingUid, userId);
22496 Binder.restoreCallingIdentity(origId);
22497 return res;
22498 }
22499 }
broadcastIntent()方法有两个布尔参数serialized和sticky来共同决定是普通广播,有序广播,还是Sticky广播,参数如下:
ActivityManagerService#broadcastIntentLocked
21730 @GuardedBy("this")
21731 final int broadcastIntentLocked(ProcessRecord callerApp,
21732 String callerPackage, Intent intent, String resolvedType,
21733 IIntentReceiver resultTo, int resultCode, String resultData,
21734 Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
21735 boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
21736 intent = new Intent(intent);
21737
21738 final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
21739 // Instant Apps cannot use FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS
21740 if (callerInstantApp) {
21741 intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
21742 }
// If we have not finished booting, don't allow this to launch new processes.
//当系统没启动完成时,不允许静态注册的广播起进程响应broadcast
21759 if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
21760 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
/**
5743 * If set, when sending a broadcast only registered receivers will be
5744 * called -- no BroadcastReceiver components will be launched.
5745 */
21761
21755 // By default broadcasts do not go to stopped apps.
21756 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
//step1: 设置flag
//这个过程最重要的工作是:
//添加flag=FLAG_EXCLUDE_STOPPED_PACKAGES,保证已停止app不会收到该广播;
//当系统还没有启动完成,则不允许启动新进程,即只有动态注册receiver才能接受广播
21762
21763 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
21764 (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
21765 + " ordered=" + ordered + " userid=" + userId);
21766 if ((resultTo != null) && !ordered) {
21767 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
21768 }
21769
21770 userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
21771 ALLOW_NON_FULL, "broadcast", callerPackage);
21772
21773 // Make sure that the user who is receiving this broadcast or its parent is running.
21774 // If not, we will just skip it. Make an exception for shutdown broadcasts, upgrade steps.
21775 if (userId != UserHandle.USER_ALL && !mUserController.isUserOrItsParentRunning(userId)) {
21776 if ((callingUid != SYSTEM_UID
21777 || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
21778 && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
21779 Slog.w(TAG, "Skipping broadcast of " + intent
21780 + ": user " + userId + " and its parent (if any) are stopped");
21781 return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
21782 }
21783 }
//当非USER_ALL广播且当前用户并没有处于Running的情况下,除非是系统升级广播或者关机广播,否则直接返回。
21784
21785 final String action = intent.getAction();
21786 BroadcastOptions brOptions = null;
21787 if (bOptions != null) {
21788 brOptions = new BroadcastOptions(bOptions);
21789 if (brOptions.getTemporaryAppWhitelistDuration() > 0) {
21790 // See if the caller is allowed to do this. Note we are checking against
21791 // the actual real caller (not whoever provided the operation as say a
21792 // PendingIntent), because that who is actually supplied the arguments.
21793 if (checkComponentPermission(
21794 android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
21795 Binder.getCallingPid(), Binder.getCallingUid(), -1, true)
21796 != PackageManager.PERMISSION_GRANTED) {
21797 String msg = "Permission Denial: " + intent.getAction()
21798 + " broadcast from " + callerPackage + " (pid=" + callingPid
21799 + ", uid=" + callingUid + ")"
21800 + " requires "
21801 + android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
21802 Slog.w(TAG, msg);
21803 throw new SecurityException(msg);
21804 }
21805 }
21806 if (brOptions.isDontSendToRestrictedApps()
21807 && !isUidActiveLocked(callingUid)
21808 && isBackgroundRestrictedNoCheck(callingUid, callerPackage)) {
21809 Slog.i(TAG, "Not sending broadcast " + action + " - app " + callerPackage
21810 + " has background restrictions");
21811 return ActivityManager.START_CANCELED;
21812 }
21813 }
21814
21815 // Verify that protected broadcasts are only being sent by system code,
21816 // and that system code is only sending protected broadcasts.
21817 final boolean isProtectedBroadcast;
21818 try {
21819 isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
21820 } catch (RemoteException e) {
21821 Slog.w(TAG, "Remote exception", e);
21822 return ActivityManager.BROADCAST_SUCCESS;
21823 }
21824
21825 final boolean isCallerSystem;
21826 //step2: 广播权限验证
/*
对于callingAppId为SYSTEM_UID,PHONE_UID,SHELL_UID,BLUETOOTH_UID,NFC_UID之一或者callingUid == 0时都畅通无阻;
否则对于调用者进程为空并且不是persistent进程的情况下:
当发送的是受保护广播mProtectedBroadcasts(只允许系统使用),则抛出异常;
当action为ACTION_APPWIDGET_CONFIGURE时,虽然不希望该应用发送这种广播,处于兼容性考虑,限制该广播只允许发送给自己,否则抛出异常。
*/
21827 final boolean isCallerPersistent = (callerApp != null) && callerApp.persistent;
21828 switch (UserHandle.getAppId(callingUid)) {
21829 case ROOT_UID:
21830 case SYSTEM_UID:
21831 case PHONE_UID:
21832 case BLUETOOTH_UID:
21833 case NFC_UID:
21834 case SE_UID:
21835 isCallerSystem = true;
21836 break;
21837 default:
21838
21839 //isCallerSystem = (callerApp != null) && callerApp.persistent;
21840 isCallerSystem = false;
21841 break;
21842 }
21843
21844 // First line security check before anything else: stop non-system apps from
21845 // sending protected broadcasts.
21848 if (!isCallerSystem && !isCallerPersistent) {
21849 if (isProtectedBroadcast) {
21850 String msg = "Permission Denial: not allowed to send broadcast "
21851 + action + " from pid="
21852 + callingPid + ", uid=" + callingUid;
21853 Slog.w(TAG, msg);
21854 throw new SecurityException(msg);
21855
21856 } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
21857 || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
21858 // Special case for compatibility: we don't want apps to send this,
21859 // but historically it has not been protected and apps may be using it
21860 // to poke their own app widget. So, instead of making it protected,
21861 // just limit it to the caller.
21862 if (callerPackage == null) {
21863 String msg = "Permission Denial: not allowed to send broadcast "
21864 + action + " from unknown caller.";
21865 Slog.w(TAG, msg);
21866 throw new SecurityException(msg);
21867 } else if (intent.getComponent() != null) {
21868 // They are good enough to send to an explicit component... verify
21869 // it is being sent to the calling app.
21870 if (!intent.getComponent().getPackageName().equals(
21871 callerPackage)) {
21872 String msg = "Permission Denial: not allowed to send broadcast "
21873 + action + " to "
21874 + intent.getComponent().getPackageName() + " from "
21875 + callerPackage;
21876 Slog.w(TAG, msg);
21877 throw new SecurityException(msg);
21878 }
21879 } else {
21880 // Limit broadcast to their own package.
21881 intent.setPackage(callerPackage);
21882 }
21883 }
21884 }
21885 //step3: 处理系统相关广播
21886 if (action != null) {
21887 if (getBackgroundLaunchBroadcasts().contains(action)) {
21888 if (DEBUG_BACKGROUND_CHECK) {
21889 Slog.i(TAG, "Broadcast action " + action + " forcing include-background");
21890 }
21891 intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
21892 }
21893
21894 switch (action) {
21895 case Intent.ACTION_UID_REMOVED:
21896 case Intent.ACTION_PACKAGE_REMOVED:
21897 case Intent.ACTION_PACKAGE_CHANGED:
21898 case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
21899 case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
21900 case Intent.ACTION_PACKAGES_SUSPENDED:
21901 case Intent.ACTION_PACKAGES_UNSUSPENDED:
21902 // Handle special intents: if this broadcast is from the package
21903 // manager about a package being removed, we need to remove all of
21904 // its activities from the history stack.
21905 if (checkComponentPermission(
21906 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
21907 callingPid, callingUid, -1, true)
21908 != PackageManager.PERMISSION_GRANTED) {
21909 String msg = "Permission Denial: " + intent.getAction()
21910 + " broadcast from " + callerPackage + " (pid=" + callingPid
21911 + ", uid=" + callingUid + ")"
21912 + " requires "
21913 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
21914 Slog.w(TAG, msg);
21915 throw new SecurityException(msg);
21916 }
21917 switch (action) {
21918 case Intent.ACTION_UID_REMOVED:
21919 final int uid = getUidFromIntent(intent);
21920 if (uid >= 0) {
21921 mBatteryStatsService.removeUid(uid);
21922 mAppOpsService.uidRemoved(uid);
21923 }
21924 break;
21925 case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
21926 // If resources are unavailable just force stop all those packages
21927 // and flush the attribute cache as well.
21928 String list[] =
21929 intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
21930 if (list != null && list.length > 0) {
21931 for (int i = 0; i < list.length; i++) {
21932 forceStopPackageLocked(list[i], -1, false, true, true,
21933 false, false, userId, "storage unmount");
21934 }
21935 mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
21936 sendPackageBroadcastLocked(
21937 ApplicationThreadConstants.EXTERNAL_STORAGE_UNAVAILABLE,
21938 list, userId);
21939 }
21940 break;
21941 case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
21942 mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
21943 break;
21944 case Intent.ACTION_PACKAGE_REMOVED:
21945 case Intent.ACTION_PACKAGE_CHANGED:
21946 Uri data = intent.getData();
21947 String ssp;
21948 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
21949 boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
21950 final boolean replacing =
21951 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
21952 final boolean killProcess =
21953 !intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
21954 final boolean fullUninstall = removed && !replacing;
21955 if (removed) {
21956 if (killProcess) {
21957 forceStopPackageLocked(ssp, UserHandle.getAppId(
21958 intent.getIntExtra(Intent.EXTRA_UID, -1)),
21959 false, true, true, false, fullUninstall, userId,
21960 removed ? "pkg removed" : "pkg changed");
21961 }
21962 final int cmd = killProcess
21963 ? ApplicationThreadConstants.PACKAGE_REMOVED
21964 : ApplicationThreadConstants.PACKAGE_REMOVED_DONT_KILL;
21965 sendPackageBroadcastLocked(cmd,
21966 new String[] {ssp}, userId);
21967 if (fullUninstall) {
21968 mAppOpsService.packageRemoved(
21969 intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
21970
21971 // Remove all permissions granted from/to this package
21972 removeUriPermissionsForPackageLocked(ssp, userId, true,
21973 false);
21974
21975 mRecentTasks.removeTasksByPackageName(ssp, userId);
21976
21977 mServices.forceStopPackageLocked(ssp, userId);
21978 mAppWarnings.onPackageUninstalled(ssp);
21979 mCompatModePackages.handlePackageUninstalledLocked(ssp);
21980 mBatteryStatsService.notePackageUninstalled(ssp);
21981 }
21982 } else {
21983 if (killProcess) {
21984 killPackageProcessesLocked(ssp, UserHandle.getAppId(
21985 intent.getIntExtra(Intent.EXTRA_UID, -1)),
21986 userId, ProcessList.INVALID_ADJ,
21987 false, true, true, false, "change " + ssp);
21988 }
21989 cleanupDisabledPackageComponentsLocked(ssp, userId, killProcess,
21990 intent.getStringArrayExtra(
21991 Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
21992 }
21993 }
21994 break;
21995 case Intent.ACTION_PACKAGES_SUSPENDED:
21996 case Intent.ACTION_PACKAGES_UNSUSPENDED:
21997 final boolean suspended = Intent.ACTION_PACKAGES_SUSPENDED.equals(
21998 intent.getAction());
21999 final String[] packageNames = intent.getStringArrayExtra(
22000 Intent.EXTRA_CHANGED_PACKAGE_LIST);
22001 final int userHandle = intent.getIntExtra(
22002 Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
22003
22004 synchronized(ActivityManagerService.this) {
22005 mRecentTasks.onPackagesSuspendedChanged(
22006 packageNames, suspended, userHandle);
22007 }
22008 break;
22009 }
22010 break;
22011 case Intent.ACTION_PACKAGE_REPLACED:
22012 {
22013 final Uri data = intent.getData();
22014 final String ssp;
22015 if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
22016 ApplicationInfo aInfo = null;
22017 try {
22018 aInfo = AppGlobals.getPackageManager()
22019 .getApplicationInfo(ssp, STOCK_PM_FLAGS, userId);
22020 } catch (RemoteException ignore) {}
22021 if (aInfo == null) {
22022 Slog.w(TAG, "Dropping ACTION_PACKAGE_REPLACED for non-existent pkg:"
22023 + " ssp=" + ssp + " data=" + data);
22024 return ActivityManager.BROADCAST_SUCCESS;
22025 }
22026 mStackSupervisor.updateActivityApplicationInfoLocked(aInfo);
22027 mServices.updateServiceApplicationInfoLocked(aInfo);
22028 sendPackageBroadcastLocked(ApplicationThreadConstants.PACKAGE_REPLACED,
22029 new String[] {ssp}, userId);
22030 }
22031 break;
22032 }
22033 case Intent.ACTION_PACKAGE_ADDED:
22034 {
22035 // Special case for adding a package: by default turn on compatibility mode.
22036 Uri data = intent.getData();
22037 String ssp;
22038 if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
22039 final boolean replacing =
22040 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
22041 mCompatModePackages.handlePackageAddedLocked(ssp, replacing);
22042
22043 try {
22044 ApplicationInfo ai = AppGlobals.getPackageManager().
22045 getApplicationInfo(ssp, STOCK_PM_FLAGS, 0);
22046 mBatteryStatsService.notePackageInstalled(ssp,
22047 ai != null ? ai.versionCode : 0);
22048 } catch (RemoteException e) {
22049 }
22050 }
22051 break;
22052 }
22053 case Intent.ACTION_PACKAGE_DATA_CLEARED:
22054 {
22055 Uri data = intent.getData();
22056 String ssp;
22057 if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
22058 mCompatModePackages.handlePackageDataClearedLocked(ssp);
22059 mAppWarnings.onPackageDataCleared(ssp);
22060 }
22061 break;
22062 }
22063 case Intent.ACTION_TIMEZONE_CHANGED:
22064 // If this is the time zone changed action, queue up a message that will reset
22065 // the timezone of all currently running processes. This message will get
22066 // queued up before the broadcast happens.
22067 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
22068 break;
22069 case Intent.ACTION_TIME_CHANGED:
22070 // EXTRA_TIME_PREF_24_HOUR_FORMAT is optional so we must distinguish between
22071 // the tri-state value it may contain and "unknown".
22072 // For convenience we re-use the Intent extra values.
22073 final int NO_EXTRA_VALUE_FOUND = -1;
22074 final int timeFormatPreferenceMsgValue = intent.getIntExtra(
22075 Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT,
22076 NO_EXTRA_VALUE_FOUND /* defaultValue */);
22077 // Only send a message if the time preference is available.
22078 if (timeFormatPreferenceMsgValue != NO_EXTRA_VALUE_FOUND) {
22079 Message updateTimePreferenceMsg =
22080 mHandler.obtainMessage(UPDATE_TIME_PREFERENCE_MSG,
22081 timeFormatPreferenceMsgValue, 0);
22082 mHandler.sendMessage(updateTimePreferenceMsg);
22083 }
22084 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
22085 synchronized (stats) {
22086 stats.noteCurrentTimeChangedLocked();
22087 }
22088 break;
22089 case Intent.ACTION_CLEAR_DNS_CACHE:
22090 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
22091 break;
22092 case Proxy.PROXY_CHANGE_ACTION:
22093 ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
22094 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
22095 break;
22096 case android.hardware.Camera.ACTION_NEW_PICTURE:
22097 case android.hardware.Camera.ACTION_NEW_VIDEO:
22098 // In N we just turned these off; in O we are turing them back on partly,
22099 // only for registered receivers. This will still address the main problem
22100 // (a spam of apps waking up when a picture is taken putting significant
22101 // memory pressure on the system at a bad point), while still allowing apps
22102 // that are already actively running to know about this happening.
22103 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
22104 break;
22105 case android.security.KeyChain.ACTION_TRUST_STORE_CHANGED:
22106 mHandler.sendEmptyMessage(HANDLE_TRUST_STORAGE_UPDATE_MSG);
22107 break;
22108 case "com.android.launcher.action.INSTALL_SHORTCUT":
22109 // As of O, we no longer support this broadcasts, even for pre-O apps.
22110 // Apps should now be using ShortcutManager.pinRequestShortcut().
22111 Log.w(TAG, "Broadcast " + action
22112 + " no longer supported. It will not be delivered.");
22113 return ActivityManager.BROADCAST_SUCCESS;
22114 }
22115
22116 if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
22117 Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
22118 Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
22119 final int uid = getUidFromIntent(intent);
22120 if (uid != -1) {
22121 final UidRecord uidRec = mActiveUids.get(uid);
22122 if (uidRec != null) {
22123 uidRec.updateHasInternetPermission();
22124 }
22125 }
22126 }
22127 }
22128
22129 // Add to the sticky list if requested.
//step4:增加sticky广播
22130 if (sticky) {
22131 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
22132 callingPid, callingUid)
22133 != PackageManager.PERMISSION_GRANTED) {
22134 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
22135 + callingPid + ", uid=" + callingUid
22136 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
22137 Slog.w(TAG, msg);
22138 throw new SecurityException(msg);
22139 }
22140 if (requiredPermissions != null && requiredPermissions.length > 0) {
22141 Slog.w(TAG, "Can't broadcast sticky intent " + intent
22142 + " and enforce permissions " + Arrays.toString(requiredPermissions));
22143 return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
22144 }
22145 if (intent.getComponent() != null) {
22146 throw new SecurityException(
22147 "Sticky broadcasts can't target a specific component");
22148 }
22149 // We use userId directly here, since the "all" target is maintained
22150 // as a separate set of sticky broadcasts.
22151 if (userId != UserHandle.USER_ALL) {
22152 // But first, if this is not a broadcast to all users, then
22153 // make sure it doesn't conflict with an existing broadcast to
22154 // all users.
22155 ArrayMap> stickies = mStickyBroadcasts.get(
22156 UserHandle.USER_ALL);
22157 if (stickies != null) {
22158 ArrayList list = stickies.get(intent.getAction());
22159 if (list != null) {
22160 int N = list.size();
22161 int i;
22162 for (i=0; i> stickies = mStickyBroadcasts.get(userId);
22173 if (stickies == null) {
22174 stickies = new ArrayMap<>();
22175 mStickyBroadcasts.put(userId, stickies);
22176 }
22177 ArrayList list = stickies.get(intent.getAction());
22178 if (list == null) {
22179 list = new ArrayList<>();
22180 stickies.put(intent.getAction(), list);
22181 }
22182 final int stickiesCount = list.size();
22183 int i;
22184 for (i = 0; i < stickiesCount; i++) {
22185 if (intent.filterEquals(list.get(i))) {
22186 // This sticky already exists, replace it.
22187 list.set(i, new Intent(intent));
22188 break;
22189 }
22190 }
22191 if (i >= stickiesCount) {
22192 list.add(new Intent(intent));
22193 }
22194 }
//这个过程主要是将sticky广播增加到list,并放入mStickyBroadcasts里面。
22195 //step5:查询receivers和registeredReceivers
22196 int[] users;
22197 if (userId == UserHandle.USER_ALL) {
22198 // Caller wants broadcast to go to all started users.
22199 users = mUserController.getStartedUserArray();//广播给所有已启动用户
22200 } else {
22201 // Caller wants broadcast to go to one specific user.
22202 users = new int[] {userId};//广播给指定用户
22203 }
22204
22205 // Figure out who all will receive this broadcast.
22206 List receivers = null;
22207 List registeredReceivers = null;
22208 // Need to resolve the intent to interested receivers...
22209 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
22210 == 0) {
22211 receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);//receivers:记录着匹配当前intent的所有静态注册广播接收者;
22212 }
22213 if (intent.getComponent() == null) {
22214 if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
22215 // Query one target user at a time, excluding shell-restricted users
22216 for (int i = 0; i < users.length; i++) {
22217 if (mUserController.hasUserRestriction(
22218 UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
22219 continue;
22220 }
22221 List registeredReceiversForUser =
22222 mReceiverResolver.queryIntent(intent,
22223 resolvedType, false /*defaultOnly*/, users[i]);// 查询动态注册的广播
22224 if (registeredReceivers == null) {
22225 registeredReceivers = registeredReceiversForUser;
22226 } else if (registeredReceiversForUser != null) {
22227 registeredReceivers.addAll(registeredReceiversForUser);
22228 }
22229 }
22230 } else {
22231 registeredReceivers = mReceiverResolver.queryIntent(intent,
22232 resolvedType, false /*defaultOnly*/, userId);//registeredReceivers:记录着匹配当前的所有动态注册的广播接收者
22233 }
22234 }
/*
1119 final IntentResolver mReceiverResolver
1120 = new IntentResolver()
public abstract class IntentResolver
//ReceiverResolver是AMS的成员变量,记录着已注册的广播接收者的resolver.
*/
//step6:处理并行广播
22235 //用于标识是否需要用新intent替换旧的intent。
22236 final boolean replacePending =
22237 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
22238
22239 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction()
22240 + " replacePending=" + replacePending);
22241
22242 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
22243 if (!ordered && NR > 0) { //针对并行广播的情况
22244 // If we are not serializing this broadcast, then send the
22245 // registered receivers separately so they don't wait for the
22246 // components to be launched.
22247 if (isCallerSystem) {
22251 checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
22252 isProtectedBroadcast, registeredReceivers, requiredPermissions);
22254 }
22255 final BroadcastQueue queue = broadcastQueueForIntent(intent); //根据Intent flag决定是返回前台队列还是后台队列
22256 BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
22257 callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
22258 requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
22259 resultCode, resultData, resultExtras, ordered, sticky, false, userId); //创建BroadcastRecord
22260 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
22261 final boolean replaced = replacePending
22262 && (queue.replaceParallelBroadcastLocked(r) != null); //队列当中已经有这个broadcastRecord了,只不过将其替换为新的,那么就调用replaceParallelBroadcastLocked替换就行了,无需入队enqueueParallelBroadcastLocked,激活处理scheduleBroadcastsLocked的相关操作了
22263 // Note: We assume resultTo is null for non-ordered broadcasts.
22264 if (!replaced) { //无法替换的,入队,进入处理流程
22265 queue.enqueueParallelBroadcastLocked(r);
22266 queue.scheduleBroadcastsLocked();
22267 }
22268 registeredReceivers = null;
22269 NR = 0;
22270 }
22271 //step7:合并registeredReceivers到receivers
22272 // Merge into one list.
22273 int ir = 0;
22274 if (receivers != null) {
22275 // A special case for PACKAGE_ADDED: do not allow the package
22276 // being added to see this broadcast. This prevents them from
22277 // using this as a back door to get run as soon as they are
22278 // installed. Maybe in the future we want to have a special install
22279 // broadcast or such for apps, but we'd like to deliberately make
22280 // this decision.
22281 String skipPackages[] = null;
22282 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
22283 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
22284 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
//防止应用监听该广播,在安装时直接运行。
22285 Uri data = intent.getData();
22286 if (data != null) {
22287 String pkgName = data.getSchemeSpecificPart();
22288 if (pkgName != null) {
22289 skipPackages = new String[] { pkgName };
22290 }
22291 }
22292 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
22293 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
22294 }
22295 if (skipPackages != null && (skipPackages.length > 0)) {
22296 for (String skipPackage : skipPackages) {
22297 if (skipPackage != null) {
22298 int NT = receivers.size();
22299 for (int it=0; it= curt.priority) {
22323 // Insert this broadcast record into the final list.
22324 receivers.add(it, curr);
22325 ir++;
22326 curr = null;
22327 it++;
22328 NT++;
22329 } else {
22330 // Skip to the next ResolveInfo in the final list.
22331 it++;
22332 curt = null;
22333 }
22334 }
22335 }
22336 while (ir < NR) {
22337 if (receivers == null) {
22338 receivers = new ArrayList();
22339 }
22340 receivers.add(registeredReceivers.get(ir));
22341 ir++;
22342 }
22343
22344 if (isCallerSystem) {
22348 checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
22349 isProtectedBroadcast, receivers, requiredPermissions);
22351 }
22352 //step8: 处理串行广播
22353 if ((receivers != null && receivers.size() > 0)
22354 || resultTo != null) {
22355 BroadcastQueue queue = broadcastQueueForIntent(intent); //前台queue还是后台queue
22356 BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
22357 callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
22358 requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
22359 resultData, resultExtras, ordered, sticky, false, userId);//创建BroadcastRecord
22360
22361 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r
22362 + ": prev had " + queue.mOrderedBroadcasts.size());
22363 if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
22364 "Enqueueing broadcast " + r.intent.getAction());
22365
22366 final BroadcastRecord oldRecord =
22367 replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
22368 if (oldRecord != null) {
22369 // Replaced, fire the result-to receiver.
22370 if (oldRecord.resultTo != null) {
22371 final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
22372 try {
22373 oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
22374 oldRecord.intent,
22375 Activity.RESULT_CANCELED, null, null,
22376 false, false, oldRecord.userId); //对于原来就存在的Broadcast
22377 } catch (RemoteException e) {
22378 Slog.w(TAG, "Failure ["
22379 + queue.mQueueName + "] sending broadcast result of "
22380 + intent, e);
22381
22382 }
22383 }
22384 } else {
//将BroadcastRecord加入到有序广播队列
22385 queue.enqueueOrderedBroadcastLocked(r);
//处理广播
22386 queue.scheduleBroadcastsLocked();
22387 }
22388 } else {
22389 // There was nobody interested in the broadcast, but we still want to record
22390 // that it happened.
22391 if (intent.getComponent() == null && intent.getPackage() == null
22392 && (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
22393 // This was an implicit broadcast... let's record it for posterity.
//对没有接收者的广播,将其保存起来
22394 addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
22395 }
22396 }
22397
22398 return ActivityManager.BROADCAST_SUCCESS;
22399 }
22400
上面的一些逻辑整理
ActivityManagerService#collectReceiverComponents
返回intent对应的静态注册的receiver,通过PMS查找AndroidMainfest中定义的静态广播
21539
21540 private List collectReceiverComponents(Intent intent, String resolvedType,
21541 int callingUid, int[] users) {
21542 // TODO: come back and remove this assumption to triage all broadcasts
21543 int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
21544
21545 List receivers = null;
21546 try {
21547 HashSet singleUserReceivers = null;
21548 boolean scannedFirstReceivers = false;
21549 for (int user : users) {
21550 // Skip users that have Shell restrictions, with exception of always permitted
21551 // Shell broadcasts
21552 if (callingUid == SHELL_UID
21553 && mUserController.hasUserRestriction(
21554 UserManager.DISALLOW_DEBUGGING_FEATURES, user)
21555 && !isPermittedShellBroadcast(intent)) {
21556 continue;
21557 }
21558 List newReceivers = AppGlobals.getPackageManager()
21559 .queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
21560 if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
21561 // If this is not the system user, we need to check for
21562 // any receivers that should be filtered out.
21563 for (int i=0; i();
21591 }
21592 singleUserReceivers.add(cn);
21593 }
21594 }
21595 }
21596 // Add the new results to the existing results, tracking
21597 // and de-dupping single user receivers.
21598 for (int i=0; i();
21605 }
21606 if (!singleUserReceivers.contains(cn)) {
21607 singleUserReceivers.add(cn);
21608 receivers.add(ri);
21609 }
21610 } else {
21611 receivers.add(ri);
21612 }
21613 }
21614 }
21615 }
21616 } catch (RemoteException ex) {
21617 // pm is in same process, this will never happen.
21618 }
21619 return receivers;
21620 }
ActivityManagerService#broadcastQueueForIntent
决定是返回前台广播队列还是后台广播队列,根据Intent是否有FLAG_RECEIVER_FOREGROUND来决定
757 BroadcastQueue broadcastQueueForIntent(Intent intent) {
758 final boolean isFg = (intent.getFlags() & Intent.) != 0;
759 if (DEBUG_BROADCAST_BACKGROUND) Slog.i(TAG_BROADCAST,
760 "Broadcast intent " + intent + " on "
761 + (isFg ? "foreground" : "background") + " queue");
762 return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
763 }
BroadcastQueue#replaceParallelBroadcastLocked
245 /**
246 * Find the same intent from queued parallel broadcast, replace with a new one and return
247 * the old one.
248 */
249 public final BroadcastRecord replaceParallelBroadcastLocked(BroadcastRecord r) {
250 return replaceBroadcastLocked(mParallelBroadcasts, r, "PARALLEL");
251 }
261 private BroadcastRecord replaceBroadcastLocked(ArrayList queue,
262 BroadcastRecord r, String typeForLogging) {
263 final Intent intent = r.intent;
264 for (int i = queue.size() - 1; i > 0; i--) {
265 final BroadcastRecord old = queue.get(i);
266 if (old.userId == r.userId && intent.filterEquals(old.intent)) {
267 if (DEBUG_BROADCAST) {
268 Slog.v(TAG_BROADCAST, "***** DROPPING "
269 + typeForLogging + " [" + mQueueName + "]: " + intent);
270 }
271 queue.set(i, r);
272 return old;
273 }
274 }
275 return null;
276 }
BroadcastQueue#enqueueParallelBroadcastLocked
将BroadcastRecord发送到mParallelBroadcasts
221 public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
222 mParallelBroadcasts.add(r);
223 enqueueBroadcastHelper(r);
224 }
广播队列中有一个成员变量mParallelBroadcasts,类型为ArrayList,记录着所有的并行广播
94 /**
95 * Lists of all active broadcasts that are to be executed immediately
96 * (without waiting for another broadcast to finish). Currently this only
97 * contains broadcasts to registered receivers, to avoid spinning up
98 * a bunch of processes to execute IntentReceiver components. Background-
99 * and foreground-priority broadcasts are queued separately.
100 */
101 final ArrayList mParallelBroadcasts = new ArrayList<>();
enqueueBroadcastHelper记录广播入队时间
235 private void enqueueBroadcastHelper(BroadcastRecord r) {
236 r.enqueueClockTime = System.currentTimeMillis(); //记录广播的入队时间
237
238 if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
239 Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
240 createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
241 System.identityHashCode(r));
242 }
243 }
从上面的代码,我们知道广播发送方调用sendBroadcast后,AMS会构造对应的BroadcastRecord加入到BroadcastQueue中, 然后调用BroadcastQueue的scheduleBroadcastsLocked函数
BroadcastQueue#scheduleBroadcastsLocked
396 public void scheduleBroadcastsLocked() {
397 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
398 + mQueueName + "]: current="
399 + mBroadcastsScheduled);
400 //避免短时间内重复发送BROADCAST_INTENT_MSG
401 if (mBroadcastsScheduled) {
402 return;
403 }
404 mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
405 mBroadcastsScheduled = true;
406 }
mHandler的构造是在BroadcastQueue的构造函数中构造的
mHandler = new BroadcastHandler(handler.getLooper());
203 BroadcastQueue(ActivityManagerService service, Handler handler,
204 String name, long timeoutPeriod, boolean allowDelayBehindServices) {
205 mService = service;
206 mHandler = new BroadcastHandler(handler.getLooper());
207 mQueueName = name;
208 mTimeoutPeriod = timeoutPeriod;
209 mDelayBehindServices = allowDelayBehindServices;
210 }
而BroadcastQueue在AMS的构造函数中构造
3160 mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
3161 "foreground", BROADCAST_FG_TIMEOUT, false);
3162 mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
3163 "background", BROADCAST_BG_TIMEOUT, true);
3137 mHandlerThread = new ServiceThread(TAG,
3138 THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
3139 mHandlerThread.start();
3140 mHandler = new MainHandler(mHandlerThread.getLooper());
创建一个Handler,使用的是ServiceThread的Looper
166 final class BroadcastHandler extends Handler {
167 public BroadcastHandler(Looper looper) {
168 super(looper, null, true);
169 }
170
171 @Override
172 public void handleMessage(Message msg) {
173 switch (msg.what) {
174 case BROADCAST_INTENT_MSG: {
175 if (DEBUG_BROADCAST) Slog.v(
176 TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
177 processNextBroadcast(true);
178 } break;
179 case BROADCAST_TIMEOUT_MSG: {
180 synchronized (mService) {
181 broadcastTimeoutLocked(true);
182 }
183 } break;
184 }
185 }
186 }
BroadcastQueue#processNextBroadcast
854 //add arg parallelOnce if true, process one broadcast
855 void processNextBroadcast(boolean fromMsg) {
856 processNextBroadcast(fromMsg, false);
857 }
858
859 void processNextBroadcast(boolean fromMsg, boolean parallelOnce) {
860 synchronized (mService) {
861 processNextBroadcastLocked(fromMsg, false, parallelOnce);
862 }
863 }
864
865 final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
866 processNextBroadcastLocked(fromMsg, skipOomAdj, false);
867 }
Broadcast广播相关的resultTo如何设置
举例:
163 mContext.sendOrderedBroadcastAsUser(completeIntent, managedProfileUserHandle, null,
164 dpcReceivedSuccessReceiver, null, Activity.RESULT_OK, null, null);
2254 /**
2255 * Version of
2256 * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)}
2257 * that allows you to specify the
2258 * user the broadcast will be sent to. This is not available to applications
2259 * that are not pre-installed on the system image.
2260 *
2261 * See {@link BroadcastReceiver} for more information on Intent broadcasts.
2262 *
2263 * @param intent The Intent to broadcast; all receivers matching this
2264 * Intent will receive the broadcast.
2265 * @param user UserHandle to send the intent to.
2266 * @param receiverPermission String naming a permissions that
2267 * a receiver must hold in order to receive your broadcast.
2268 * If null, no permission is required.
2269 * @param resultReceiver Your own BroadcastReceiver to treat as the final
2270 * receiver of the broadcast.
2271 * @param scheduler A custom Handler with which to schedule the
2272 * resultReceiver callback; if null it will be
2273 * scheduled in the Context's main thread.
2274 * @param initialCode An initial value for the result code. Often
2275 * Activity.RESULT_OK.
2276 * @param initialData An initial value for the result data. Often
2277 * null.
2278 * @param initialExtras An initial value for the result extras. Often
2279 * null.
2280 *
2281 * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
2282 */
2283 @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
2284 public abstract void sendOrderedBroadcastAsUser(@RequiresPermission Intent intent,
2285 UserHandle user, @Nullable String receiverPermission, BroadcastReceiver resultReceiver,
2286 @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
2287 @Nullable Bundle initialExtras);
注意,这里是发送的流程,其中的rd就代表动态注册的resultTo receiver
1259 @Override
1260 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
1261 String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
1262 Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
1263 IIntentReceiver rd = null;
1264 if (resultReceiver != null) {
1265 if (mPackageInfo != null) {
1266 if (scheduler == null) {
1267 scheduler = mMainThread.getHandler();
1268 }
1269 rd = mPackageInfo.getReceiverDispatcher(
1270 resultReceiver, getOuterContext(), scheduler,
1271 mMainThread.getInstrumentation(), false);
1272 } else {
1273 if (scheduler == null) {
1274 scheduler = mMainThread.getHandler();
1275 }
1276 rd = new LoadedApk.ReceiverDispatcher(resultReceiver, getOuterContext(),
1277 scheduler, null, false).getIIntentReceiver();
1278 }
1279 }
1280 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
1281 String[] receiverPermissions = receiverPermission == null ? null
1282 : new String[] {receiverPermission};
1283 try {
1284 intent.prepareToLeaveProcess(this);
1285 ActivityManager.getService().broadcastIntent(
1286 mMainThread.getApplicationThread(), intent, resolvedType, rd,
1287 initialCode, initialData, initialExtras, receiverPermissions,
1288 appOp, options, true, false, user.getIdentifier());
1289 } catch (RemoteException e) {
1290 throw e.rethrowFromSystemServer();
1291 }
1292 }
调用到processNextBroadcast,这个流程较为复杂,单独写一章梳理相关流程