• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
20 
21 import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_ALL;
22 import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_BACKGROUND_RESTRICTED_ONLY;
23 import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_CHANGE_ID;
24 import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_NONE;
25 import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_TARGET_T_ONLY;
26 
27 import android.annotation.NonNull;
28 import android.annotation.Nullable;
29 import android.app.ActivityManagerInternal;
30 import android.app.AppOpsManager;
31 import android.app.BroadcastOptions;
32 import android.app.compat.CompatChanges;
33 import android.content.ComponentName;
34 import android.content.IIntentReceiver;
35 import android.content.Intent;
36 import android.content.pm.ActivityInfo;
37 import android.content.pm.ResolveInfo;
38 import android.os.Binder;
39 import android.os.Bundle;
40 import android.os.IBinder;
41 import android.os.SystemClock;
42 import android.os.UserHandle;
43 import android.util.PrintWriterPrinter;
44 import android.util.SparseArray;
45 import android.util.TimeUtils;
46 import android.util.proto.ProtoOutputStream;
47 
48 import com.android.internal.annotations.VisibleForTesting;
49 
50 import java.io.PrintWriter;
51 import java.text.SimpleDateFormat;
52 import java.util.ArrayList;
53 import java.util.Arrays;
54 import java.util.Date;
55 import java.util.List;
56 import java.util.Set;
57 import java.util.concurrent.atomic.AtomicInteger;
58 
59 /**
60  * An active intent broadcast.
61  */
62 final class BroadcastRecord extends Binder {
63     final Intent intent;    // the original intent that generated us
64     final ComponentName targetComp; // original component name set on the intent
65     final ProcessRecord callerApp; // process that sent this
66     final String callerPackage; // who sent this
67     final @Nullable String callerFeatureId; // which feature in the package sent this
68     final int callingPid;   // the pid of who sent this
69     final int callingUid;   // the uid of who sent this
70     final boolean callerInstantApp; // caller is an Instant App?
71     final boolean ordered;  // serialize the send to receivers?
72     final boolean sticky;   // originated from existing sticky data?
73     final boolean alarm;    // originated from an alarm triggering?
74     final boolean pushMessage; // originated from a push message?
75     final boolean pushMessageOverQuota; // originated from a push message which was over quota?
76     final boolean initialSticky; // initial broadcast from register to sticky?
77     final int userId;       // user id this broadcast was for
78     final String resolvedType; // the resolved data type
79     final String[] requiredPermissions; // permissions the caller has required
80     final String[] excludedPermissions; // permissions to exclude
81     final String[] excludedPackages; // packages to exclude
82     final int appOp;        // an app op that is associated with this broadcast
83     final BroadcastOptions options; // BroadcastOptions supplied by caller
84     final List receivers;   // contains BroadcastFilter and ResolveInfo
85     final int[] delivery;   // delivery state of each receiver
86     final long[] duration;   // duration a receiver took to process broadcast
87     IIntentReceiver resultTo; // who receives final result if non-null
88     boolean deferred;
89     int splitCount;         // refcount for result callback, when split
90     int splitToken;         // identifier for cross-BroadcastRecord refcount
91     long enqueueTime;       // uptimeMillis when the broadcast was enqueued
92     long enqueueRealTime;   // elapsedRealtime when the broadcast was enqueued
93     long enqueueClockTime;  // the clock time the broadcast was enqueued
94     long dispatchTime;      // when dispatch started on this set of receivers
95     long dispatchRealTime;  // elapsedRealtime when the broadcast was dispatched
96     long dispatchClockTime; // the clock time the dispatch started
97     long receiverTime;      // when current receiver started for timeouts.
98     long finishTime;        // when we finished the current receiver.
99     boolean timeoutExempt;  // true if this broadcast is not subject to receiver timeouts
100     int resultCode;         // current result code value.
101     String resultData;      // current result data value.
102     Bundle resultExtras;    // current result extra data values.
103     boolean resultAbort;    // current result abortBroadcast value.
104     int nextReceiver;       // next receiver to be executed.
105     IBinder receiver;       // who is currently running, null if none.
106     int state;
107     int anrCount;           // has this broadcast record hit any ANRs?
108     int manifestCount;      // number of manifest receivers dispatched.
109     int manifestSkipCount;  // number of manifest receivers skipped.
110     BroadcastQueue queue;   // the outbound queue handling this broadcast
111 
112     // if set to true, app's process will be temporarily allowed to start activities from background
113     // for the duration of the broadcast dispatch
114     final boolean allowBackgroundActivityStarts;
115     // token used to trace back the grant for activity starts, optional
116     @Nullable
117     final IBinder mBackgroundActivityStartsToken;
118 
119     static final int IDLE = 0;
120     static final int APP_RECEIVE = 1;
121     static final int CALL_IN_RECEIVE = 2;
122     static final int CALL_DONE_RECEIVE = 3;
123     static final int WAITING_SERVICES = 4;
124 
125     static final int DELIVERY_PENDING = 0;
126     static final int DELIVERY_DELIVERED = 1;
127     static final int DELIVERY_SKIPPED = 2;
128     static final int DELIVERY_TIMEOUT = 3;
129 
130     // The following are set when we are calling a receiver (one that
131     // was found in our list of registered receivers).
132     BroadcastFilter curFilter;
133 
134     // The following are set only when we are launching a receiver (one
135     // that was found by querying the package manager).
136     ProcessRecord curApp;       // hosting application of current receiver.
137     ComponentName curComponent; // the receiver class that is currently running.
138     ActivityInfo curReceiver;   // info about the receiver that is currently running.
139 
140     boolean mIsReceiverAppRunning; // Was the receiver's app already running.
141 
142     // Private refcount-management bookkeeping; start > 0
143     static AtomicInteger sNextToken = new AtomicInteger(1);
144 
dump(PrintWriter pw, String prefix, SimpleDateFormat sdf)145     void dump(PrintWriter pw, String prefix, SimpleDateFormat sdf) {
146         final long now = SystemClock.uptimeMillis();
147 
148         pw.print(prefix); pw.print(this); pw.print(" to user "); pw.println(userId);
149         pw.print(prefix); pw.println(intent.toInsecureString());
150         if (targetComp != null && targetComp != intent.getComponent()) {
151             pw.print(prefix); pw.print("  targetComp: "); pw.println(targetComp.toShortString());
152         }
153         Bundle bundle = intent.getExtras();
154         if (bundle != null) {
155             pw.print(prefix); pw.print("  extras: "); pw.println(bundle.toString());
156         }
157         pw.print(prefix); pw.print("caller="); pw.print(callerPackage); pw.print(" ");
158                 pw.print(callerApp != null ? callerApp.toShortString() : "null");
159                 pw.print(" pid="); pw.print(callingPid);
160                 pw.print(" uid="); pw.println(callingUid);
161         if ((requiredPermissions != null && requiredPermissions.length > 0)
162                 || appOp != AppOpsManager.OP_NONE) {
163             pw.print(prefix); pw.print("requiredPermissions=");
164             pw.print(Arrays.toString(requiredPermissions));
165             pw.print("  appOp="); pw.println(appOp);
166         }
167         if (excludedPermissions != null && excludedPermissions.length > 0) {
168             pw.print(prefix); pw.print("excludedPermissions=");
169             pw.print(Arrays.toString(excludedPermissions));
170         }
171         if (excludedPackages != null && excludedPackages.length > 0) {
172             pw.print(prefix); pw.print("excludedPackages=");
173             pw.print(Arrays.toString(excludedPackages));
174         }
175         if (options != null) {
176             pw.print(prefix); pw.print("options="); pw.println(options.toBundle());
177         }
178         pw.print(prefix); pw.print("enqueueClockTime=");
179                 pw.print(sdf.format(new Date(enqueueClockTime)));
180                 pw.print(" dispatchClockTime=");
181                 pw.println(sdf.format(new Date(dispatchClockTime)));
182         pw.print(prefix); pw.print("dispatchTime=");
183                 TimeUtils.formatDuration(dispatchTime, now, pw);
184                 pw.print(" (");
185                 TimeUtils.formatDuration(dispatchTime - enqueueTime, pw);
186                 pw.print(" since enq)");
187         if (finishTime != 0) {
188             pw.print(" finishTime="); TimeUtils.formatDuration(finishTime, now, pw);
189             pw.print(" (");
190             TimeUtils.formatDuration(finishTime-dispatchTime, pw);
191             pw.print(" since disp)");
192         } else {
193             pw.print(" receiverTime="); TimeUtils.formatDuration(receiverTime, now, pw);
194         }
195         pw.println("");
196         if (anrCount != 0) {
197             pw.print(prefix); pw.print("anrCount="); pw.println(anrCount);
198         }
199         if (resultTo != null || resultCode != -1 || resultData != null) {
200             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
201                     pw.print(" resultCode="); pw.print(resultCode);
202                     pw.print(" resultData="); pw.println(resultData);
203         }
204         if (resultExtras != null) {
205             pw.print(prefix); pw.print("resultExtras="); pw.println(resultExtras);
206         }
207         if (resultAbort || ordered || sticky || initialSticky) {
208             pw.print(prefix); pw.print("resultAbort="); pw.print(resultAbort);
209                     pw.print(" ordered="); pw.print(ordered);
210                     pw.print(" sticky="); pw.print(sticky);
211                     pw.print(" initialSticky="); pw.println(initialSticky);
212         }
213         if (nextReceiver != 0 || receiver != null) {
214             pw.print(prefix); pw.print("nextReceiver="); pw.print(nextReceiver);
215                     pw.print(" receiver="); pw.println(receiver);
216         }
217         if (curFilter != null) {
218             pw.print(prefix); pw.print("curFilter="); pw.println(curFilter);
219         }
220         if (curReceiver != null) {
221             pw.print(prefix); pw.print("curReceiver="); pw.println(curReceiver);
222         }
223         if (curApp != null) {
224             pw.print(prefix); pw.print("curApp="); pw.println(curApp);
225             pw.print(prefix); pw.print("curComponent=");
226                     pw.println((curComponent != null ? curComponent.toShortString() : "--"));
227             if (curReceiver != null && curReceiver.applicationInfo != null) {
228                 pw.print(prefix); pw.print("curSourceDir=");
229                         pw.println(curReceiver.applicationInfo.sourceDir);
230             }
231         }
232         if (state != IDLE) {
233             String stateStr = " (?)";
234             switch (state) {
235                 case APP_RECEIVE:       stateStr=" (APP_RECEIVE)"; break;
236                 case CALL_IN_RECEIVE:   stateStr=" (CALL_IN_RECEIVE)"; break;
237                 case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_RECEIVE)"; break;
238                 case WAITING_SERVICES:  stateStr=" (WAITING_SERVICES)"; break;
239             }
240             pw.print(prefix); pw.print("state="); pw.print(state); pw.println(stateStr);
241         }
242         final int N = receivers != null ? receivers.size() : 0;
243         String p2 = prefix + "  ";
244         PrintWriterPrinter printer = new PrintWriterPrinter(pw);
245         for (int i = 0; i < N; i++) {
246             Object o = receivers.get(i);
247             pw.print(prefix);
248             switch (delivery[i]) {
249                 case DELIVERY_PENDING:   pw.print("Pending"); break;
250                 case DELIVERY_DELIVERED: pw.print("Deliver"); break;
251                 case DELIVERY_SKIPPED:   pw.print("Skipped"); break;
252                 case DELIVERY_TIMEOUT:   pw.print("Timeout"); break;
253                 default:                 pw.print("???????"); break;
254             }
255             pw.print(" "); TimeUtils.formatDuration(duration[i], pw);
256             pw.print(" #"); pw.print(i); pw.print(": ");
257             if (o instanceof BroadcastFilter) {
258                 pw.println(o);
259                 ((BroadcastFilter) o).dumpBrief(pw, p2);
260             } else if (o instanceof ResolveInfo) {
261                 pw.println("(manifest)");
262                 ((ResolveInfo) o).dump(printer, p2, 0);
263             } else {
264                 pw.println(o);
265             }
266         }
267     }
268 
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, IIntentReceiver _resultTo, int _resultCode, String _resultData, Bundle _resultExtras, boolean _serialized, boolean _sticky, boolean _initialSticky, int _userId, boolean allowBackgroundActivityStarts, @Nullable IBinder backgroundActivityStartsToken, boolean timeoutExempt)269     BroadcastRecord(BroadcastQueue _queue,
270             Intent _intent, ProcessRecord _callerApp, String _callerPackage,
271             @Nullable String _callerFeatureId, int _callingPid, int _callingUid,
272             boolean _callerInstantApp, String _resolvedType,
273             String[] _requiredPermissions, String[] _excludedPermissions,
274             String[] _excludedPackages, int _appOp,
275             BroadcastOptions _options, List _receivers, IIntentReceiver _resultTo, int _resultCode,
276             String _resultData, Bundle _resultExtras, boolean _serialized, boolean _sticky,
277             boolean _initialSticky, int _userId, boolean allowBackgroundActivityStarts,
278             @Nullable IBinder backgroundActivityStartsToken, boolean timeoutExempt) {
279         if (_intent == null) {
280             throw new NullPointerException("Can't construct with a null intent");
281         }
282         queue = _queue;
283         intent = _intent;
284         targetComp = _intent.getComponent();
285         callerApp = _callerApp;
286         callerPackage = _callerPackage;
287         callerFeatureId = _callerFeatureId;
288         callingPid = _callingPid;
289         callingUid = _callingUid;
290         callerInstantApp = _callerInstantApp;
291         resolvedType = _resolvedType;
292         requiredPermissions = _requiredPermissions;
293         excludedPermissions = _excludedPermissions;
294         excludedPackages = _excludedPackages;
295         appOp = _appOp;
296         options = _options;
297         receivers = _receivers;
298         delivery = new int[_receivers != null ? _receivers.size() : 0];
299         duration = new long[delivery.length];
300         resultTo = _resultTo;
301         resultCode = _resultCode;
302         resultData = _resultData;
303         resultExtras = _resultExtras;
304         ordered = _serialized;
305         sticky = _sticky;
306         initialSticky = _initialSticky;
307         userId = _userId;
308         nextReceiver = 0;
309         state = IDLE;
310         this.allowBackgroundActivityStarts = allowBackgroundActivityStarts;
311         mBackgroundActivityStartsToken = backgroundActivityStartsToken;
312         this.timeoutExempt = timeoutExempt;
313         alarm = options != null && options.isAlarmBroadcast();
314         pushMessage = options != null && options.isPushMessagingBroadcast();
315         pushMessageOverQuota = options != null && options.isPushMessagingOverQuotaBroadcast();
316     }
317 
318     /**
319      * Copy constructor which takes a different intent.
320      * Only used by {@link #maybeStripForHistory}.
321      */
BroadcastRecord(BroadcastRecord from, Intent newIntent)322     private BroadcastRecord(BroadcastRecord from, Intent newIntent) {
323         intent = newIntent;
324         targetComp = newIntent.getComponent();
325 
326         callerApp = from.callerApp;
327         callerPackage = from.callerPackage;
328         callerFeatureId = from.callerFeatureId;
329         callingPid = from.callingPid;
330         callingUid = from.callingUid;
331         callerInstantApp = from.callerInstantApp;
332         ordered = from.ordered;
333         sticky = from.sticky;
334         initialSticky = from.initialSticky;
335         userId = from.userId;
336         resolvedType = from.resolvedType;
337         requiredPermissions = from.requiredPermissions;
338         excludedPermissions = from.excludedPermissions;
339         excludedPackages = from.excludedPackages;
340         appOp = from.appOp;
341         options = from.options;
342         receivers = from.receivers;
343         delivery = from.delivery;
344         duration = from.duration;
345         resultTo = from.resultTo;
346         enqueueTime = from.enqueueTime;
347         enqueueRealTime = from.enqueueRealTime;
348         enqueueClockTime = from.enqueueClockTime;
349         dispatchTime = from.dispatchTime;
350         dispatchRealTime = from.dispatchRealTime;
351         dispatchClockTime = from.dispatchClockTime;
352         receiverTime = from.receiverTime;
353         finishTime = from.finishTime;
354         resultCode = from.resultCode;
355         resultData = from.resultData;
356         resultExtras = from.resultExtras;
357         resultAbort = from.resultAbort;
358         nextReceiver = from.nextReceiver;
359         receiver = from.receiver;
360         state = from.state;
361         anrCount = from.anrCount;
362         manifestCount = from.manifestCount;
363         manifestSkipCount = from.manifestSkipCount;
364         queue = from.queue;
365         allowBackgroundActivityStarts = from.allowBackgroundActivityStarts;
366         mBackgroundActivityStartsToken = from.mBackgroundActivityStartsToken;
367         timeoutExempt = from.timeoutExempt;
368         alarm = from.alarm;
369         pushMessage = from.pushMessage;
370         pushMessageOverQuota = from.pushMessageOverQuota;
371     }
372 
373     /**
374      * Split off a new BroadcastRecord that clones this one, but contains only the
375      * recipient records for the current (just-finished) receiver's app, starting
376      * after the just-finished receiver [i.e. at r.nextReceiver].  Returns null
377      * if there are no matching subsequent receivers in this BroadcastRecord.
378      */
splitRecipientsLocked(int slowAppUid, int startingAt)379     BroadcastRecord splitRecipientsLocked(int slowAppUid, int startingAt) {
380         // Do we actually have any matching receivers down the line...?
381         ArrayList splitReceivers = null;
382         for (int i = startingAt; i < receivers.size(); ) {
383             Object o = receivers.get(i);
384             if (getReceiverUid(o) == slowAppUid) {
385                 if (splitReceivers == null) {
386                     splitReceivers = new ArrayList<>();
387                 }
388                 splitReceivers.add(o);
389                 receivers.remove(i);
390             } else {
391                 i++;
392             }
393         }
394 
395         // No later receivers in the same app, so we have no more to do
396         if (splitReceivers == null) {
397             return null;
398         }
399 
400         // build a new BroadcastRecord around that single-target list
401         BroadcastRecord split = new BroadcastRecord(queue, intent, callerApp, callerPackage,
402                 callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
403                 requiredPermissions, excludedPermissions, excludedPackages, appOp, options,
404                 splitReceivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky,
405                 initialSticky, userId, allowBackgroundActivityStarts,
406                 mBackgroundActivityStartsToken, timeoutExempt);
407         split.enqueueTime = this.enqueueTime;
408         split.enqueueRealTime = this.enqueueRealTime;
409         split.enqueueClockTime = this.enqueueClockTime;
410         split.splitToken = this.splitToken;
411         return split;
412     }
413 
414     /**
415      * Split a BroadcastRecord to a map of deferred receiver UID to deferred BroadcastRecord.
416      *
417      * The receivers that are deferred are removed from original BroadcastRecord's receivers list.
418      * The receivers that are not deferred are kept in original BroadcastRecord's receivers list.
419      *
420      * Only used to split LOCKED_BOOT_COMPLETED or BOOT_COMPLETED BroadcastRecord.
421      * LOCKED_BOOT_COMPLETED or BOOT_COMPLETED broadcast can be deferred until the first time
422      * the receiver's UID has a process started.
423      *
424      * @param ams The ActivityManagerService object.
425      * @param deferType Defer what UID?
426      * @return the deferred UID to BroadcastRecord map, the BroadcastRecord has the list of
427      *         receivers in that UID.
428      */
splitDeferredBootCompletedBroadcastLocked( ActivityManagerInternal activityManagerInternal, @BroadcastConstants.DeferBootCompletedBroadcastType int deferType)429     @NonNull SparseArray<BroadcastRecord> splitDeferredBootCompletedBroadcastLocked(
430             ActivityManagerInternal activityManagerInternal,
431             @BroadcastConstants.DeferBootCompletedBroadcastType int deferType) {
432         final SparseArray<BroadcastRecord> ret = new SparseArray<>();
433         if (deferType == DEFER_BOOT_COMPLETED_BROADCAST_NONE) {
434             return ret;
435         }
436 
437         if (receivers == null) {
438             return ret;
439         }
440 
441         final String action = intent.getAction();
442         if (!Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(action)
443                 && !Intent.ACTION_BOOT_COMPLETED.equals(action)) {
444             return ret;
445         }
446 
447         final SparseArray<List<Object>> uid2receiverList = new SparseArray<>();
448         for (int i = receivers.size() - 1; i >= 0; i--) {
449             final Object receiver = receivers.get(i);
450             final int uid = getReceiverUid(receiver);
451             if (deferType != DEFER_BOOT_COMPLETED_BROADCAST_ALL) {
452                 if ((deferType & DEFER_BOOT_COMPLETED_BROADCAST_BACKGROUND_RESTRICTED_ONLY) != 0) {
453                     if (activityManagerInternal.getRestrictionLevel(uid)
454                             < RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
455                         // skip if the UID is not background restricted.
456                         continue;
457                     }
458                 }
459                 if ((deferType & DEFER_BOOT_COMPLETED_BROADCAST_TARGET_T_ONLY) != 0) {
460                     if (!CompatChanges.isChangeEnabled(DEFER_BOOT_COMPLETED_BROADCAST_CHANGE_ID,
461                             uid)) {
462                         // skip if the UID is not targetSdkVersion T+.
463                         continue;
464                     }
465                 }
466             }
467             // Remove receiver from original BroadcastRecord's receivers list.
468             receivers.remove(i);
469             final List<Object> receiverList = uid2receiverList.get(uid);
470             if (receiverList != null) {
471                 receiverList.add(0, receiver);
472             } else {
473                 ArrayList<Object> splitReceivers = new ArrayList<>();
474                 splitReceivers.add(0, receiver);
475                 uid2receiverList.put(uid, splitReceivers);
476             }
477         }
478         final int uidSize = uid2receiverList.size();
479         for (int i = 0; i < uidSize; i++) {
480             final BroadcastRecord br = new BroadcastRecord(queue, intent, callerApp, callerPackage,
481                     callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
482                     requiredPermissions, excludedPermissions, excludedPackages, appOp, options,
483                     uid2receiverList.valueAt(i), null /* _resultTo */,
484                     resultCode, resultData, resultExtras, ordered, sticky, initialSticky, userId,
485                     allowBackgroundActivityStarts, mBackgroundActivityStartsToken, timeoutExempt);
486             br.enqueueTime = this.enqueueTime;
487             br.enqueueRealTime = this.enqueueRealTime;
488             br.enqueueClockTime = this.enqueueClockTime;
489             ret.put(uid2receiverList.keyAt(i), br);
490         }
491         return ret;
492     }
493 
getReceiverUid(Object receiver)494     int getReceiverUid(Object receiver) {
495         if (receiver instanceof BroadcastFilter) {
496             return ((BroadcastFilter) receiver).owningUid;
497         } else /* if (receiver instanceof ResolveInfo) */ {
498             return ((ResolveInfo) receiver).activityInfo.applicationInfo.uid;
499         }
500     }
501 
maybeStripForHistory()502     public BroadcastRecord maybeStripForHistory() {
503         if (!intent.canStripForHistory()) {
504             return this;
505         }
506         return new BroadcastRecord(this, intent.maybeStripForHistory());
507     }
508 
509     @VisibleForTesting
cleanupDisabledPackageReceiversLocked( String packageName, Set<String> filterByClasses, int userId, boolean doit)510     boolean cleanupDisabledPackageReceiversLocked(
511             String packageName, Set<String> filterByClasses, int userId, boolean doit) {
512         if (receivers == null) {
513             return false;
514         }
515 
516         final boolean cleanupAllUsers = userId == UserHandle.USER_ALL;
517         final boolean sendToAllUsers = this.userId == UserHandle.USER_ALL;
518         if (this.userId != userId && !cleanupAllUsers && !sendToAllUsers) {
519             return false;
520         }
521 
522         boolean didSomething = false;
523         Object o;
524         for (int i = receivers.size() - 1; i >= 0; i--) {
525             o = receivers.get(i);
526             if (!(o instanceof ResolveInfo)) {
527                 continue;
528             }
529             ActivityInfo info = ((ResolveInfo)o).activityInfo;
530 
531             final boolean sameComponent = packageName == null
532                     || (info.applicationInfo.packageName.equals(packageName)
533                     && (filterByClasses == null || filterByClasses.contains(info.name)));
534             if (sameComponent && (cleanupAllUsers
535                     || UserHandle.getUserId(info.applicationInfo.uid) == userId)) {
536                 if (!doit) {
537                     return true;
538                 }
539                 didSomething = true;
540                 receivers.remove(i);
541                 if (i < nextReceiver) {
542                     nextReceiver--;
543                 }
544             }
545         }
546         nextReceiver = Math.min(nextReceiver, receivers.size());
547 
548         return didSomething;
549     }
550 
551     @Override
toString()552     public String toString() {
553         return "BroadcastRecord{"
554             + Integer.toHexString(System.identityHashCode(this))
555             + " u" + userId + " " + intent.getAction() + "}";
556     }
557 
dumpDebug(ProtoOutputStream proto, long fieldId)558     public void dumpDebug(ProtoOutputStream proto, long fieldId) {
559         long token = proto.start(fieldId);
560         proto.write(BroadcastRecordProto.USER_ID, userId);
561         proto.write(BroadcastRecordProto.INTENT_ACTION, intent.getAction());
562         proto.end(token);
563     }
564 }
565