Basic knowledge of
The broadcast-related logic of the framework layer is mainly in ams. Java and BroadcastQueue. Java, which represents a broadcast, is BroadcastRecord.
classification
-
Registration method:
- Static registration: Android manifest file registration, resident broadcast, slow distribution.
- Dynamic registration: registration in code, very resident, fast distribution.
-
Receiver:
- Display broadcast: Specifies the class type of the receiver
- Implicit broadcast: Specify only actions, URIs, etc. Android 8.0 limits the reception of implicit broadcast
-
Sending mode:
- Sequential broadcast: Serial distribution is inefficient and can be truncated by abortBroadcast. Receivers are sorted according to priority when enqueueing.
- Disorder broadcast: default disorder; Parallel distribution; Can not be intercepted, terminated, modified; No priority issues; Data is passed with intent.putextra
Statically registered broadcasts are treated as serial broadcasts, because they may be designed to pull up multiple processes, etc., before serial broadcasts have timeout processing.
-
Processing type:
-
Foreground broadcast: Intent.FLAG_RECEIVER_FOREGROUND is added when the packet is sent. The timeout duration is 10 seconds
-
Background broadcast: default background, timeout period 60s
In AMS, the foreground broadcast and the background broadcast respectively have a broadcast queue, which do not interfere with each other.
-
Common command
- dumpsys activity broadcasts
- Registered Receivers: Lists all Registered Receivers
- Receiver Resolver Table: Resolution Table of the Receiver
- Historical broadcasts [foreground]: Historical broadcast history
- Historical broadcasts summary [foreground]: Historical broadcasts
- Historical broadcasts [background] : history of background broadcasts
- Historical broadcasts Summary [background]: Indicates the Historical record of background broadcasts
/ / registered receiver * ReceiverList {7657857 3271 com. Android. Systemui / 1000 / u0 remote: 5 d6fdd6} App = 3271: com. Android. Systemui uid = 1000 user / 1000 pid = 3271 = 0 / / process related information, pid, uid, such as the user Filter # 0: BroadcastFilter {b28ef44} / / : lists the current receiver all BroadcastFilter Action: "android. Intent. Action. CLOSE_SYSTEM_DIALOGS"Copy the code
/ / receiver of the lookup table android. Intent. Action. CLOSE_SYSTEM_DIALOGS: BroadcastFilter{cd0b64d 1000/u0 ReceiverList{5cd41e4 2477 system/1000/u0 local:7b2f177}} BroadcastFilter{766ac91 1000/u0 ReceiverList{b2bd6b8 2477 system/1000/u0 local:dd6451b}} BroadcastFilter{707a39e 1000/u-1 ReceiverList{6db3dd9 2477 system/1000/u-1 local:28e4020}} BroadcastFilter{921cf0a 1000/u0 ReceiverList{a168375 3271 com.android.systemui/1000/u0 remote:792eaac}} BroadcastFilter{eb0f625 1000/u-1 ReceiverList{f9ba1c 3271 com.android.systemui/1000/u-1 remote:311c78f}} BroadcastFilter{b28ef44 1000/u0 ReceiverList{**7657857** 3271 com.android.systemui/1000/u0 remote:5d6fdd6}} BroadcastFilter{3dc5af6 1000/u0 ReceiverList{9ad5b91 2477 system/1000/u0 local:ab3e1b8}} BroadcastFilter{84a1c2 1000/u0 ReceiverList{27a8e0d 5062 com.miui.securitycenter.remote/1000/u0 remote:49ca0a4}} BroadcastFilter{6151148 1000/u0 ReceiverList{6ac8feb 5062 com.miui.securitycenter.remote/1000/u0 remote:17c273a}} BroadcastFilter{1525a45 1000/u0 ReceiverList{caf9abc 5062 com.miui.securitycenter.remote/1000/u0 remote:aa646af}}Copy the code
Historical Broadcast foreground #1: BroadcastRecord{8888912 u0 com.mi_connect_service. mi_mover_endpoint_found} to user 0 // user 0 Intent {act= com.mi.mi_connect_service. mi_mover_endpoint_found FLG =0x11000030 (has extras)} FLAG_RECEIVER_FOREGROUND | FLAG_RECEIVER_INCLUDE_BACKGROUND | |FLAG_INCLUDE_STOPPED_PACKAGES | FLAG_EXCLUDE_STOPPED_PACKAGES extras: Bundle[{STRIPPED=1}] caller=com.xiaomi.mi_connect_service 9219:com.xiaomi.mi_connect_service/1000 pid=9219 uid=1000 // Send information broadcast app requiredPermissions = [com. Xiaomi. Mi_connect_service. Permission. RECEIVE_ENDPOINT] appOp = 1 / / radio receiver permissions EnqueueClockTime =2021-09-11 16:04:57.623 dispatchClockTime=2021-09-11 16:04:57.623 // dispatchTime=-1m2s207ms (0 since enq) finishTime=-1m2s164ms (+43ms since disp) // End time & Distribution time resultTo= NULL resultCode=0 resultData=null // NextReceiver =1 receiver= NULL +42ms #0: resultCode = 0; resultTo =null; (manifest) // Receiver Priority =0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=false // The default priority is 0, ActivityInfo: / / information receiver name = com. Beautiful miui. Huanji. Ble. MiConnectBleReceiver packageName = com. Beautiful miui. Huanji enabled = true exported = true directBootAware=false resizeMode=RESIZE_MODE_RESIZEABLECopy the code
Historical Broadcast background #29: Radio / / the background queue article 29 BroadcastRecord {android e0ebea0 u - 1. Intent. Action. PHONE_STATE {color}} / / to the user - 1-1 represents user_all intent { Act = android. Intent. Action. PHONE_STATE FLG = 0 x1000010 (from the extras)} / / extras intent information: Bundle[\{incoming_number=18381098208, State =IDLE}] Caller = Android 1309: System /1000 PID =1309 UID =1000 requiredPermissions=[android.permission.READ_PHONE_STATE, AppOp =-1 // Permission of broadcast request receiver enqueueClockTime=2021-06-23 11:41:05.687 DispatchClockTime =-1m39s763ms (0 since enq) finishTime=-1m39s755ms (+8ms since disp) // End time & distribution time // Distribution information and status of each receiver // Deliver represents the current receiver has been distributed to Deliver 0 #0: BroadcastFilter{12c9c23 1000/u-1 ReceiverList{5b06152 1309 system/1000/u-1 local:4a651dd}} Deliver 0 #1: BroadcastFilter{672acd7 1000/u0 ReceiverList{5be3456 1780 com.android.systemui/1000/u0 remote:b33e71}} Deliver 0 #2: BroadcastFilter{f932daf 1000/u-1 ReceiverList{1ef518e 1780 com.android.systemui/1000/u-1 remote:35e2d89}} Deliver 0 #3: BroadcastFilter{d0d467b 1001/u0 ReceiverList{b4a5e0a 1996 com.android.phone/1001/u0 remote:65bee75}} Deliver 0 #4: BroadcastFilter{4081988 1002/u0 ReceiverList{661912b 2315 com.xiaomi.bluetooth/1002/u0 remote:34b657a}} Deliver 0 #5: BroadcastFilter{b6bda66 1000/u0 ReceiverList{73672c1 5261 com.miui.powerkeeper/1000/u0 remote:bc317a8}} // Skipped over to be Skipped over 0 #6: To be Skipped over. BroadcastFilter{ebabe72 10243/u0 ReceiverList{5596f7d 21465 com.smile.gifmaker/10243/u0 remote:96d61d4}} Skipped 0 #7: BroadcastFilter{f7d90ab 10243/u0 ReceiverList{261b2fa 21465 com.smile.gifmaker/10243/u0 remote:ef8c125}} Skipped 0 #8: BroadcastFilter{1f05292 10250/u0 ReceiverList{396401d 12339 com.tencent.mobileqq/10250/u0 remote:e8e90f4}} Skipped 0 #9: BroadcastFilter{d98737f 10250/u0 ReceiverList{469cc9e 12339 com.tencent.mobileqq/10250/u0 remote:b386ad9}} Skipped 0 #10: BroadcastFilter{4e1588 10250/u0 ReceiverList{851fd2b 29070 com.tencent.mobileqq:tool/10250/u0 remote:64a017a}}Copy the code
- Dumpsys Activity broadcast-stats: Indicates broadcast statistics
Android. Intent. Action. DROPBOX_ENTRY_ADDED: Number received: 0, skipped: 302 / / distribute 0 times, jump over 302 times the Total dispatch time: Package Android: 151 times Bg Check Violation com.google.andro.gms: + 24S731ms, Max: + 13S538ms // Total distribution time, maximum distribution time Package Android: 151 times Bg Check Violation com.google.andro.gms: 302 timesCopy the code
Flags in common intents
- FLAG_RECEIVER_REGISTERED_ONLY
Indicates that only the dynamically registered receiver is allowed to receive broadcasts. This prevents some system broadcasts (such as TIME_TICK) from holding up the statically registered APP process. FLAG_RECEIVER_REPLACE_PENDING If there are identical broadcasts that are not processed in the broadcast queue, the broadcasts are replaced directly and distributed in disorder. 3. The broadcast will be added to the foreground broadcast queue.
Some properties in AMS
// Registered dynamic broadcast receiver. Receiver IBinder is key and ReceiverList is value. ReceiverList inherits from ArrayList<BroadcastFilter> Final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>(); // Record the resolver that registers the broadcast receiver, Broadcast receivers can be queried according to IntentResolver<BroadcastFilter. BroadcastFilter> mReceiverResolver = new IntentResolver<BroadcastFilter, BroadcastFilter>();Copy the code
Properties of BroadcastRecord
int state; Idle final int[] delivery; // Final List receivers; // Broadcast receivers include statically registered ResolveInfo and dynamically registered BroadcastFilter int nextReceiver; // The index of the next broadcast receiver to be processed, corresponding to the index of receivers IIntentReceiver resultTo; // Long enqueueClockTime, the last receiver specified for an ordered broadcast; // Long dispatchTime; // Long receiverTime; // Start time to send broadcast to app, used to calculate anR timeout period long finishTime; // End the broadcast time IBinder receiver; / / receiver is currently processing (ReceiverDispatcher InnerReceiver), orderly broadcast and the registration of the static assignmentCopy the code
Some properties of ResolveInfo
public int priority; Public int preferredOrder; // Preference priority public int match; // System evaluation activity matches IntentFilter. public int specificIndex = -1; / / only if by queryIntentActivityOptions (the ComponentName, Intent [], Intent, int) returns Settings, this to tell you the result from which a given specific Intent. public boolean isDefault; // This filter specifies intent.category_default, which means it will be treated as the default action the user can perform on this data.Copy the code
State of broadcast
static final int IDLE = 0; Static final int APP_RECEIVE = 1; // Broadcast is being sent to the APP process. Static receiver static final int CALL_IN_RECEIVE = 2; // Indicates that broadcast is being sent to app process, orderly broadcast, dynamic receiver static final int CALL_DONE_RECEIVE = 3; Static final int WAITING_SERVICES = 4; // Static final int WAITING_SERVICES = 4; // Wait for the background service to startCopy the code
Processing status of the broadcast receiver
static final int DELIVERY_PENDING = 0; Static final int DELIVERY_DELIVERED = 1; To be skipped static final int DELIVERY_SKIPPED = 2; to be skipped lightly. Static final int DELIVERY_TIMEOUT = 3; static final int DELIVERY_TIMEOUT = 3; // Indicates that the packet is sent to the APP. The packet is not finished due to timeoutCopy the code
A situation in which a broadcast is not processed
In fact, there are many different situations in which broadcasts are not processed, and here are just some of the common ones.
The receiver does not declare the specified broadcast permission
W/BroadcastQueue: Permission Denial: receiving Intent { act=android.intent.action.ORDER_BROADCAST flg=0x10 } to com.example.myapplication/com.example.receive.MyReceiver requires com.android.permission.ORDER_PERMISSION due to sender com.example.testapplication (uid 10255)
In BroadcastQueue deliverToRegisteredReceiverLocked (dynamic registration) or processNextBroadcastLocked register (static) method, to check whether the receiver has broadcast request permissions, if do not have, The broadcast will be skipped and distributed to the APP.
if (! skip && r.requiredPermissions ! = null && r.requiredPermissions.length > 0) { for (int i = 0; i < r.requiredPermissions.length; i++) { String requiredPermission = r.requiredPermissions[i]; int perm = mService.checkComponentPermission(requiredPermission, filter.receiverList.pid, filter.receiverList.uid, -1, true); if (perm ! = PackageManager.PERMISSION_GRANTED) { Slog.w(TAG, "Permission Denial: receiving " + r.intent.toString() + " to " + filter.receiverList.app + " (pid=" + filter.receiverList.pid + ", uid=" + filter.receiverList.uid + ")" + " requires " + requiredPermission + " due to sender " + r.callerPackage + " (uid " + r.callingUid + ")"); skip = true; break; }Copy the code
Android 8.0 restrictions on implicit broadcasting
W BroadcastQueue: Background execution not allowed: receiving Intent { act=android.intent.action.PACKAGE_RESTARTED dat=package:com.android.soundrecorder flg=0x10 (has extras) } to com.xiaomi.misubscreenui/.receiver.LightDeviceStatusReceiver
Restrict broadcast distribution in the following two cases
- FLAG_RECEIVER_EXCLUDE_BACKGROUND was added to the Intent
- No FLAG_RECEIVER_INCLUDE_BACKGROUND flag is implicit in the Intent
FLAG_RECEIVER_INCLUDE_BACKGROUND Scenario added
The following implicit broadcasts are also received by those registered in the background manifest file
- ACTION_BOOT_COMPLETED
@BroadcastBehavior(includeBackground = true)
public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
Copy the code
- Intents in the allow-implicit-broadcast list are added to broadcastIntentLocked
if (action ! = null) { if (getBackgroundLaunchBroadcasts().contains(action)) { intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); }Copy the code
20 <! -- Broadcast actions that are currently exempted from O+ background 21 delivery restrictions. --> 22 <allow-implicit-broadcast action="android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED" /> 23 <allow-implicit-broadcast action="android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED" /> 24 <allow-implicit-broadcast action="android.intent.action.DATA_SMS_RECEIVED" /> 25 <allow-implicit-broadcast action="android.intent.action.MEDIA_SCANNER_SCAN_FILE" /> 26 <allow-implicit-broadcast action="android.intent.action.PACKAGE_CHANGED" /> 27 <allow-implicit-broadcast action="android.intent.action.SIM_STATE_CHANGED" /> 28 <allow-implicit-broadcast action="android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION" /> 29 <allow-implicit-broadcast action="android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION" /> 30 <allow-implicit-broadcast action="android.provider.Telephony.SECRET_CODE" /> 31 <allow-implicit-broadcast action="android.provider.Telephony.SMS_CB_RECEIVED" /> 32 <allow-implicit-broadcast action="android.provider.Telephony.SMS_DELIVER" /> 33 <allow-implicit-broadcast action="android.provider.Telephony.SMS_RECEIVED" /> 34 <allow-implicit-broadcast action="android.provider.Telephony.SMS_REJECTED" /> 35 <allow-implicit-broadcast action="android.provider.Telephony.WAP_PUSH_DELIVER" /> 36 <allow-implicit-broadcast action="android.provider.Telephony.WAP_PUSH_RECEIVED" /> 37 <allow-implicit-broadcast action="android.telephony.action.CARRIER_CONFIG_CHANGED" /> 38 <allow-implicit-broadcast action="android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED" /> 39 <allow-implicit-broadcast action="android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED" /> 40 <allow-implicit-broadcast action="android.telephony.action.MULTI_SIM_CONFIG_CHANGED" /> 41 <allow-implicit-broadcast action="android.telephony.action.SECRET_CODE" /> 42 <allow-implicit-broadcast action="android.telephony.action.SIM_APPLICATION_STATE_CHANGED" /> 43 <allow-implicit-broadcast action="android.telephony.action.SIM_CARD_STATE_CHANGED" /> 44 <allow-implicit-broadcast action="android.telephony.action.SIM_SLOT_STATUS_CHANGED" />Copy the code
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj, boolean parallelOnce) { ..... boolean skip = false; if (! The skip) {/ / check the start of the current app permissions final int charges. = mService getAppStartModeLocked (uid, info. ActivityInfo. ApplicationInfo. info.activityInfo.packageName, info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false, false, r.callerPackage); if (allowed ! = ActivityManager.APP_START_MODE_NORMAL) { if (allowed == ActivityManager.APP_START_MODE_DISABLED) { skip = true; // 1. FLAG_RECEIVER_EXCLUDE_BACKGROUND , 2. Else if (((r.inten.getFlags ()& Intent.flag_receiver_exclude_background)! = 0) || (r.intent.getComponent() == null && r.intent.getPackage() == null && ((r.intent.getFlags() & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0) && ! isSignaturePerm(r.requiredPermissions))) { mService.addBackgroundCheckViolationLocked(r.intent.getAction(), component.getPackageName()); Slog.w(TAG, "Background execution not allowed: receiving " + r.intent + " to " + component.flattenToShortString()); skip = true; }}}}Copy the code
Process Crashes frequently
W BroadcastQueue: Unable to launch app com.bsp.catchlog/1000 for broadcast Intent { act=android.provider.Telephony.SECRET_CODE dat=android_secret_code://284 flg=0x1400010 }: process is bad
AppErrors determines whether to mark the current process as bad when processing a current crash.
boolean handleAppCrashLocked(ProcessRecord app, String reason, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { ....... if (crashTime ! = null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) { Slog.w(TAG, "Process " + app.info.processName + " has crashed too many times: killing!" ); EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH, app.userId, app.info.processName, app.uid); mService.mAtmInternal.onHandleAppCrash(app.getWindowProcessController()); if (! app.isPersistent()) { EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.userId, app.uid, app.info.processName); if (! app.isolated) { mBadProcesses.put(app.info.processName, app.uid, new BadProcessInfo(now, shortMsg, longMsg, stackTrace)); mProcessCrashTimes.remove(app.info.processName, app.uid); } app.bad = true; app.removed = true; . }Copy the code
When the process is started, startProcessLocked of ProcessList checks if the background is started and the process is bad, and returns NULL, terminating the process
ProcessRecord app; if (! isolated) { app = getProcessRecordLocked(processName, info.uid, keepIfLarge); if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) ! = 0) { if (mService.mAppErrors.isBadProcessLocked(info)) { return null; }}Copy the code
In BroadcastQueue processNextBroadcastLocked does not exist in the process to create the process if it fails, will print the above the line of the log
if ((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, // MIUI MOD // (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) ! = 0, false, false)) (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) ! = 0, false, false, r.callerPackage)) == null) { // Ah, this recipient is unavailable. Finish it if necessary, // and mark the broadcast record as ready for the next. Slog.w(TAG, "Unable to launch app " + info.activityInfo.applicationInfo.packageName + "/" + receiverUid + " for broadcast " + r.intent + ": process is bad"); logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false); scheduleBroadcastsLocked(); r.state = BroadcastRecord.IDLE; return; }Copy the code
“Asked the radio’s three thousand
- When are receivers for ordered broadcasts sorted?
- Are the enqueueing and distribution processes for broadcasts synchronous or asynchronous?
- Does a statically registered receiver (ordered & unordered) correspond to an ordered broadcast queue or an unordered (parallel) broadcast queue?
- What are the states of broadcast? What do they stand for?
- What are the states of receiver and what do they represent?
- What timeout logic is involved in broadcasting?
- How many broadcast queues does the system have?
- How to send an ordered broadcast? Sticky radio? Reception announcements?
- Android O has added background launch restrictions. What are the main restrictions?
- Under what circumstances are sent broadcasts not enqueued?
- What is the priority of a process that is pulled up through a broadcast Receiver?
- How can I use log to check whether broadcast distribution times out? And whether the broadcast is sent to the corresponding receiver? Distribution status?
- If log is used to check whether the broadcast is orderly broadcast? Static registration?
- Which broadcast enjoys the total distribution timeout exemption?
- What implicit broadcasts can be sent to background processes?
- By what can ordered broadcast transmit data? What about out-of-order broadcasts?
- When will the resultTo (final receiver) of the ordered broadcast be distributed?
- What are the restrictions on sending protected broadcasts?
- What are the restrictions on sending sticky broadcasts?
- How can broadcast only be sent to dynamically registered receivers?
- When a static broadcast is sent, the process does not exist. What can I do?
- How to obtain static receivers before broadcasting into queue? How do I get dynamic receivers?