1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.am;
18 
19 import static android.app.AppProtoEnums.BROADCAST_TYPE_ALARM;
20 import static android.app.AppProtoEnums.BROADCAST_TYPE_BACKGROUND;
21 import static android.app.AppProtoEnums.BROADCAST_TYPE_DEFERRABLE_UNTIL_ACTIVE;
22 import static android.app.AppProtoEnums.BROADCAST_TYPE_FOREGROUND;
23 import static android.app.AppProtoEnums.BROADCAST_TYPE_INITIAL_STICKY;
24 import static android.app.AppProtoEnums.BROADCAST_TYPE_INTERACTIVE;
25 import static android.app.AppProtoEnums.BROADCAST_TYPE_NONE;
26 import static android.app.AppProtoEnums.BROADCAST_TYPE_ORDERED;
27 import static android.app.AppProtoEnums.BROADCAST_TYPE_PRIORITIZED;
28 import static android.app.AppProtoEnums.BROADCAST_TYPE_PUSH_MESSAGE;
29 import static android.app.AppProtoEnums.BROADCAST_TYPE_PUSH_MESSAGE_OVER_QUOTA;
30 import static android.app.AppProtoEnums.BROADCAST_TYPE_RESULT_TO;
31 import static android.app.AppProtoEnums.BROADCAST_TYPE_STICKY;
32 
33 import android.annotation.CheckResult;
34 import android.annotation.CurrentTimeMillisLong;
35 import android.annotation.ElapsedRealtimeLong;
36 import android.annotation.IntDef;
37 import android.annotation.NonNull;
38 import android.annotation.Nullable;
39 import android.annotation.UptimeMillisLong;
40 import android.app.ActivityManager.ProcessState;
41 import android.app.AppOpsManager;
42 import android.app.BackgroundStartPrivileges;
43 import android.app.BroadcastOptions;
44 import android.app.BroadcastOptions.DeliveryGroupPolicy;
45 import android.content.ComponentName;
46 import android.content.IIntentReceiver;
47 import android.content.Intent;
48 import android.content.IntentFilter;
49 import android.content.pm.ActivityInfo;
50 import android.content.pm.ResolveInfo;
51 import android.os.Binder;
52 import android.os.Bundle;
53 import android.os.SystemClock;
54 import android.os.UserHandle;
55 import android.util.ArrayMap;
56 import android.util.PrintWriterPrinter;
57 import android.util.TimeUtils;
58 import android.util.proto.ProtoOutputStream;
59 
60 import com.android.internal.annotations.VisibleForTesting;
61 
62 import dalvik.annotation.optimization.NeverCompile;
63 
64 import java.io.PrintWriter;
65 import java.lang.annotation.Retention;
66 import java.lang.annotation.RetentionPolicy;
67 import java.text.SimpleDateFormat;
68 import java.util.Arrays;
69 import java.util.Date;
70 import java.util.List;
71 import java.util.Objects;
72 import java.util.Set;
73 import java.util.function.BiFunction;
74 
75 /**
76  * An active intent broadcast.
77  */
78 final class BroadcastRecord extends Binder {
79     final @NonNull Intent intent;    // the original intent that generated us
80     final @Nullable ComponentName targetComp; // original component name set on the intent
81     final @Nullable ProcessRecord callerApp; // process that sent this
82     final @Nullable String callerPackage; // who sent this
83     final @Nullable String callerFeatureId; // which feature in the package sent this
84     final int callingPid;   // the pid of who sent this
85     final int callingUid;   // the uid of who sent this
86     final @ProcessState int callerProcState; // Procstate of the caller process at enqueue time.
87 
88     final int originalStickyCallingUid;
89             // if this is a sticky broadcast, the Uid of the original sender
90     final boolean callerInstantApp; // caller is an Instant App?
91     final boolean callerInstrumented; // caller is being instrumented?
92     final boolean ordered;  // serialize the send to receivers?
93     final boolean sticky;   // originated from existing sticky data?
94     final boolean alarm;    // originated from an alarm triggering?
95     final boolean pushMessage; // originated from a push message?
96     final boolean pushMessageOverQuota; // originated from a push message which was over quota?
97     final boolean interactive; // originated from user interaction?
98     final boolean initialSticky; // initial broadcast from register to sticky?
99     final boolean prioritized; // contains more than one priority tranche
100     final boolean deferUntilActive; // infinitely deferrable broadcast
101     final boolean shareIdentity;  // whether the broadcaster's identity should be shared
102     final boolean urgent;    // has been classified as "urgent"
103     final int userId;       // user id this broadcast was for
104     final @Nullable String resolvedType; // the resolved data type
105     final @Nullable String[] requiredPermissions; // permissions the caller has required
106     final @Nullable String[] excludedPermissions; // permissions to exclude
107     final @Nullable String[] excludedPackages; // packages to exclude
108     final int appOp;        // an app op that is associated with this broadcast
109     final @Nullable BroadcastOptions options; // BroadcastOptions supplied by caller
110     final @NonNull List<Object> receivers;   // contains BroadcastFilter and ResolveInfo
111     final @DeliveryState int[] delivery;   // delivery state of each receiver
112     final @NonNull String[] deliveryReasons; // reasons for delivery state of each receiver
113     final int[] blockedUntilBeyondCount; // blocked until count of each receiver
114     @Nullable ProcessRecord resultToApp; // who receives final result if non-null
115     @Nullable IIntentReceiver resultTo; // who receives final result if non-null
116     @UptimeMillisLong       long enqueueTime;        // when broadcast enqueued
117     @ElapsedRealtimeLong    long enqueueRealTime;    // when broadcast enqueued
118     @CurrentTimeMillisLong  long enqueueClockTime;   // when broadcast enqueued
119     // When broadcast is originally enqueued. Only used in case of replacing broadcasts
120     // with FLAG_RECEIVER_REPLACE_PENDING. If it is 0, then 'enqueueClockTime' is the original
121     // enqueue time.
122     @UptimeMillisLong       long originalEnqueueClockTime;
123     @UptimeMillisLong       long dispatchTime;       // when broadcast dispatch started
124     @ElapsedRealtimeLong    long dispatchRealTime;   // when broadcast dispatch started
125     @CurrentTimeMillisLong  long dispatchClockTime;  // when broadcast dispatch started
126     @UptimeMillisLong       long receiverTime;       // when receiver started for timeouts
127     @UptimeMillisLong       long finishTime;         // when broadcast finished
128     final @UptimeMillisLong long[] scheduledTime;    // when each receiver was scheduled
129     final @UptimeMillisLong long[] terminalTime;     // when each receiver was terminal
130     final boolean timeoutExempt;  // true if this broadcast is not subject to receiver timeouts
131     int resultCode;         // current result code value.
132     @Nullable String resultData;      // current result data value.
133     @Nullable Bundle resultExtras;    // current result extra data values.
134     boolean resultAbort;    // current result abortBroadcast value.
135     int nextReceiver;       // next receiver to be executed.
136     int state;
137     int anrCount;           // has this broadcast record hit any ANRs?
138     int manifestCount;      // number of manifest receivers dispatched.
139     int manifestSkipCount;  // number of manifest receivers skipped.
140     int terminalCount;      // number of receivers in terminal state.
141     int deferredCount;      // number of receivers in deferred state.
142     int beyondCount;        // high-water number of receivers we've moved beyond.
143     @Nullable BroadcastQueue queue;   // the outbound queue handling this broadcast
144 
145     // Determines the privileges the app's process has in regard to background starts.
146     final BackgroundStartPrivileges mBackgroundStartPrivileges;
147 
148     // Filter the intent extras by using the rules of the package visibility before broadcasting
149     // the intent to the receiver.
150     @Nullable
151     final BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver;
152 
153     // Cache of records that are "matching" this. Only used at the time of enqueuing this record
154     // into the queue.
155     @Nullable
156     private ArrayMap<BroadcastRecord, Boolean> mMatchingRecordsCache;
157 
158     private @Nullable String mCachedToString;
159     private @Nullable String mCachedToShortString;
160 
161     /**
162      * When enabled, assume that {@link UserHandle#isCore(int)} apps should
163      * treat {@link BroadcastOptions#DEFERRAL_POLICY_DEFAULT} as
164      * {@link BroadcastOptions#DEFERRAL_POLICY_UNTIL_ACTIVE}.
165      */
166     static boolean CORE_DEFER_UNTIL_ACTIVE = false;
167 
168     /** Empty immutable list of receivers */
169     static final List<Object> EMPTY_RECEIVERS = List.of();
170 
171     static final int IDLE = 0;
172     static final int APP_RECEIVE = 1;
173     static final int CALL_IN_RECEIVE = 2;
174     static final int CALL_DONE_RECEIVE = 3;
175     static final int WAITING_SERVICES = 4;
176 
177     /** Initial state: waiting to run in future */
178     static final int DELIVERY_PENDING = 0;
179     /** Terminal state: finished successfully */
180     static final int DELIVERY_DELIVERED = 1;
181     /** Terminal state: skipped due to internal policy */
182     static final int DELIVERY_SKIPPED = 2;
183     /** Terminal state: timed out during attempted delivery */
184     static final int DELIVERY_TIMEOUT = 3;
185     /** Intermediate state: currently executing */
186     static final int DELIVERY_SCHEDULED = 4;
187     /** Terminal state: failure to dispatch */
188     static final int DELIVERY_FAILURE = 5;
189     /** Intermediate state: currently deferred while app is cached */
190     static final int DELIVERY_DEFERRED = 6;
191 
192     @IntDef(flag = false, prefix = { "DELIVERY_" }, value = {
193             DELIVERY_PENDING,
194             DELIVERY_DELIVERED,
195             DELIVERY_SKIPPED,
196             DELIVERY_TIMEOUT,
197             DELIVERY_SCHEDULED,
198             DELIVERY_FAILURE,
199             DELIVERY_DEFERRED,
200     })
201     @Retention(RetentionPolicy.SOURCE)
202     public @interface DeliveryState {}
203 
deliveryStateToString(@eliveryState int deliveryState)204     static @NonNull String deliveryStateToString(@DeliveryState int deliveryState) {
205         switch (deliveryState) {
206             case DELIVERY_PENDING: return "PENDING";
207             case DELIVERY_DELIVERED: return "DELIVERED";
208             case DELIVERY_SKIPPED: return "SKIPPED";
209             case DELIVERY_TIMEOUT: return "TIMEOUT";
210             case DELIVERY_SCHEDULED: return "SCHEDULED";
211             case DELIVERY_FAILURE: return "FAILURE";
212             case DELIVERY_DEFERRED: return "DEFERRED";
213             default: return Integer.toString(deliveryState);
214         }
215     }
216 
217     /**
218      * Return if the given delivery state is "terminal", where no additional
219      * delivery state changes will be made.
220      */
isDeliveryStateTerminal(@eliveryState int deliveryState)221     static boolean isDeliveryStateTerminal(@DeliveryState int deliveryState) {
222         switch (deliveryState) {
223             case DELIVERY_DELIVERED:
224             case DELIVERY_SKIPPED:
225             case DELIVERY_TIMEOUT:
226             case DELIVERY_FAILURE:
227                 return true;
228             default:
229                 return false;
230         }
231     }
232 
233     /**
234      * Return if the given delivery state is "beyond", which means that we've
235      * moved beyond this receiver, and future receivers are now unblocked.
236      */
isDeliveryStateBeyond(@eliveryState int deliveryState)237     static boolean isDeliveryStateBeyond(@DeliveryState int deliveryState) {
238         switch (deliveryState) {
239             case DELIVERY_DELIVERED:
240             case DELIVERY_SKIPPED:
241             case DELIVERY_TIMEOUT:
242             case DELIVERY_FAILURE:
243             case DELIVERY_DEFERRED:
244                 return true;
245             default:
246                 return false;
247         }
248     }
249 
250     /**
251      * Return true if this receiver should be assumed to have been delivered.
252      */
isAssumedDelivered(int index)253     boolean isAssumedDelivered(int index) {
254         return (receivers.get(index) instanceof BroadcastFilter) && !ordered
255                 && (resultTo == null);
256     }
257 
258     ProcessRecord curApp;       // hosting application of current receiver.
259     ComponentName curComponent; // the receiver class that is currently running.
260     ActivityInfo curReceiver;   // the manifest receiver that is currently running.
261     BroadcastFilter curFilter;  // the registered receiver currently running.
262     Bundle curFilteredExtras;   // the bundle that has been filtered by the package visibility rules
263 
264     @NeverCompile
dump(PrintWriter pw, String prefix, SimpleDateFormat sdf)265     void dump(PrintWriter pw, String prefix, SimpleDateFormat sdf) {
266         final long now = SystemClock.uptimeMillis();
267 
268         pw.print(prefix); pw.print(this); pw.print(" to user "); pw.println(userId);
269         pw.print(prefix); pw.println(intent.toInsecureString());
270         if (targetComp != null && targetComp != intent.getComponent()) {
271             pw.print(prefix); pw.print("  targetComp: "); pw.println(targetComp.toShortString());
272         }
273         Bundle bundle = intent.getExtras();
274         if (bundle != null) {
275             pw.print(prefix); pw.print("  extras: "); pw.println(bundle.toString());
276         }
277         pw.print(prefix); pw.print("caller="); pw.print(callerPackage); pw.print(" ");
278                 pw.print(callerApp != null ? callerApp.toShortString() : "null");
279                 pw.print(" pid="); pw.print(callingPid);
280                 pw.print(" uid="); pw.println(callingUid);
281         if ((requiredPermissions != null && requiredPermissions.length > 0)
282                 || appOp != AppOpsManager.OP_NONE) {
283             pw.print(prefix); pw.print("requiredPermissions=");
284             pw.print(Arrays.toString(requiredPermissions));
285             pw.print("  appOp="); pw.println(appOp);
286         }
287         if (excludedPermissions != null && excludedPermissions.length > 0) {
288             pw.print(prefix); pw.print("excludedPermissions=");
289             pw.print(Arrays.toString(excludedPermissions));
290         }
291         if (excludedPackages != null && excludedPackages.length > 0) {
292             pw.print(prefix); pw.print("excludedPackages=");
293             pw.print(Arrays.toString(excludedPackages));
294         }
295         if (options != null) {
296             pw.print(prefix); pw.print("options="); pw.println(options.toBundle());
297         }
298         pw.print(prefix); pw.print("enqueueClockTime=");
299                 pw.print(sdf.format(new Date(enqueueClockTime)));
300                 pw.print(" dispatchClockTime=");
301                 pw.print(sdf.format(new Date(dispatchClockTime)));
302         if (originalEnqueueClockTime > 0) {
303             pw.print(" originalEnqueueClockTime=");
304             pw.print(sdf.format(new Date(originalEnqueueClockTime)));
305         }
306         pw.println();
307         pw.print(prefix); pw.print("dispatchTime=");
308                 TimeUtils.formatDuration(dispatchTime, now, pw);
309                 pw.print(" (");
310                 TimeUtils.formatDuration(dispatchTime - enqueueTime, pw);
311                 pw.print(" since enq)");
312         if (finishTime != 0) {
313             pw.print(" finishTime="); TimeUtils.formatDuration(finishTime, now, pw);
314             pw.print(" (");
315             TimeUtils.formatDuration(finishTime-dispatchTime, pw);
316             pw.print(" since disp)");
317         } else {
318             pw.print(" receiverTime="); TimeUtils.formatDuration(receiverTime, now, pw);
319         }
320         pw.println("");
321         if (anrCount != 0) {
322             pw.print(prefix); pw.print("anrCount="); pw.println(anrCount);
323         }
324         if (resultTo != null || resultCode != -1 || resultData != null) {
325             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
326                     pw.print(" resultCode="); pw.print(resultCode);
327                     pw.print(" resultData="); pw.println(resultData);
328         }
329         if (resultExtras != null) {
330             pw.print(prefix); pw.print("resultExtras="); pw.println(resultExtras);
331         }
332         if (resultAbort || ordered || sticky || initialSticky) {
333             pw.print(prefix); pw.print("resultAbort="); pw.print(resultAbort);
334                     pw.print(" ordered="); pw.print(ordered);
335                     pw.print(" sticky="); pw.print(sticky);
336                     pw.print(" initialSticky="); pw.print(initialSticky);
337                     pw.print(" originalStickyCallingUid="); pw.println(originalStickyCallingUid);
338         }
339         if (nextReceiver != 0) {
340             pw.print(prefix); pw.print("nextReceiver="); pw.println(nextReceiver);
341         }
342         if (curFilter != null) {
343             pw.print(prefix); pw.print("curFilter="); pw.println(curFilter);
344         }
345         if (curReceiver != null) {
346             pw.print(prefix); pw.print("curReceiver="); pw.println(curReceiver);
347         }
348         if (curApp != null) {
349             pw.print(prefix); pw.print("curApp="); pw.println(curApp);
350             pw.print(prefix); pw.print("curComponent=");
351                     pw.println((curComponent != null ? curComponent.toShortString() : "--"));
352             if (curReceiver != null && curReceiver.applicationInfo != null) {
353                 pw.print(prefix); pw.print("curSourceDir=");
354                         pw.println(curReceiver.applicationInfo.sourceDir);
355             }
356         }
357         if (curFilteredExtras != null) {
358             pw.print(" filtered extras: "); pw.println(curFilteredExtras);
359         }
360         if (state != IDLE) {
361             String stateStr = " (?)";
362             switch (state) {
363                 case APP_RECEIVE:       stateStr=" (APP_RECEIVE)"; break;
364                 case CALL_IN_RECEIVE:   stateStr=" (CALL_IN_RECEIVE)"; break;
365                 case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_RECEIVE)"; break;
366                 case WAITING_SERVICES:  stateStr=" (WAITING_SERVICES)"; break;
367             }
368             pw.print(prefix); pw.print("state="); pw.print(state); pw.println(stateStr);
369         }
370         pw.print(prefix); pw.print("terminalCount="); pw.println(terminalCount);
371         final int N = receivers != null ? receivers.size() : 0;
372         String p2 = prefix + "  ";
373         PrintWriterPrinter printer = new PrintWriterPrinter(pw);
374         for (int i = 0; i < N; i++) {
375             Object o = receivers.get(i);
376             pw.print(prefix);
377             pw.print(deliveryStateToString(delivery[i]));
378             pw.print(' ');
379             if (scheduledTime[i] != 0) {
380                 pw.print("scheduled ");
381                 TimeUtils.formatDuration(scheduledTime[i] - enqueueTime, pw);
382                 pw.print(' ');
383             }
384             if (terminalTime[i] != 0) {
385                 pw.print("terminal ");
386                 TimeUtils.formatDuration(terminalTime[i] - scheduledTime[i], pw);
387                 pw.print(' ');
388             }
389             pw.print("("); pw.print(blockedUntilBeyondCount[i]); pw.print(") ");
390             pw.print("#"); pw.print(i); pw.print(": ");
391             if (o instanceof BroadcastFilter) {
392                 pw.println(o);
393                 ((BroadcastFilter) o).dumpBrief(pw, p2);
394             } else if (o instanceof ResolveInfo) {
395                 pw.println("(manifest)");
396                 ((ResolveInfo) o).dump(printer, p2, 0);
397             } else {
398                 pw.println(o);
399             }
400             if (deliveryReasons[i] != null) {
401                 pw.print(p2); pw.print("reason: "); pw.println(deliveryReasons[i]);
402             }
403         }
404     }
405 
BroadcastRecord(BroadcastQueue queue, Intent intent, ProcessRecord callerApp, String callerPackage, @Nullable String callerFeatureId, int callingPid, int callingUid, boolean callerInstantApp, String resolvedType, String[] requiredPermissions, String[] excludedPermissions, String[] excludedPackages, int appOp, BroadcastOptions options, List receivers, ProcessRecord resultToApp, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, boolean serialized, boolean sticky, boolean initialSticky, int userId, @NonNull BackgroundStartPrivileges backgroundStartPrivileges, boolean timeoutExempt, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver, int callerAppProcessState)406     BroadcastRecord(BroadcastQueue queue,
407             Intent intent, ProcessRecord callerApp, String callerPackage,
408             @Nullable String callerFeatureId, int callingPid, int callingUid,
409             boolean callerInstantApp, String resolvedType,
410             String[] requiredPermissions, String[] excludedPermissions,
411             String[] excludedPackages, int appOp,
412             BroadcastOptions options, List receivers,
413             ProcessRecord resultToApp, IIntentReceiver resultTo, int resultCode,
414             String resultData, Bundle resultExtras, boolean serialized, boolean sticky,
415             boolean initialSticky, int userId,
416             @NonNull BackgroundStartPrivileges backgroundStartPrivileges,
417             boolean timeoutExempt,
418             @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
419             int callerAppProcessState) {
420         this(queue, intent, callerApp, callerPackage, callerFeatureId, callingPid,
421                 callingUid, callerInstantApp, resolvedType, requiredPermissions,
422                 excludedPermissions, excludedPackages, appOp, options, receivers, resultToApp,
423                 resultTo, resultCode, resultData, resultExtras, serialized, sticky,
424                 initialSticky, userId, -1, backgroundStartPrivileges, timeoutExempt,
425                 filterExtrasForReceiver, callerAppProcessState);
426     }
427 
BroadcastRecord(BroadcastQueue _queue, Intent _intent, ProcessRecord _callerApp, String _callerPackage, @Nullable String _callerFeatureId, int _callingPid, int _callingUid, boolean _callerInstantApp, String _resolvedType, String[] _requiredPermissions, String[] _excludedPermissions, String[] _excludedPackages, int _appOp, BroadcastOptions _options, List _receivers, ProcessRecord _resultToApp, IIntentReceiver _resultTo, int _resultCode, String _resultData, Bundle _resultExtras, boolean _serialized, boolean _sticky, boolean _initialSticky, int _userId, int originalStickyCallingUid, @NonNull BackgroundStartPrivileges backgroundStartPrivileges, boolean timeoutExempt, @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver, int callerAppProcessState)428     BroadcastRecord(BroadcastQueue _queue,
429             Intent _intent, ProcessRecord _callerApp, String _callerPackage,
430             @Nullable String _callerFeatureId, int _callingPid, int _callingUid,
431             boolean _callerInstantApp, String _resolvedType,
432             String[] _requiredPermissions, String[] _excludedPermissions,
433             String[] _excludedPackages, int _appOp,
434             BroadcastOptions _options, List _receivers,
435             ProcessRecord _resultToApp, IIntentReceiver _resultTo, int _resultCode,
436             String _resultData, Bundle _resultExtras, boolean _serialized, boolean _sticky,
437             boolean _initialSticky, int _userId, int originalStickyCallingUid,
438             @NonNull BackgroundStartPrivileges backgroundStartPrivileges,
439             boolean timeoutExempt,
440             @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
441             int callerAppProcessState) {
442         if (_intent == null) {
443             throw new NullPointerException("Can't construct with a null intent");
444         }
445         queue = _queue;
446         intent = Objects.requireNonNull(_intent);
447         targetComp = _intent.getComponent();
448         callerApp = _callerApp;
449         callerPackage = _callerPackage;
450         callerFeatureId = _callerFeatureId;
451         callingPid = _callingPid;
452         callingUid = _callingUid;
453         callerProcState = callerAppProcessState;
454         callerInstantApp = _callerInstantApp;
455         callerInstrumented = isCallerInstrumented(_callerApp, _callingUid);
456         resolvedType = _resolvedType;
457         requiredPermissions = _requiredPermissions;
458         excludedPermissions = _excludedPermissions;
459         excludedPackages = _excludedPackages;
460         appOp = _appOp;
461         options = _options;
462         receivers = (_receivers != null) ? _receivers : EMPTY_RECEIVERS;
463         delivery = new int[_receivers != null ? _receivers.size() : 0];
464         deliveryReasons = new String[delivery.length];
465         urgent = calculateUrgent(_intent, _options);
466         deferUntilActive = calculateDeferUntilActive(_callingUid,
467                 _options, _resultTo, _serialized, urgent);
468         blockedUntilBeyondCount = calculateBlockedUntilBeyondCount(receivers, _serialized);
469         scheduledTime = new long[delivery.length];
470         terminalTime = new long[delivery.length];
471         resultToApp = _resultToApp;
472         resultTo = _resultTo;
473         resultCode = _resultCode;
474         resultData = _resultData;
475         resultExtras = _resultExtras;
476         ordered = _serialized;
477         sticky = _sticky;
478         initialSticky = _initialSticky;
479         prioritized = isPrioritized(blockedUntilBeyondCount, _serialized);
480         userId = _userId;
481         nextReceiver = 0;
482         state = IDLE;
483         mBackgroundStartPrivileges = backgroundStartPrivileges;
484         this.timeoutExempt = timeoutExempt;
485         alarm = options != null && options.isAlarmBroadcast();
486         pushMessage = options != null && options.isPushMessagingBroadcast();
487         pushMessageOverQuota = options != null && options.isPushMessagingOverQuotaBroadcast();
488         interactive = options != null && options.isInteractive();
489         shareIdentity = options != null && options.isShareIdentityEnabled();
490         this.filterExtrasForReceiver = filterExtrasForReceiver;
491         this.originalStickyCallingUid = originalStickyCallingUid;
492     }
493 
494     /**
495      * Copy constructor which takes a different intent.
496      * Only used by {@link #maybeStripForHistory}.
497      */
BroadcastRecord(BroadcastRecord from, Intent newIntent)498     private BroadcastRecord(BroadcastRecord from, Intent newIntent) {
499         intent = Objects.requireNonNull(newIntent);
500         targetComp = newIntent.getComponent();
501 
502         callerApp = from.callerApp;
503         callerPackage = from.callerPackage;
504         callerFeatureId = from.callerFeatureId;
505         callingPid = from.callingPid;
506         callingUid = from.callingUid;
507         callerProcState = from.callerProcState;
508         callerInstantApp = from.callerInstantApp;
509         callerInstrumented = from.callerInstrumented;
510         ordered = from.ordered;
511         sticky = from.sticky;
512         initialSticky = from.initialSticky;
513         prioritized = from.prioritized;
514         userId = from.userId;
515         resolvedType = from.resolvedType;
516         requiredPermissions = from.requiredPermissions;
517         excludedPermissions = from.excludedPermissions;
518         excludedPackages = from.excludedPackages;
519         appOp = from.appOp;
520         options = from.options;
521         receivers = from.receivers;
522         delivery = from.delivery;
523         deliveryReasons = from.deliveryReasons;
524         deferUntilActive = from.deferUntilActive;
525         blockedUntilBeyondCount = from.blockedUntilBeyondCount;
526         scheduledTime = from.scheduledTime;
527         terminalTime = from.terminalTime;
528         resultToApp = from.resultToApp;
529         resultTo = from.resultTo;
530         enqueueTime = from.enqueueTime;
531         enqueueRealTime = from.enqueueRealTime;
532         enqueueClockTime = from.enqueueClockTime;
533         dispatchTime = from.dispatchTime;
534         dispatchRealTime = from.dispatchRealTime;
535         dispatchClockTime = from.dispatchClockTime;
536         receiverTime = from.receiverTime;
537         finishTime = from.finishTime;
538         resultCode = from.resultCode;
539         resultData = from.resultData;
540         resultExtras = from.resultExtras;
541         resultAbort = from.resultAbort;
542         nextReceiver = from.nextReceiver;
543         state = from.state;
544         anrCount = from.anrCount;
545         manifestCount = from.manifestCount;
546         manifestSkipCount = from.manifestSkipCount;
547         queue = from.queue;
548         mBackgroundStartPrivileges = from.mBackgroundStartPrivileges;
549         timeoutExempt = from.timeoutExempt;
550         alarm = from.alarm;
551         pushMessage = from.pushMessage;
552         pushMessageOverQuota = from.pushMessageOverQuota;
553         interactive = from.interactive;
554         shareIdentity = from.shareIdentity;
555         urgent = from.urgent;
556         filterExtrasForReceiver = from.filterExtrasForReceiver;
557         originalStickyCallingUid = from.originalStickyCallingUid;
558     }
559 
560     /**
561      * Update the delivery state of the given {@link #receivers} index.
562      * Automatically updates any time measurements related to state changes.
563      *
564      * @return if {@link #beyondCount} changed due to this state transition,
565      *         indicating that other events may be unblocked.
566      */
567     @CheckResult
setDeliveryState(int index, @DeliveryState int newDeliveryState, @NonNull String reason)568     boolean setDeliveryState(int index, @DeliveryState int newDeliveryState,
569             @NonNull String reason) {
570         final int oldDeliveryState = delivery[index];
571         if (isDeliveryStateTerminal(oldDeliveryState)
572                 || newDeliveryState == oldDeliveryState) {
573             // We've already arrived in terminal or requested state, so leave
574             // any statistics and reasons intact from the first transition
575             return false;
576         }
577 
578         switch (oldDeliveryState) {
579             case DELIVERY_DEFERRED:
580                 deferredCount--;
581                 break;
582         }
583         switch (newDeliveryState) {
584             case DELIVERY_PENDING:
585                 scheduledTime[index] = 0;
586                 break;
587             case DELIVERY_SCHEDULED:
588                 scheduledTime[index] = SystemClock.uptimeMillis();
589                 break;
590             case DELIVERY_DEFERRED:
591                 deferredCount++;
592                 break;
593             case DELIVERY_DELIVERED:
594             case DELIVERY_SKIPPED:
595             case DELIVERY_TIMEOUT:
596             case DELIVERY_FAILURE:
597                 terminalTime[index] = SystemClock.uptimeMillis();
598                 terminalCount++;
599                 break;
600         }
601 
602         delivery[index] = newDeliveryState;
603         deliveryReasons[index] = reason;
604 
605         // If this state change might bring us to a new high-water mark, bring
606         // ourselves as high as we possibly can
607         final int oldBeyondCount = beyondCount;
608         if (index >= beyondCount) {
609             for (int i = beyondCount; i < delivery.length; i++) {
610                 if (isDeliveryStateBeyond(getDeliveryState(i))) {
611                     beyondCount = i + 1;
612                 } else {
613                     break;
614                 }
615             }
616         }
617         return (beyondCount != oldBeyondCount);
618     }
619 
getDeliveryState(int index)620     @DeliveryState int getDeliveryState(int index) {
621         return delivery[index];
622     }
623 
624     /**
625      * @return if the given {@link #receivers} index should be considered
626      *         blocked based on the current status of the overall broadcast.
627      */
isBlocked(int index)628     boolean isBlocked(int index) {
629         return (beyondCount < blockedUntilBeyondCount[index]);
630     }
631 
wasDeliveryAttempted(int index)632     boolean wasDeliveryAttempted(int index) {
633         final int deliveryState = getDeliveryState(index);
634         switch (deliveryState) {
635             case DELIVERY_DELIVERED:
636             case DELIVERY_TIMEOUT:
637             case DELIVERY_FAILURE:
638                 return true;
639             default:
640                 return false;
641         }
642     }
643 
copyEnqueueTimeFrom(@onNull BroadcastRecord replacedBroadcast)644     void copyEnqueueTimeFrom(@NonNull BroadcastRecord replacedBroadcast) {
645         originalEnqueueClockTime = enqueueClockTime;
646         enqueueTime = replacedBroadcast.enqueueTime;
647         enqueueRealTime = replacedBroadcast.enqueueRealTime;
648         enqueueClockTime = replacedBroadcast.enqueueClockTime;
649     }
650 
isForeground()651     boolean isForeground() {
652         return (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
653     }
654 
isReplacePending()655     boolean isReplacePending() {
656         return (intent.getFlags() & Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
657     }
658 
isNoAbort()659     boolean isNoAbort() {
660         return (intent.getFlags() & Intent.FLAG_RECEIVER_NO_ABORT) != 0;
661     }
662 
isOffload()663     boolean isOffload() {
664         return (intent.getFlags() & Intent.FLAG_RECEIVER_OFFLOAD) != 0;
665     }
666 
isDeferUntilActive()667     boolean isDeferUntilActive() {
668         return deferUntilActive;
669     }
670 
isUrgent()671     boolean isUrgent() {
672         return urgent;
673     }
674 
getHostingRecordTriggerType()675     @NonNull String getHostingRecordTriggerType() {
676         if (alarm) {
677             return HostingRecord.TRIGGER_TYPE_ALARM;
678         } else if (pushMessage) {
679             return HostingRecord.TRIGGER_TYPE_PUSH_MESSAGE;
680         } else if (pushMessageOverQuota) {
681             return HostingRecord.TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA;
682         }
683         return HostingRecord.TRIGGER_TYPE_UNKNOWN;
684     }
685 
686     /**
687      * Return an instance of {@link #intent} specialized for the given receiver.
688      * For example, this returns a new specialized instance if the extras need
689      * to be filtered, or a {@link ResolveInfo} needs to be configured.
690      *
691      * @return a specialized intent, otherwise {@code null} to indicate that the
692      *         broadcast should not be delivered to this receiver, typically due
693      *         to it being filtered away by {@link #filterExtrasForReceiver}.
694      */
getReceiverIntent(@onNull Object receiver)695     @Nullable Intent getReceiverIntent(@NonNull Object receiver) {
696         Intent newIntent = null;
697         if (filterExtrasForReceiver != null) {
698             final Bundle extras = intent.getExtras();
699             if (extras != null) {
700                 final int receiverUid = getReceiverUid(receiver);
701                 final Bundle filteredExtras = filterExtrasForReceiver.apply(receiverUid, extras);
702                 if (filteredExtras == null) {
703                     // Completely filtered; skip the broadcast!
704                     return null;
705                 } else {
706                     newIntent = new Intent(intent);
707                     newIntent.replaceExtras(filteredExtras);
708                 }
709             }
710         }
711         if (receiver instanceof ResolveInfo) {
712             if (newIntent == null) {
713                 newIntent = new Intent(intent);
714             }
715             newIntent.setComponent(((ResolveInfo) receiver).activityInfo.getComponentName());
716         }
717         return (newIntent != null) ? newIntent : intent;
718     }
719 
isCallerInstrumented(@ullable ProcessRecord callerApp, int callingUid)720     static boolean isCallerInstrumented(@Nullable ProcessRecord callerApp, int callingUid) {
721         switch (UserHandle.getAppId(callingUid)) {
722             case android.os.Process.ROOT_UID:
723             case android.os.Process.SHELL_UID:
724                 // Broadcasts sent via "shell" are typically invoked by test
725                 // suites, so we treat them as if the caller was instrumented
726                 return true;
727         }
728         return (callerApp != null) ? (callerApp.getActiveInstrumentation() != null) : false;
729     }
730 
731     /**
732      * Determine if the result of {@link #calculateBlockedUntilBeyondCount(List, boolean)}
733      * has prioritized tranches of receivers.
734      */
735     @VisibleForTesting
isPrioritized(@onNull int[] blockedUntilBeyondCount, boolean ordered)736     static boolean isPrioritized(@NonNull int[] blockedUntilBeyondCount,
737             boolean ordered) {
738         return !ordered && (blockedUntilBeyondCount.length > 0)
739                 && (blockedUntilBeyondCount[0] != -1);
740     }
741 
742     /**
743      * Calculate the {@link #beyondCount} that each receiver should be
744      * considered blocked until.
745      * <p>
746      * For example, in an ordered broadcast, receiver {@code N} is blocked until
747      * receiver {@code N-1} reaches a terminal or deferred state. Similarly, in
748      * a prioritized broadcast, receiver {@code N} is blocked until all
749      * receivers of a higher priority reach a terminal or deferred state.
750      * <p>
751      * When there are no beyond count constraints, the blocked value for each
752      * receiver is {@code -1}.
753      */
754     @VisibleForTesting
calculateBlockedUntilBeyondCount( @onNull List<Object> receivers, boolean ordered)755     static @NonNull int[] calculateBlockedUntilBeyondCount(
756             @NonNull List<Object> receivers, boolean ordered) {
757         final int N = receivers.size();
758         final int[] blockedUntilBeyondCount = new int[N];
759         int lastPriority = 0;
760         int lastPriorityIndex = 0;
761         for (int i = 0; i < N; i++) {
762             if (ordered) {
763                 // When sending an ordered broadcast, we need to block this
764                 // receiver until all previous receivers have terminated
765                 blockedUntilBeyondCount[i] = i;
766             } else {
767                 // When sending a prioritized broadcast, we only need to wait
768                 // for the previous tranche of receivers to be terminated
769                 final int thisPriority = getReceiverPriority(receivers.get(i));
770                 if ((i == 0) || (thisPriority != lastPriority)) {
771                     lastPriority = thisPriority;
772                     lastPriorityIndex = i;
773                     blockedUntilBeyondCount[i] = i;
774                 } else {
775                     blockedUntilBeyondCount[i] = lastPriorityIndex;
776                 }
777             }
778         }
779         // If the entire list is in the same priority tranche, mark as -1 to
780         // indicate that none of them need to wait
781         if (N > 0 && blockedUntilBeyondCount[N - 1] == 0) {
782             Arrays.fill(blockedUntilBeyondCount, -1);
783         }
784         return blockedUntilBeyondCount;
785     }
786 
getReceiverUid(@onNull Object receiver)787     static int getReceiverUid(@NonNull Object receiver) {
788         if (receiver instanceof BroadcastFilter) {
789             return ((BroadcastFilter) receiver).owningUid;
790         } else /* if (receiver instanceof ResolveInfo) */ {
791             return ((ResolveInfo) receiver).activityInfo.applicationInfo.uid;
792         }
793     }
794 
getReceiverProcessName(@onNull Object receiver)795     static @NonNull String getReceiverProcessName(@NonNull Object receiver) {
796         if (receiver instanceof BroadcastFilter) {
797             return ((BroadcastFilter) receiver).receiverList.app.processName;
798         } else /* if (receiver instanceof ResolveInfo) */ {
799             return ((ResolveInfo) receiver).activityInfo.processName;
800         }
801     }
802 
getReceiverPackageName(@onNull Object receiver)803     static @NonNull String getReceiverPackageName(@NonNull Object receiver) {
804         if (receiver instanceof BroadcastFilter) {
805             return ((BroadcastFilter) receiver).receiverList.app.info.packageName;
806         } else /* if (receiver instanceof ResolveInfo) */ {
807             return ((ResolveInfo) receiver).activityInfo.packageName;
808         }
809     }
810 
getReceiverClassName(@onNull Object receiver)811     static @Nullable String getReceiverClassName(@NonNull Object receiver) {
812         if (receiver instanceof BroadcastFilter) {
813             return ((BroadcastFilter) receiver).getReceiverClassName();
814         } else /* if (receiver instanceof ResolveInfo) */ {
815             return ((ResolveInfo) receiver).activityInfo.name;
816         }
817     }
818 
getReceiverPriority(@onNull Object receiver)819     static int getReceiverPriority(@NonNull Object receiver) {
820         if (receiver instanceof BroadcastFilter) {
821             return ((BroadcastFilter) receiver).getPriority();
822         } else /* if (receiver instanceof ResolveInfo) */ {
823             return ((ResolveInfo) receiver).priority;
824         }
825     }
826 
isReceiverEquals(@onNull Object a, @NonNull Object b)827     static boolean isReceiverEquals(@NonNull Object a, @NonNull Object b) {
828         if (a == b) {
829             return true;
830         } else if (a instanceof ResolveInfo && b instanceof ResolveInfo) {
831             final ResolveInfo infoA = (ResolveInfo) a;
832             final ResolveInfo infoB = (ResolveInfo) b;
833             return Objects.equals(infoA.activityInfo.packageName, infoB.activityInfo.packageName)
834                     && Objects.equals(infoA.activityInfo.name, infoB.activityInfo.name);
835         } else {
836             return false;
837         }
838     }
839 
840     /**
841      * Core policy determination about this broadcast's delivery prioritization
842      */
843     @VisibleForTesting
calculateUrgent(@onNull Intent intent, @Nullable BroadcastOptions options)844     static boolean calculateUrgent(@NonNull Intent intent, @Nullable BroadcastOptions options) {
845         // TODO: flags for controlling policy
846         // TODO: migrate alarm-prioritization flag to BroadcastConstants
847         if ((intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0) {
848             return true;
849         }
850         if (options != null) {
851             if (options.isInteractive()) {
852                 return true;
853             }
854             if (options.isAlarmBroadcast()) {
855                 return true;
856             }
857         }
858         return false;
859     }
860 
861     /**
862      * Resolve the requested {@link BroadcastOptions#setDeferralPolicy(int)}
863      * against this broadcast state to determine if it should be marked as
864      * "defer until active".
865      */
866     @VisibleForTesting
calculateDeferUntilActive(int callingUid, @Nullable BroadcastOptions options, @Nullable IIntentReceiver resultTo, boolean ordered, boolean urgent)867     static boolean calculateDeferUntilActive(int callingUid, @Nullable BroadcastOptions options,
868             @Nullable IIntentReceiver resultTo, boolean ordered, boolean urgent) {
869         // Ordered broadcasts can never be deferred until active
870         if (ordered) {
871             return false;
872         }
873 
874         // Unordered resultTo broadcasts are always deferred until active
875         if (!ordered && resultTo != null) {
876             return true;
877         }
878 
879         // Determine if a strong preference in either direction was expressed;
880         // a preference here overrides all remaining policies
881         if (options != null) {
882             switch (options.getDeferralPolicy()) {
883                 case BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE:
884                     return true;
885                 case BroadcastOptions.DEFERRAL_POLICY_NONE:
886                     return false;
887             }
888         }
889 
890         // Urgent broadcasts aren't deferred until active
891         if (urgent) {
892             return false;
893         }
894 
895         // Otherwise, choose a reasonable default
896         if (CORE_DEFER_UNTIL_ACTIVE && UserHandle.isCore(callingUid)) {
897             return true;
898         } else {
899             return false;
900         }
901     }
902 
calculateTypeForLogging()903     int calculateTypeForLogging() {
904         int type = BROADCAST_TYPE_NONE;
905         if (isForeground()) {
906             type |= BROADCAST_TYPE_FOREGROUND;
907         } else {
908             type |= BROADCAST_TYPE_BACKGROUND;
909         }
910         if (alarm) {
911             type |= BROADCAST_TYPE_ALARM;
912         }
913         if (interactive) {
914             type |= BROADCAST_TYPE_INTERACTIVE;
915         }
916         if (ordered) {
917             type |= BROADCAST_TYPE_ORDERED;
918         }
919         if (prioritized) {
920             type |= BROADCAST_TYPE_PRIORITIZED;
921         }
922         if (resultTo != null) {
923             type |= BROADCAST_TYPE_RESULT_TO;
924         }
925         if (deferUntilActive) {
926             type |= BROADCAST_TYPE_DEFERRABLE_UNTIL_ACTIVE;
927         }
928         if (pushMessage) {
929             type |= BROADCAST_TYPE_PUSH_MESSAGE;
930         }
931         if (pushMessageOverQuota) {
932             type |= BROADCAST_TYPE_PUSH_MESSAGE_OVER_QUOTA;
933         }
934         if (sticky) {
935             type |= BROADCAST_TYPE_STICKY;
936         }
937         if (initialSticky) {
938             type |= BROADCAST_TYPE_INITIAL_STICKY;
939         }
940         return type;
941     }
942 
maybeStripForHistory()943     public BroadcastRecord maybeStripForHistory() {
944         if (!intent.canStripForHistory()) {
945             return this;
946         }
947         return new BroadcastRecord(this, intent.maybeStripForHistory());
948     }
949 
950     @VisibleForTesting
cleanupDisabledPackageReceiversLocked( String packageName, Set<String> filterByClasses, int userId, boolean doit)951     boolean cleanupDisabledPackageReceiversLocked(
952             String packageName, Set<String> filterByClasses, int userId, boolean doit) {
953         if (receivers == null) {
954             return false;
955         }
956 
957         final boolean cleanupAllUsers = userId == UserHandle.USER_ALL;
958         final boolean sendToAllUsers = this.userId == UserHandle.USER_ALL;
959         if (this.userId != userId && !cleanupAllUsers && !sendToAllUsers) {
960             return false;
961         }
962 
963         boolean didSomething = false;
964         Object o;
965         for (int i = receivers.size() - 1; i >= 0; i--) {
966             o = receivers.get(i);
967             if (!(o instanceof ResolveInfo)) {
968                 continue;
969             }
970             ActivityInfo info = ((ResolveInfo)o).activityInfo;
971 
972             final boolean sameComponent = packageName == null
973                     || (info.applicationInfo.packageName.equals(packageName)
974                     && (filterByClasses == null || filterByClasses.contains(info.name)));
975             if (sameComponent && (cleanupAllUsers
976                     || UserHandle.getUserId(info.applicationInfo.uid) == userId)) {
977                 if (!doit) {
978                     return true;
979                 }
980                 didSomething = true;
981                 receivers.remove(i);
982                 if (i < nextReceiver) {
983                     nextReceiver--;
984                 }
985             }
986         }
987         nextReceiver = Math.min(nextReceiver, receivers.size());
988 
989         return didSomething;
990     }
991 
992     /**
993      * Apply special treatment to manifest receivers hosted by a singleton
994      * process, by re-targeting them at {@link UserHandle#USER_SYSTEM}.
995      */
applySingletonPolicy(@onNull ActivityManagerService service)996     void applySingletonPolicy(@NonNull ActivityManagerService service) {
997         if (receivers == null) return;
998         for (int i = 0; i < receivers.size(); i++) {
999             final Object receiver = receivers.get(i);
1000             if (receiver instanceof ResolveInfo) {
1001                 final ResolveInfo info = (ResolveInfo) receiver;
1002                 boolean isSingleton = false;
1003                 try {
1004                     isSingleton = service.isSingleton(info.activityInfo.processName,
1005                             info.activityInfo.applicationInfo,
1006                             info.activityInfo.name, info.activityInfo.flags);
1007                 } catch (SecurityException e) {
1008                     BroadcastQueue.logw(e.getMessage());
1009                 }
1010                 final int receiverUid = info.activityInfo.applicationInfo.uid;
1011                 if (callingUid != android.os.Process.SYSTEM_UID && isSingleton
1012                         && service.isValidSingletonCall(callingUid, receiverUid)) {
1013                     info.activityInfo = service.getActivityInfoForUser(info.activityInfo,
1014                             UserHandle.USER_SYSTEM);
1015                 }
1016             }
1017         }
1018     }
1019 
containsReceiver(@onNull Object receiver)1020     boolean containsReceiver(@NonNull Object receiver) {
1021         for (int i = receivers.size() - 1; i >= 0; --i) {
1022             if (isReceiverEquals(receiver, receivers.get(i))) {
1023                 return true;
1024             }
1025         }
1026         return false;
1027     }
1028 
containsAllReceivers(@onNull List<Object> otherReceivers)1029     boolean containsAllReceivers(@NonNull List<Object> otherReceivers) {
1030         for (int i = otherReceivers.size() - 1; i >= 0; --i) {
1031             if (!containsReceiver(otherReceivers.get(i))) {
1032                 return false;
1033             }
1034         }
1035         return true;
1036     }
1037 
1038     @DeliveryGroupPolicy
getDeliveryGroupPolicy()1039     int getDeliveryGroupPolicy() {
1040         return (options != null) ? options.getDeliveryGroupPolicy()
1041                 : BroadcastOptions.DELIVERY_GROUP_POLICY_ALL;
1042     }
1043 
matchesDeliveryGroup(@onNull BroadcastRecord other)1044     boolean matchesDeliveryGroup(@NonNull BroadcastRecord other) {
1045         return matchesDeliveryGroup(this, other);
1046     }
1047 
matchesDeliveryGroup(@onNull BroadcastRecord newRecord, @NonNull BroadcastRecord oldRecord)1048     private static boolean matchesDeliveryGroup(@NonNull BroadcastRecord newRecord,
1049             @NonNull BroadcastRecord oldRecord) {
1050         final IntentFilter newMatchingFilter = getDeliveryGroupMatchingFilter(newRecord);
1051         // If neither delivery group key nor matching filter is specified, then use
1052         // Intent.filterEquals() to identify the delivery group.
1053         if (isMatchingKeyNull(newRecord) && isMatchingKeyNull(oldRecord)
1054                 && newMatchingFilter == null) {
1055             return newRecord.intent.filterEquals(oldRecord.intent);
1056         }
1057         if (newMatchingFilter != null && !newMatchingFilter.asPredicate().test(oldRecord.intent)) {
1058             return false;
1059         }
1060         return areMatchingKeysEqual(newRecord, oldRecord);
1061     }
1062 
isMatchingKeyNull(@onNull BroadcastRecord record)1063     private static boolean isMatchingKeyNull(@NonNull BroadcastRecord record) {
1064         final String namespace = getDeliveryGroupMatchingNamespaceFragment(record);
1065         final String key = getDeliveryGroupMatchingKeyFragment(record);
1066         // If either namespace or key part is null, then treat the entire matching key as null.
1067         return namespace == null || key == null;
1068     }
1069 
areMatchingKeysEqual(@onNull BroadcastRecord newRecord, @NonNull BroadcastRecord oldRecord)1070     private static boolean areMatchingKeysEqual(@NonNull BroadcastRecord newRecord,
1071             @NonNull BroadcastRecord oldRecord) {
1072         final String newNamespaceFragment = getDeliveryGroupMatchingNamespaceFragment(newRecord);
1073         final String oldNamespaceFragment = getDeliveryGroupMatchingNamespaceFragment(oldRecord);
1074         if (!Objects.equals(newNamespaceFragment, oldNamespaceFragment)) {
1075             return false;
1076         }
1077 
1078         final String newKeyFragment = getDeliveryGroupMatchingKeyFragment(newRecord);
1079         final String oldKeyFragment = getDeliveryGroupMatchingKeyFragment(oldRecord);
1080         return Objects.equals(newKeyFragment, oldKeyFragment);
1081     }
1082 
1083     @Nullable
getDeliveryGroupMatchingNamespaceFragment( @onNull BroadcastRecord record)1084     private static String getDeliveryGroupMatchingNamespaceFragment(
1085             @NonNull BroadcastRecord record) {
1086         return record.options == null
1087                 ? null : record.options.getDeliveryGroupMatchingNamespaceFragment();
1088     }
1089 
1090     @Nullable
getDeliveryGroupMatchingKeyFragment(@onNull BroadcastRecord record)1091     private static String getDeliveryGroupMatchingKeyFragment(@NonNull BroadcastRecord record) {
1092         return record.options == null
1093                 ? null : record.options.getDeliveryGroupMatchingKeyFragment();
1094     }
1095 
1096     @Nullable
getDeliveryGroupMatchingFilter(@onNull BroadcastRecord record)1097     private static IntentFilter getDeliveryGroupMatchingFilter(@NonNull BroadcastRecord record) {
1098         return record.options == null ? null : record.options.getDeliveryGroupMatchingFilter();
1099     }
1100 
1101     /**
1102      * Returns {@code true} if all the receivers are still waiting to receive the broadcast.
1103      * Otherwise {@code false}.
1104      */
allReceiversPending()1105     boolean allReceiversPending() {
1106         // We could also count the number of receivers with deliver state DELIVERY_PENDING, but
1107         // checking how many receivers have finished (either skipped or cancelled) and whether or
1108         // not the dispatch has been started should be sufficient.
1109         return (terminalCount == 0 && dispatchTime <= 0);
1110     }
1111 
isMatchingRecord(@onNull BroadcastRecord record)1112     boolean isMatchingRecord(@NonNull BroadcastRecord record) {
1113         final int idx = mMatchingRecordsCache.indexOfKey(record);
1114         if (idx > 0) {
1115             return mMatchingRecordsCache.valueAt(idx);
1116         }
1117         // Consider a record to be matching if has the same receivers in the same order.
1118         boolean matches = (receivers.size() == record.receivers.size());
1119         if (matches) {
1120             for (int i = receivers.size() - 1; i >= 0; --i) {
1121                 if (!isReceiverEquals(receivers.get(i), record.receivers.get(i))) {
1122                     matches = false;
1123                     break;
1124                 }
1125             }
1126         }
1127         mMatchingRecordsCache.put(record, matches);
1128         return matches;
1129     }
1130 
setMatchingRecordsCache(@onNull ArrayMap<BroadcastRecord, Boolean> matchingRecordsCache)1131     void setMatchingRecordsCache(@NonNull ArrayMap<BroadcastRecord, Boolean> matchingRecordsCache) {
1132         mMatchingRecordsCache = matchingRecordsCache;
1133     }
1134 
clearMatchingRecordsCache()1135     void clearMatchingRecordsCache() {
1136         mMatchingRecordsCache = null;
1137     }
1138 
1139     @Override
toString()1140     public String toString() {
1141         if (mCachedToString == null) {
1142             String label = intent.getAction();
1143             if (label == null) {
1144                 label = intent.toString();
1145             }
1146             mCachedToString = "BroadcastRecord{" + toShortString() + "}";
1147         }
1148         return mCachedToString;
1149     }
1150 
toShortString()1151     public String toShortString() {
1152         if (mCachedToShortString == null) {
1153             String label = intent.getAction();
1154             if (label == null) {
1155                 label = intent.toString();
1156             }
1157             mCachedToShortString = Integer.toHexString(System.identityHashCode(this))
1158                     + " " + label + "/u" + userId;
1159         }
1160         return mCachedToShortString;
1161     }
1162 
1163     @NeverCompile
dumpDebug(ProtoOutputStream proto, long fieldId)1164     public void dumpDebug(ProtoOutputStream proto, long fieldId) {
1165         long token = proto.start(fieldId);
1166         proto.write(BroadcastRecordProto.USER_ID, userId);
1167         proto.write(BroadcastRecordProto.INTENT_ACTION, intent.getAction());
1168         proto.end(token);
1169     }
1170 }
1171