1 /*
2  * Copyright (C) 2018 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 com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST;
20 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_DEFERRAL;
21 import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_NONE;
22 
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.UptimeMillisLong;
26 import android.content.Intent;
27 import android.content.pm.ResolveInfo;
28 import android.os.Handler;
29 import android.os.SystemClock;
30 import android.os.UserHandle;
31 import android.util.Slog;
32 import android.util.SparseArray;
33 import android.util.SparseBooleanArray;
34 import android.util.SparseIntArray;
35 import android.util.proto.ProtoOutputStream;
36 
37 import com.android.internal.annotations.VisibleForTesting;
38 import com.android.server.AlarmManagerInternal;
39 import com.android.server.LocalServices;
40 
41 import dalvik.annotation.optimization.NeverCompile;
42 
43 import java.io.PrintWriter;
44 import java.text.SimpleDateFormat;
45 import java.util.ArrayList;
46 import java.util.Set;
47 
48 /**
49  * Manages ordered broadcast delivery, applying policy to mitigate the effects of
50  * slow receivers.
51  */
52 public class BroadcastDispatcher {
53     private static final String TAG = "BroadcastDispatcher";
54 
55     // Deferred broadcasts to one app; times are all uptime time base like
56     // other broadcast-related timekeeping
57     static class Deferrals {
58         final int uid;
59         long deferredAt;    // when we started deferring
60         long deferredBy;    // how long did we defer by last time?
61         long deferUntil;    // when does the next element become deliverable?
62         int alarmCount;
63 
64         final ArrayList<BroadcastRecord> broadcasts;
65 
Deferrals(int uid, long now, long backoff, int count)66         Deferrals(int uid, long now, long backoff, int count) {
67             this.uid = uid;
68             this.deferredAt = now;
69             this.deferredBy = backoff;
70             this.deferUntil = now + backoff;
71             this.alarmCount = count;
72             broadcasts = new ArrayList<>();
73         }
74 
add(BroadcastRecord br)75         void add(BroadcastRecord br) {
76             broadcasts.add(br);
77         }
78 
size()79         int size() {
80             return broadcasts.size();
81         }
82 
isEmpty()83         boolean isEmpty() {
84             return broadcasts.isEmpty();
85         }
86 
87         @NeverCompile
dumpDebug(ProtoOutputStream proto, long fieldId)88         void dumpDebug(ProtoOutputStream proto, long fieldId) {
89             for (BroadcastRecord br : broadcasts) {
90                 br.dumpDebug(proto, fieldId);
91             }
92         }
93 
94         @NeverCompile
dumpLocked(Dumper d)95         void dumpLocked(Dumper d) {
96             for (BroadcastRecord br : broadcasts) {
97                 d.dump(br);
98             }
99         }
100 
101         @Override
toString()102         public String toString() {
103             StringBuilder sb = new StringBuilder(128);
104             sb.append("Deferrals{uid=");
105             sb.append(uid);
106             sb.append(", deferUntil=");
107             sb.append(deferUntil);
108             sb.append(", #broadcasts=");
109             sb.append(broadcasts.size());
110             sb.append("}");
111             return sb.toString();
112         }
113     }
114 
115     // Carrying dump formatting state across multiple concatenated datasets
116     class Dumper {
117         final PrintWriter mPw;
118         final String mQueueName;
119         final String mDumpPackage;
120         final SimpleDateFormat mSdf;
121         boolean mPrinted;
122         boolean mNeedSep;
123         String mHeading;
124         String mLabel;
125         int mOrdinal;
126 
Dumper(PrintWriter pw, String queueName, String dumpPackage, SimpleDateFormat sdf)127         Dumper(PrintWriter pw, String queueName, String dumpPackage, SimpleDateFormat sdf) {
128             mPw = pw;
129             mQueueName = queueName;
130             mDumpPackage = dumpPackage;
131             mSdf = sdf;
132 
133             mPrinted = false;
134             mNeedSep = true;
135         }
136 
setHeading(String heading)137         void setHeading(String heading) {
138             mHeading = heading;
139             mPrinted = false;
140         }
141 
setLabel(String label)142         void setLabel(String label) {
143             //"  Active Ordered Broadcast " + mQueueName + " #" + i + ":"
144             mLabel = "  " + label + " " + mQueueName + " #";
145             mOrdinal = 0;
146         }
147 
didPrint()148         boolean didPrint() {
149             return mPrinted;
150         }
151 
152         @NeverCompile
dump(BroadcastRecord br)153         void dump(BroadcastRecord br) {
154             if (mDumpPackage == null || mDumpPackage.equals(br.callerPackage)) {
155                 if (!mPrinted) {
156                     if (mNeedSep) {
157                         mPw.println();
158                     }
159                     mPrinted = true;
160                     mNeedSep = true;
161                     mPw.println("  " + mHeading + " [" + mQueueName + "]:");
162                 }
163                 mPw.println(mLabel + mOrdinal + ":");
164                 mOrdinal++;
165 
166                 br.dump(mPw, "    ", mSdf);
167             }
168         }
169     }
170 
171     private final Object mLock;
172     private final BroadcastQueueImpl mQueue;
173     private final BroadcastConstants mConstants;
174     private final Handler mHandler;
175     private AlarmManagerInternal mAlarm;
176 
177     // Current alarm targets; mapping uid -> in-flight alarm count
178     final SparseIntArray mAlarmUids = new SparseIntArray();
179     final AlarmManagerInternal.InFlightListener mAlarmListener =
180             new AlarmManagerInternal.InFlightListener() {
181         @Override
182         public void broadcastAlarmPending(final int recipientUid) {
183             synchronized (mLock) {
184                 final int newCount = mAlarmUids.get(recipientUid, 0) + 1;
185                 mAlarmUids.put(recipientUid, newCount);
186                 // any deferred broadcasts to this app now get fast-tracked
187                 final int numEntries = mDeferredBroadcasts.size();
188                 for (int i = 0; i < numEntries; i++) {
189                     if (recipientUid == mDeferredBroadcasts.get(i).uid) {
190                         Deferrals d = mDeferredBroadcasts.remove(i);
191                         mAlarmDeferrals.add(d);
192                         break;
193                     }
194                 }
195             }
196         }
197 
198         @Override
199         public void broadcastAlarmComplete(final int recipientUid) {
200             synchronized (mLock) {
201                 final int newCount = mAlarmUids.get(recipientUid, 0) - 1;
202                 if (newCount >= 0) {
203                     mAlarmUids.put(recipientUid, newCount);
204                 } else {
205                     Slog.wtf(TAG, "Undercount of broadcast alarms in flight for " + recipientUid);
206                     mAlarmUids.put(recipientUid, 0);
207                 }
208 
209                 // No longer an alarm target, so resume ordinary deferral policy
210                 if (newCount <= 0) {
211                     final int numEntries = mAlarmDeferrals.size();
212                     for (int i = 0; i < numEntries; i++) {
213                         if (recipientUid == mAlarmDeferrals.get(i).uid) {
214                             Deferrals d = mAlarmDeferrals.remove(i);
215                             insertLocked(mDeferredBroadcasts, d);
216                             break;
217                         }
218                     }
219                 }
220             }
221         }
222     };
223 
224     // Queue recheck operation used to tickle broadcast delivery when appropriate
225     final Runnable mScheduleRunnable = new Runnable() {
226         @Override
227         public void run() {
228             synchronized (mLock) {
229                 if (DEBUG_BROADCAST_DEFERRAL) {
230                     Slog.v(TAG, "Deferral recheck of pending broadcasts");
231                 }
232                 mQueue.scheduleBroadcastsLocked();
233                 mRecheckScheduled = false;
234             }
235         }
236     };
237     private boolean mRecheckScheduled = false;
238 
239     // Usual issuance-order outbound queue
240     private final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>();
241     // General deferrals not holding up alarms
242     private final ArrayList<Deferrals> mDeferredBroadcasts = new ArrayList<>();
243     // Deferrals that *are* holding up alarms; ordered by alarm dispatch time
244     private final ArrayList<Deferrals> mAlarmDeferrals = new ArrayList<>();
245     // Under the "deliver alarm broadcasts immediately" policy, the queue of
246     // upcoming alarm broadcasts.  These are always delivered first - if the
247     // policy is changed on the fly from immediate-alarm-delivery to the previous
248     // in-order-queueing behavior, pending immediate alarm deliveries will drain
249     // and then the behavior settle into the pre-U semantics.
250     private final ArrayList<BroadcastRecord> mAlarmQueue = new ArrayList<>();
251 
252     // Next outbound broadcast, established by getNextBroadcastLocked()
253     private BroadcastRecord mCurrentBroadcast;
254 
255     // Map userId to its deferred boot completed broadcasts.
256     private SparseArray<DeferredBootCompletedBroadcastPerUser> mUser2Deferred = new SparseArray<>();
257 
258     /**
259      * Deferred LOCKED_BOOT_COMPLETED and BOOT_COMPLETED broadcasts that is sent to a user.
260      */
261     static class DeferredBootCompletedBroadcastPerUser {
262         private int mUserId;
263         // UID that has process started at least once, ready to execute LOCKED_BOOT_COMPLETED
264         // receivers.
265         @VisibleForTesting
266         SparseBooleanArray mUidReadyForLockedBootCompletedBroadcast = new SparseBooleanArray();
267         // UID that has process started at least once, ready to execute BOOT_COMPLETED receivers.
268         @VisibleForTesting
269         SparseBooleanArray mUidReadyForBootCompletedBroadcast = new SparseBooleanArray();
270         // Map UID to deferred LOCKED_BOOT_COMPLETED broadcasts.
271         // LOCKED_BOOT_COMPLETED broadcast receivers are deferred until the first time the uid has
272         // any process started.
273         @VisibleForTesting
274         SparseArray<BroadcastRecord> mDeferredLockedBootCompletedBroadcasts = new SparseArray<>();
275         // is the LOCKED_BOOT_COMPLETED broadcast received by the user.
276         @VisibleForTesting
277         boolean mLockedBootCompletedBroadcastReceived;
278         // Map UID to deferred BOOT_COMPLETED broadcasts.
279         // BOOT_COMPLETED broadcast receivers are deferred until the first time the uid has any
280         // process started.
281         @VisibleForTesting
282         SparseArray<BroadcastRecord> mDeferredBootCompletedBroadcasts = new SparseArray<>();
283         // is the BOOT_COMPLETED broadcast received by the user.
284         @VisibleForTesting
285         boolean mBootCompletedBroadcastReceived;
286 
DeferredBootCompletedBroadcastPerUser(int userId)287         DeferredBootCompletedBroadcastPerUser(int userId) {
288             this.mUserId = userId;
289         }
290 
updateUidReady(int uid)291         public void updateUidReady(int uid) {
292             if (!mLockedBootCompletedBroadcastReceived
293                     || mDeferredLockedBootCompletedBroadcasts.size() != 0) {
294                 mUidReadyForLockedBootCompletedBroadcast.put(uid, true);
295             }
296             if (!mBootCompletedBroadcastReceived
297                     || mDeferredBootCompletedBroadcasts.size() != 0) {
298                 mUidReadyForBootCompletedBroadcast.put(uid, true);
299             }
300         }
301 
enqueueBootCompletedBroadcasts(String action, SparseArray<BroadcastRecord> deferred)302         public void enqueueBootCompletedBroadcasts(String action,
303                 SparseArray<BroadcastRecord> deferred) {
304             if (Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(action)) {
305                 enqueueBootCompletedBroadcasts(deferred, mDeferredLockedBootCompletedBroadcasts,
306                         mUidReadyForLockedBootCompletedBroadcast);
307                 mLockedBootCompletedBroadcastReceived = true;
308                 if (DEBUG_BROADCAST_DEFERRAL) {
309                     dumpBootCompletedBroadcastRecord(mDeferredLockedBootCompletedBroadcasts);
310                 }
311             } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
312                 enqueueBootCompletedBroadcasts(deferred, mDeferredBootCompletedBroadcasts,
313                         mUidReadyForBootCompletedBroadcast);
314                 mBootCompletedBroadcastReceived = true;
315                 if (DEBUG_BROADCAST_DEFERRAL) {
316                     dumpBootCompletedBroadcastRecord(mDeferredBootCompletedBroadcasts);
317                 }
318             }
319         }
320 
321         /**
322          * Merge UID to BroadcastRecord map into {@link #mDeferredBootCompletedBroadcasts} or
323          * {@link #mDeferredLockedBootCompletedBroadcasts}
324          * @param from the UID to BroadcastRecord map.
325          * @param into The UID to list of BroadcastRecord map.
326          */
enqueueBootCompletedBroadcasts(SparseArray<BroadcastRecord> from, SparseArray<BroadcastRecord> into, SparseBooleanArray uidReadyForReceiver)327         private void enqueueBootCompletedBroadcasts(SparseArray<BroadcastRecord> from,
328                 SparseArray<BroadcastRecord> into, SparseBooleanArray uidReadyForReceiver) {
329             // remove unwanted uids from uidReadyForReceiver.
330             for (int i = uidReadyForReceiver.size() - 1; i >= 0; i--) {
331                 if (from.indexOfKey(uidReadyForReceiver.keyAt(i)) < 0) {
332                     uidReadyForReceiver.removeAt(i);
333                 }
334             }
335             for (int i = 0, size = from.size(); i < size; i++) {
336                 final int uid = from.keyAt(i);
337                 into.put(uid, from.valueAt(i));
338                 if (uidReadyForReceiver.indexOfKey(uid) < 0) {
339                     // uid is wanted but not ready.
340                     uidReadyForReceiver.put(uid, false);
341                 }
342             }
343         }
344 
dequeueDeferredBootCompletedBroadcast( boolean isAllUidReady)345         public @Nullable BroadcastRecord dequeueDeferredBootCompletedBroadcast(
346                 boolean isAllUidReady) {
347             BroadcastRecord next = dequeueDeferredBootCompletedBroadcast(
348                     mDeferredLockedBootCompletedBroadcasts,
349                     mUidReadyForLockedBootCompletedBroadcast, isAllUidReady);
350             if (next == null) {
351                 next = dequeueDeferredBootCompletedBroadcast(mDeferredBootCompletedBroadcasts,
352                         mUidReadyForBootCompletedBroadcast, isAllUidReady);
353             }
354             return next;
355         }
356 
dequeueDeferredBootCompletedBroadcast( SparseArray<BroadcastRecord> uid2br, SparseBooleanArray uidReadyForReceiver, boolean isAllUidReady)357         private @Nullable BroadcastRecord dequeueDeferredBootCompletedBroadcast(
358                 SparseArray<BroadcastRecord> uid2br, SparseBooleanArray uidReadyForReceiver,
359                 boolean isAllUidReady) {
360             for (int i = 0, size = uid2br.size(); i < size; i++) {
361                 final int uid = uid2br.keyAt(i);
362                 if (isAllUidReady || uidReadyForReceiver.get(uid)) {
363                     final BroadcastRecord br = uid2br.valueAt(i);
364                     if (DEBUG_BROADCAST_DEFERRAL) {
365                         final Object receiver = br.receivers.get(0);
366                         if (receiver instanceof BroadcastFilter) {
367                             if (DEBUG_BROADCAST_DEFERRAL) {
368                                 Slog.i(TAG, "getDeferredBootCompletedBroadcast uid:" + uid
369                                         + " BroadcastFilter:" + (BroadcastFilter) receiver
370                                         + " broadcast:" + br.intent.getAction());
371                             }
372                         } else /* if (receiver instanceof ResolveInfo) */ {
373                             ResolveInfo info = (ResolveInfo) receiver;
374                             String packageName = info.activityInfo.applicationInfo.packageName;
375                             if (DEBUG_BROADCAST_DEFERRAL) {
376                                 Slog.i(TAG, "getDeferredBootCompletedBroadcast uid:" + uid
377                                         + " packageName:" + packageName
378                                         + " broadcast:" + br.intent.getAction());
379                             }
380                         }
381                     }
382                     // remove the BroadcastRecord.
383                     uid2br.removeAt(i);
384                     if (uid2br.size() == 0) {
385                         // All deferred receivers are executed, do not need uidReadyForReceiver
386                         // any more.
387                         uidReadyForReceiver.clear();
388                     }
389                     return br;
390                 }
391             }
392             return null;
393         }
394 
getDeferredList(String action)395         private @Nullable SparseArray<BroadcastRecord> getDeferredList(String action) {
396             SparseArray<BroadcastRecord> brs = null;
397             if (action.equals(Intent.ACTION_LOCKED_BOOT_COMPLETED)) {
398                 brs = mDeferredLockedBootCompletedBroadcasts;
399             } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
400                 brs = mDeferredBootCompletedBroadcasts;
401             }
402             return brs;
403         }
404 
405         /**
406          * Return the total number of UIDs in all BroadcastRecord in
407          * {@link #mDeferredBootCompletedBroadcasts} or
408          * {@link #mDeferredLockedBootCompletedBroadcasts}
409          */
getBootCompletedBroadcastsUidsSize(String action)410         private int getBootCompletedBroadcastsUidsSize(String action) {
411             SparseArray<BroadcastRecord> brs = getDeferredList(action);
412             return brs != null ? brs.size() : 0;
413         }
414 
415         /**
416          * Return the total number of receivers in all BroadcastRecord in
417          * {@link #mDeferredBootCompletedBroadcasts} or
418          * {@link #mDeferredLockedBootCompletedBroadcasts}
419          */
getBootCompletedBroadcastsReceiversSize(String action)420         private int getBootCompletedBroadcastsReceiversSize(String action) {
421             SparseArray<BroadcastRecord> brs = getDeferredList(action);
422             if (brs == null) {
423                 return 0;
424             }
425             int size = 0;
426             for (int i = 0, s = brs.size(); i < s; i++) {
427                 size += brs.valueAt(i).receivers.size();
428             }
429             return size;
430         }
431 
432         @NeverCompile
dump(Dumper dumper, String action)433         public void dump(Dumper dumper, String action) {
434             SparseArray<BroadcastRecord> brs = getDeferredList(action);
435             if (brs == null) {
436                 return;
437             }
438             for (int i = 0, size = brs.size(); i < size; i++) {
439                 dumper.dump(brs.valueAt(i));
440             }
441         }
442 
443         @NeverCompile
dumpDebug(ProtoOutputStream proto, long fieldId)444         public void dumpDebug(ProtoOutputStream proto, long fieldId) {
445             for (int i = 0, size = mDeferredLockedBootCompletedBroadcasts.size(); i < size; i++) {
446                 mDeferredLockedBootCompletedBroadcasts.valueAt(i).dumpDebug(proto, fieldId);
447             }
448             for (int i = 0, size = mDeferredBootCompletedBroadcasts.size(); i < size; i++) {
449                 mDeferredBootCompletedBroadcasts.valueAt(i).dumpDebug(proto, fieldId);
450             }
451         }
452 
453         @NeverCompile
dumpBootCompletedBroadcastRecord(SparseArray<BroadcastRecord> brs)454         private void dumpBootCompletedBroadcastRecord(SparseArray<BroadcastRecord> brs) {
455             for (int i = 0, size = brs.size(); i < size; i++) {
456                 final Object receiver = brs.valueAt(i).receivers.get(0);
457                 String packageName = null;
458                 if (receiver instanceof BroadcastFilter) {
459                     BroadcastFilter recv = (BroadcastFilter) receiver;
460                     packageName = recv.receiverList.app.processName;
461                 } else /* if (receiver instanceof ResolveInfo) */ {
462                     ResolveInfo info = (ResolveInfo) receiver;
463                     packageName = info.activityInfo.applicationInfo.packageName;
464                 }
465                 Slog.i(TAG, "uid:" + brs.keyAt(i)
466                         + " packageName:" + packageName
467                         + " receivers:" + brs.valueAt(i).receivers.size());
468             }
469         }
470     }
471 
getDeferredPerUser(int userId)472     private DeferredBootCompletedBroadcastPerUser getDeferredPerUser(int userId) {
473         if (mUser2Deferred.contains(userId)) {
474             return mUser2Deferred.get(userId);
475         } else {
476             final DeferredBootCompletedBroadcastPerUser temp =
477                     new DeferredBootCompletedBroadcastPerUser(userId);
478             mUser2Deferred.put(userId, temp);
479             return temp;
480         }
481     }
482 
483     /**
484      * ActivityManagerService.attachApplication() call this method to notify that the UID is ready
485      * to accept deferred LOCKED_BOOT_COMPLETED and BOOT_COMPLETED broadcasts.
486      * @param uid
487      */
updateUidReadyForBootCompletedBroadcastLocked(int uid)488     public void updateUidReadyForBootCompletedBroadcastLocked(int uid) {
489         getDeferredPerUser(UserHandle.getUserId(uid)).updateUidReady(uid);
490     }
491 
dequeueDeferredBootCompletedBroadcast()492     private @Nullable BroadcastRecord dequeueDeferredBootCompletedBroadcast() {
493         final boolean isAllUidReady = (mQueue.mService.mConstants.mDeferBootCompletedBroadcast
494                 == DEFER_BOOT_COMPLETED_BROADCAST_NONE);
495         BroadcastRecord next = null;
496         for (int i = 0, size = mUser2Deferred.size(); i < size; i++) {
497             next = mUser2Deferred.valueAt(i).dequeueDeferredBootCompletedBroadcast(isAllUidReady);
498             if (next != null) {
499                 break;
500             }
501         }
502         return next;
503     }
504 
505     /**
506      * Constructed & sharing a lock with its associated BroadcastQueue instance
507      */
BroadcastDispatcher(BroadcastQueueImpl queue, BroadcastConstants constants, Handler handler, Object lock)508     public BroadcastDispatcher(BroadcastQueueImpl queue, BroadcastConstants constants,
509             Handler handler, Object lock) {
510         mQueue = queue;
511         mConstants = constants;
512         mHandler = handler;
513         mLock = lock;
514     }
515 
516     /**
517      * Spin up the integration with the alarm manager service; done lazily to manage
518      * service availability ordering during boot.
519      */
start()520     public void start() {
521         // Set up broadcast alarm tracking
522         mAlarm = LocalServices.getService(AlarmManagerInternal.class);
523         mAlarm.registerInFlightListener(mAlarmListener);
524     }
525 
526     /**
527      * Standard contents-are-empty check
528      */
isEmpty()529     public boolean isEmpty() {
530         synchronized (mLock) {
531             return isIdle()
532                     && getBootCompletedBroadcastsUidsSize(Intent.ACTION_LOCKED_BOOT_COMPLETED) == 0
533                     && getBootCompletedBroadcastsUidsSize(Intent.ACTION_BOOT_COMPLETED) == 0;
534         }
535     }
536 
537     /**
538      * Have less check than {@link #isEmpty()}.
539      * The dispatcher is considered as idle even with deferred LOCKED_BOOT_COMPLETED/BOOT_COMPLETED
540      * broadcasts because those can be deferred until the first time the uid's process is started.
541      * @return
542      */
isIdle()543     public boolean isIdle() {
544         synchronized (mLock) {
545             return mCurrentBroadcast == null
546                     && mOrderedBroadcasts.isEmpty()
547                     && mAlarmQueue.isEmpty()
548                     && isDeferralsListEmpty(mDeferredBroadcasts)
549                     && isDeferralsListEmpty(mAlarmDeferrals);
550         }
551     }
552 
isDeferralsBeyondBarrier(@onNull ArrayList<Deferrals> list, @UptimeMillisLong long barrierTime)553     private static boolean isDeferralsBeyondBarrier(@NonNull ArrayList<Deferrals> list,
554             @UptimeMillisLong long barrierTime) {
555         for (int i = 0; i < list.size(); i++) {
556             if (!isBeyondBarrier(list.get(i).broadcasts, barrierTime)) {
557                 return false;
558             }
559         }
560         return true;
561     }
562 
isBeyondBarrier(@onNull ArrayList<BroadcastRecord> list, @UptimeMillisLong long barrierTime)563     private static boolean isBeyondBarrier(@NonNull ArrayList<BroadcastRecord> list,
564             @UptimeMillisLong long barrierTime) {
565         for (int i = 0; i < list.size(); i++) {
566             if (list.get(i).enqueueTime <= barrierTime) {
567                 return false;
568             }
569         }
570         return true;
571     }
572 
isBeyondBarrier(@ptimeMillisLong long barrierTime)573     public boolean isBeyondBarrier(@UptimeMillisLong long barrierTime) {
574         synchronized (mLock) {
575             if ((mCurrentBroadcast != null) && mCurrentBroadcast.enqueueTime <= barrierTime) {
576                 return false;
577             }
578             return isBeyondBarrier(mOrderedBroadcasts, barrierTime)
579                     && isBeyondBarrier(mAlarmQueue, barrierTime)
580                     && isDeferralsBeyondBarrier(mDeferredBroadcasts, barrierTime)
581                     && isDeferralsBeyondBarrier(mAlarmDeferrals, barrierTime);
582         }
583     }
584 
isDispatchedInDeferrals(@onNull ArrayList<Deferrals> list, @NonNull Intent intent)585     private static boolean isDispatchedInDeferrals(@NonNull ArrayList<Deferrals> list,
586             @NonNull Intent intent) {
587         for (int i = 0; i < list.size(); i++) {
588             if (!isDispatched(list.get(i).broadcasts, intent)) {
589                 return false;
590             }
591         }
592         return true;
593     }
594 
isDispatched(@onNull ArrayList<BroadcastRecord> list, @NonNull Intent intent)595     private static boolean isDispatched(@NonNull ArrayList<BroadcastRecord> list,
596             @NonNull Intent intent) {
597         for (int i = 0; i < list.size(); i++) {
598             if (intent.filterEquals(list.get(i).intent)) {
599                 return false;
600             }
601         }
602         return true;
603     }
604 
isDispatched(@onNull Intent intent)605     public boolean isDispatched(@NonNull Intent intent) {
606         synchronized (mLock) {
607             if ((mCurrentBroadcast != null) && intent.filterEquals(mCurrentBroadcast.intent)) {
608                 return false;
609             }
610             return isDispatched(mOrderedBroadcasts, intent)
611                     && isDispatched(mAlarmQueue, intent)
612                     && isDispatchedInDeferrals(mDeferredBroadcasts, intent)
613                     && isDispatchedInDeferrals(mAlarmDeferrals, intent);
614         }
615     }
616 
pendingInDeferralsList(ArrayList<Deferrals> list)617     private static int pendingInDeferralsList(ArrayList<Deferrals> list) {
618         int pending = 0;
619         final int numEntries = list.size();
620         for (int i = 0; i < numEntries; i++) {
621             pending += list.get(i).size();
622         }
623         return pending;
624     }
625 
isDeferralsListEmpty(ArrayList<Deferrals> list)626     private static boolean isDeferralsListEmpty(ArrayList<Deferrals> list) {
627         return pendingInDeferralsList(list) == 0;
628     }
629 
630     /**
631      * Strictly for logging, describe the currently pending contents in a human-
632      * readable way
633      */
describeStateLocked()634     public String describeStateLocked() {
635         final StringBuilder sb = new StringBuilder(128);
636         if (mCurrentBroadcast != null) {
637             sb.append("1 in flight, ");
638         }
639         sb.append(mOrderedBroadcasts.size());
640         sb.append(" ordered");
641         int n = mAlarmQueue.size();
642         if (n > 0) {
643             sb.append(", ");
644             sb.append(n);
645             sb.append(" alarms");
646         }
647         n = pendingInDeferralsList(mAlarmDeferrals);
648         if (n > 0) {
649             sb.append(", ");
650             sb.append(n);
651             sb.append(" deferrals in alarm recipients");
652         }
653         n = pendingInDeferralsList(mDeferredBroadcasts);
654         if (n > 0) {
655             sb.append(", ");
656             sb.append(n);
657             sb.append(" deferred");
658         }
659         n = getBootCompletedBroadcastsUidsSize(Intent.ACTION_LOCKED_BOOT_COMPLETED);
660         if (n > 0) {
661             sb.append(", ");
662             sb.append(n);
663             sb.append(" deferred LOCKED_BOOT_COMPLETED/");
664             sb.append(getBootCompletedBroadcastsReceiversSize(Intent.ACTION_LOCKED_BOOT_COMPLETED));
665             sb.append(" receivers");
666         }
667 
668         n = getBootCompletedBroadcastsUidsSize(Intent.ACTION_BOOT_COMPLETED);
669         if (n > 0) {
670             sb.append(", ");
671             sb.append(n);
672             sb.append(" deferred BOOT_COMPLETED/");
673             sb.append(getBootCompletedBroadcastsReceiversSize(Intent.ACTION_BOOT_COMPLETED));
674             sb.append(" receivers");
675         }
676         return sb.toString();
677     }
678 
679     // ----------------------------------
680     // BroadcastQueue operation support
enqueueOrderedBroadcastLocked(BroadcastRecord r)681     void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
682         final ArrayList<BroadcastRecord> queue =
683                 (r.alarm && mQueue.mService.mConstants.mPrioritizeAlarmBroadcasts)
684                         ? mAlarmQueue
685                         : mOrderedBroadcasts;
686 
687         if (r.receivers == null || r.receivers.isEmpty()) {
688             // Fast no-op path for broadcasts that won't actually be dispatched to
689             // receivers - we still need to handle completion callbacks and historical
690             // records, but we don't need to consider the fancy cases.
691             queue.add(r);
692             return;
693         }
694 
695         if (Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(r.intent.getAction())) {
696             // Create one BroadcastRecord for each UID that can be deferred.
697             final SparseArray<BroadcastRecord> deferred =
698                     r.splitDeferredBootCompletedBroadcastLocked(mQueue.mService.mInternal,
699                             mQueue.mService.mConstants.mDeferBootCompletedBroadcast);
700             getDeferredPerUser(r.userId).enqueueBootCompletedBroadcasts(
701                     Intent.ACTION_LOCKED_BOOT_COMPLETED, deferred);
702             if (!r.receivers.isEmpty()) {
703                 // The non-deferred receivers.
704                 mOrderedBroadcasts.add(r);
705                 return;
706             }
707         } else if (Intent.ACTION_BOOT_COMPLETED.equals(r.intent.getAction())) {
708             // Create one BroadcastRecord for each UID that can be deferred.
709             final SparseArray<BroadcastRecord> deferred =
710                     r.splitDeferredBootCompletedBroadcastLocked(mQueue.mService.mInternal,
711                             mQueue.mService.mConstants.mDeferBootCompletedBroadcast);
712             getDeferredPerUser(r.userId).enqueueBootCompletedBroadcasts(
713                     Intent.ACTION_BOOT_COMPLETED, deferred);
714             if (!r.receivers.isEmpty()) {
715                 // The non-deferred receivers.
716                 mOrderedBroadcasts.add(r);
717                 return;
718             }
719         } else {
720             // Ordinary broadcast, so put it on the appropriate queue and carry on
721             queue.add(r);
722         }
723     }
724 
725     /**
726      * Return the total number of UIDs in all deferred boot completed BroadcastRecord.
727      */
getBootCompletedBroadcastsUidsSize(String action)728     private int getBootCompletedBroadcastsUidsSize(String action) {
729         int size = 0;
730         for (int i = 0, s = mUser2Deferred.size(); i < s; i++) {
731             size += mUser2Deferred.valueAt(i).getBootCompletedBroadcastsUidsSize(action);
732         }
733         return size;
734     }
735 
736     /**
737      * Return the total number of receivers in all deferred boot completed BroadcastRecord.
738      */
getBootCompletedBroadcastsReceiversSize(String action)739     private int getBootCompletedBroadcastsReceiversSize(String action) {
740         int size = 0;
741         for (int i = 0, s = mUser2Deferred.size(); i < s; i++) {
742             size += mUser2Deferred.valueAt(i).getBootCompletedBroadcastsReceiversSize(action);
743         }
744         return size;
745     }
746 
747     // Returns the now-replaced broadcast record, or null if none
replaceBroadcastLocked(BroadcastRecord r, String typeForLogging)748     BroadcastRecord replaceBroadcastLocked(BroadcastRecord r, String typeForLogging) {
749         // Simple case, in the ordinary queue.
750         BroadcastRecord old = replaceBroadcastLocked(mOrderedBroadcasts, r, typeForLogging);
751         // ... or possibly in the simple alarm queue
752         if (old == null) {
753             old = replaceBroadcastLocked(mAlarmQueue, r, typeForLogging);
754         }
755         // If we didn't find it, less-simple:  in a deferral queue?
756         if (old == null) {
757             old = replaceDeferredBroadcastLocked(mAlarmDeferrals, r, typeForLogging);
758         }
759         if (old == null) {
760             old = replaceDeferredBroadcastLocked(mDeferredBroadcasts, r, typeForLogging);
761         }
762         return old;
763     }
764 
replaceDeferredBroadcastLocked(ArrayList<Deferrals> list, BroadcastRecord r, String typeForLogging)765     private BroadcastRecord replaceDeferredBroadcastLocked(ArrayList<Deferrals> list,
766             BroadcastRecord r, String typeForLogging) {
767         BroadcastRecord old;
768         final int numEntries = list.size();
769         for (int i = 0; i < numEntries; i++) {
770             final Deferrals d = list.get(i);
771             old = replaceBroadcastLocked(d.broadcasts, r, typeForLogging);
772             if (old != null) {
773                 return old;
774             }
775         }
776         return null;
777     }
778 
replaceBroadcastLocked(ArrayList<BroadcastRecord> list, BroadcastRecord r, String typeForLogging)779     private BroadcastRecord replaceBroadcastLocked(ArrayList<BroadcastRecord> list,
780             BroadcastRecord r, String typeForLogging) {
781         BroadcastRecord old;
782         final Intent intent = r.intent;
783         // Any in-flight broadcast has already been popped, and cannot be replaced.
784         // (This preserves existing behavior of the replacement API)
785         for (int i = list.size() - 1; i >= 0; i--) {
786             old = list.get(i);
787             if (old.userId == r.userId && intent.filterEquals(old.intent)) {
788                 if (DEBUG_BROADCAST) {
789                     Slog.v(TAG, "***** Replacing " + typeForLogging
790                             + " [" + mQueue.mQueueName + "]: " + intent);
791                 }
792                 // Clone deferral state too if any
793                 r.deferred = old.deferred;
794                 list.set(i, r);
795                 return old;
796             }
797         }
798         return null;
799     }
800 
cleanupDisabledPackageReceiversLocked(final String packageName, Set<String> filterByClasses, final int userId, final boolean doit)801     boolean cleanupDisabledPackageReceiversLocked(final String packageName,
802             Set<String> filterByClasses, final int userId, final boolean doit) {
803         // Note: fast short circuits when 'doit' is false, as soon as we hit any
804         // "yes we would do something" circumstance
805         boolean didSomething = cleanupBroadcastListDisabledReceiversLocked(mOrderedBroadcasts,
806                 packageName, filterByClasses, userId, doit);
807         if (doit || !didSomething) {
808             didSomething = cleanupBroadcastListDisabledReceiversLocked(mAlarmQueue,
809                     packageName, filterByClasses, userId, doit);
810         }
811         if (doit || !didSomething) {
812             ArrayList<BroadcastRecord> lockedBootCompletedBroadcasts = new ArrayList<>();
813             for (int u = 0, usize = mUser2Deferred.size(); u < usize; u++) {
814                 SparseArray<BroadcastRecord> brs =
815                         mUser2Deferred.valueAt(u).mDeferredLockedBootCompletedBroadcasts;
816                 for (int i = 0, size = brs.size(); i < size; i++) {
817                     lockedBootCompletedBroadcasts.add(brs.valueAt(i));
818                 }
819             }
820             didSomething = cleanupBroadcastListDisabledReceiversLocked(
821                     lockedBootCompletedBroadcasts,
822                     packageName, filterByClasses, userId, doit);
823         }
824         if (doit || !didSomething) {
825             ArrayList<BroadcastRecord> bootCompletedBroadcasts = new ArrayList<>();
826             for (int u = 0, usize = mUser2Deferred.size(); u < usize; u++) {
827                 SparseArray<BroadcastRecord> brs =
828                         mUser2Deferred.valueAt(u).mDeferredBootCompletedBroadcasts;
829                 for (int i = 0, size = brs.size(); i < size; i++) {
830                     bootCompletedBroadcasts.add(brs.valueAt(i));
831                 }
832             }
833             didSomething = cleanupBroadcastListDisabledReceiversLocked(bootCompletedBroadcasts,
834                     packageName, filterByClasses, userId, doit);
835         }
836         if (doit || !didSomething) {
837             didSomething |= cleanupDeferralsListDisabledReceiversLocked(mAlarmDeferrals,
838                     packageName, filterByClasses, userId, doit);
839         }
840         if (doit || !didSomething) {
841             didSomething |= cleanupDeferralsListDisabledReceiversLocked(mDeferredBroadcasts,
842                     packageName, filterByClasses, userId, doit);
843         }
844         if ((doit || !didSomething) && mCurrentBroadcast != null) {
845             didSomething |= mCurrentBroadcast.cleanupDisabledPackageReceiversLocked(
846                     packageName, filterByClasses, userId, doit);
847         }
848 
849         return didSomething;
850     }
851 
cleanupDeferralsListDisabledReceiversLocked(ArrayList<Deferrals> list, final String packageName, Set<String> filterByClasses, final int userId, final boolean doit)852     private boolean cleanupDeferralsListDisabledReceiversLocked(ArrayList<Deferrals> list,
853             final String packageName, Set<String> filterByClasses, final int userId,
854             final boolean doit) {
855         boolean didSomething = false;
856         for (Deferrals d : list) {
857             didSomething = cleanupBroadcastListDisabledReceiversLocked(d.broadcasts,
858                     packageName, filterByClasses, userId, doit);
859             if (!doit && didSomething) {
860                 return true;
861             }
862         }
863         return didSomething;
864     }
865 
cleanupBroadcastListDisabledReceiversLocked(ArrayList<BroadcastRecord> list, final String packageName, Set<String> filterByClasses, final int userId, final boolean doit)866     private boolean cleanupBroadcastListDisabledReceiversLocked(ArrayList<BroadcastRecord> list,
867             final String packageName, Set<String> filterByClasses, final int userId,
868             final boolean doit) {
869         boolean didSomething = false;
870         for (BroadcastRecord br : list) {
871             didSomething |= br.cleanupDisabledPackageReceiversLocked(packageName,
872                     filterByClasses, userId, doit);
873             if (!doit && didSomething) {
874                 return true;
875             }
876         }
877         return didSomething;
878     }
879 
880     /**
881      * Standard proto dump entry point
882      */
883     @NeverCompile
dumpDebug(ProtoOutputStream proto, long fieldId)884     public void dumpDebug(ProtoOutputStream proto, long fieldId) {
885         if (mCurrentBroadcast != null) {
886             mCurrentBroadcast.dumpDebug(proto, fieldId);
887         }
888         for (Deferrals d : mAlarmDeferrals) {
889             d.dumpDebug(proto, fieldId);
890         }
891         for (BroadcastRecord br : mOrderedBroadcasts) {
892             br.dumpDebug(proto, fieldId);
893         }
894         for (BroadcastRecord br : mAlarmQueue) {
895             br.dumpDebug(proto, fieldId);
896         }
897         for (Deferrals d : mDeferredBroadcasts) {
898             d.dumpDebug(proto, fieldId);
899         }
900 
901         for (int i = 0, size = mUser2Deferred.size(); i < size; i++) {
902             mUser2Deferred.valueAt(i).dumpDebug(proto, fieldId);
903         }
904     }
905 
906     // ----------------------------------
907     // Dispatch & deferral management
908 
getActiveBroadcastLocked()909     public BroadcastRecord getActiveBroadcastLocked() {
910         return mCurrentBroadcast;
911     }
912 
913     /**
914      * If there is a deferred broadcast that is being sent to an alarm target, return
915      * that one.  If there's no deferred alarm target broadcast but there is one
916      * that has reached the end of its deferral, return that.
917      *
918      * This stages the broadcast internally until it is retired, and returns that
919      * staged record if this is called repeatedly, until retireBroadcast(r) is called.
920      */
getNextBroadcastLocked(final long now)921     public BroadcastRecord getNextBroadcastLocked(final long now) {
922         if (mCurrentBroadcast != null) {
923             return mCurrentBroadcast;
924         }
925 
926         BroadcastRecord next = null;
927 
928         // Alarms in flight take precedence over everything else.  This queue
929         // will be non-empty only when the relevant policy is in force, but if
930         // policy has changed on the fly we still need to drain this before we
931         // settle into the legacy behavior.
932         if (!mAlarmQueue.isEmpty()) {
933             next = mAlarmQueue.remove(0);
934         }
935 
936         // Next in precedence are deferred BOOT_COMPLETED broadcasts
937         if (next == null) {
938             next = dequeueDeferredBootCompletedBroadcast();
939         }
940 
941         // Alarm-related deferrals are next in precedence...
942         if (next == null && !mAlarmDeferrals.isEmpty()) {
943             next = popLocked(mAlarmDeferrals);
944             if (DEBUG_BROADCAST_DEFERRAL && next != null) {
945                 Slog.i(TAG, "Next broadcast from alarm targets: " + next);
946             }
947         }
948 
949         final boolean someQueued = !mOrderedBroadcasts.isEmpty();
950 
951         if (next == null && !mDeferredBroadcasts.isEmpty()) {
952             // A this point we're going to deliver either:
953             // 1. the next "overdue" deferral; or
954             // 2. the next ordinary ordered broadcast; *or*
955             // 3. the next not-yet-overdue deferral.
956 
957             for (int i = 0; i < mDeferredBroadcasts.size(); i++) {
958                 Deferrals d = mDeferredBroadcasts.get(i);
959                 if (now < d.deferUntil && someQueued) {
960                     // stop looking when we haven't hit the next time-out boundary
961                     // but only if we have un-deferred broadcasts waiting,
962                     // otherwise we can deliver whatever deferred broadcast
963                     // is next available.
964                     break;
965                 }
966 
967                 if (d.broadcasts.size() > 0) {
968                     next = d.broadcasts.remove(0);
969                     // apply deferral-interval decay policy and move this uid's
970                     // deferred broadcasts down in the delivery queue accordingly
971                     mDeferredBroadcasts.remove(i); // already 'd'
972                     d.deferredBy = calculateDeferral(d.deferredBy);
973                     d.deferUntil += d.deferredBy;
974                     insertLocked(mDeferredBroadcasts, d);
975                     if (DEBUG_BROADCAST_DEFERRAL) {
976                         Slog.i(TAG, "Next broadcast from deferrals " + next
977                                 + ", deferUntil now " + d.deferUntil);
978                     }
979                     break;
980                 }
981             }
982         }
983 
984         if (next == null && someQueued) {
985             next = mOrderedBroadcasts.remove(0);
986             if (DEBUG_BROADCAST_DEFERRAL) {
987                 Slog.i(TAG, "Next broadcast from main queue: " + next);
988             }
989         }
990 
991         mCurrentBroadcast = next;
992         return next;
993     }
994 
995     /**
996      * Called after the broadcast queue finishes processing the currently
997      * active broadcast (obtained by calling getNextBroadcastLocked()).
998      */
retireBroadcastLocked(final BroadcastRecord r)999     public void retireBroadcastLocked(final BroadcastRecord r) {
1000         // ERROR if 'r' is not the active broadcast
1001         if (r != mCurrentBroadcast) {
1002             Slog.wtf(TAG, "Retiring broadcast " + r
1003                     + " doesn't match current outgoing " + mCurrentBroadcast);
1004         }
1005         mCurrentBroadcast = null;
1006     }
1007 
1008     /**
1009      * Called prior to broadcast dispatch to check whether the intended
1010      * recipient is currently subject to deferral policy.
1011      */
isDeferringLocked(final int uid)1012     public boolean isDeferringLocked(final int uid) {
1013         Deferrals d = findUidLocked(uid);
1014         if (d != null && d.broadcasts.isEmpty()) {
1015             // once we've caught up with deferred broadcasts to this uid
1016             // and time has advanced sufficiently that we wouldn't be
1017             // deferring newly-enqueued ones, we're back to normal policy.
1018             if (SystemClock.uptimeMillis() >= d.deferUntil) {
1019                 if (DEBUG_BROADCAST_DEFERRAL) {
1020                     Slog.i(TAG, "No longer deferring broadcasts to uid " + d.uid);
1021                 }
1022                 removeDeferral(d);
1023                 return false;
1024             }
1025         }
1026         return (d != null);
1027     }
1028 
1029     /**
1030      * Defer broadcasts for the given app.  If 'br' is non-null, this also makes
1031      * sure that broadcast record is enqueued as the next upcoming broadcast for
1032      * the app.
1033      */
startDeferring(final int uid)1034     public void startDeferring(final int uid) {
1035         synchronized (mLock) {
1036             Deferrals d = findUidLocked(uid);
1037 
1038             // If we're not yet tracking this app, set up that bookkeeping
1039             if (d == null) {
1040                 // Start a new deferral
1041                 final long now = SystemClock.uptimeMillis();
1042                 d = new Deferrals(uid,
1043                         now,
1044                         mConstants.DEFERRAL,
1045                         mAlarmUids.get(uid, 0));
1046                 if (DEBUG_BROADCAST_DEFERRAL) {
1047                     Slog.i(TAG, "Now deferring broadcasts to " + uid
1048                             + " until " + d.deferUntil);
1049                 }
1050                 // where it goes depends on whether it is coming into an alarm-related situation
1051                 if (d.alarmCount == 0) {
1052                     // common case, put it in the ordinary priority queue
1053                     insertLocked(mDeferredBroadcasts, d);
1054                     scheduleDeferralCheckLocked(true);
1055                 } else {
1056                     // alarm-related: strict order-encountered
1057                     mAlarmDeferrals.add(d);
1058                 }
1059             } else {
1060                 // We're already deferring, but something was slow again.  Reset the
1061                 // deferral decay progression.
1062                 d.deferredBy = mConstants.DEFERRAL;
1063                 if (DEBUG_BROADCAST_DEFERRAL) {
1064                     Slog.i(TAG, "Uid " + uid + " slow again, deferral interval reset to "
1065                             + d.deferredBy);
1066                 }
1067             }
1068         }
1069     }
1070 
1071     /**
1072      * Key entry point when a broadcast about to be delivered is instead
1073      * set aside for deferred delivery
1074      */
addDeferredBroadcast(final int uid, BroadcastRecord br)1075     public void addDeferredBroadcast(final int uid, BroadcastRecord br) {
1076         if (DEBUG_BROADCAST_DEFERRAL) {
1077             Slog.i(TAG, "Enqueuing deferred broadcast " + br);
1078         }
1079         synchronized (mLock) {
1080             Deferrals d = findUidLocked(uid);
1081             if (d == null) {
1082                 Slog.wtf(TAG, "Adding deferred broadcast but not tracking " + uid);
1083             } else {
1084                 if (br == null) {
1085                     Slog.wtf(TAG, "Deferring null broadcast to " + uid);
1086                 } else {
1087                     br.deferred = true;
1088                     d.add(br);
1089                 }
1090             }
1091         }
1092     }
1093 
1094     /**
1095      * When there are deferred broadcasts, we need to make sure to recheck the
1096      * dispatch queue when they come due.  Alarm-sensitive deferrals get dispatched
1097      * aggressively, so we only need to use the ordinary deferrals timing to figure
1098      * out when to recheck.
1099      */
scheduleDeferralCheckLocked(boolean force)1100     public void scheduleDeferralCheckLocked(boolean force) {
1101         if ((force || !mRecheckScheduled) && !mDeferredBroadcasts.isEmpty()) {
1102             final Deferrals d = mDeferredBroadcasts.get(0);
1103             if (!d.broadcasts.isEmpty()) {
1104                 mHandler.removeCallbacks(mScheduleRunnable);
1105                 mHandler.postAtTime(mScheduleRunnable, d.deferUntil);
1106                 mRecheckScheduled = true;
1107                 if (DEBUG_BROADCAST_DEFERRAL) {
1108                     Slog.i(TAG, "Scheduling deferred broadcast recheck at " + d.deferUntil);
1109                 }
1110             }
1111         }
1112     }
1113 
1114     /**
1115      * Cancel all current deferrals; that is, make all currently-deferred broadcasts
1116      * immediately deliverable.  Used by the wait-for-broadcast-idle mechanism.
1117      */
cancelDeferralsLocked()1118     public void cancelDeferralsLocked() {
1119         zeroDeferralTimes(mAlarmDeferrals);
1120         zeroDeferralTimes(mDeferredBroadcasts);
1121     }
1122 
zeroDeferralTimes(ArrayList<Deferrals> list)1123     private static void zeroDeferralTimes(ArrayList<Deferrals> list) {
1124         final int num = list.size();
1125         for (int i = 0; i < num; i++) {
1126             Deferrals d = list.get(i);
1127             // Safe to do this in-place because it won't break ordering
1128             d.deferUntil = d.deferredBy = 0;
1129         }
1130     }
1131 
1132     // ----------------------------------
1133 
1134     /**
1135      * If broadcasts to this uid are being deferred, find the deferrals record about it.
1136      * @return null if this uid's broadcasts are not being deferred
1137      */
findUidLocked(final int uid)1138     private Deferrals findUidLocked(final int uid) {
1139         // The common case is that they it isn't also an alarm target...
1140         Deferrals d = findUidLocked(uid, mDeferredBroadcasts);
1141         // ...but if not there, also check alarm-prioritized deferrals
1142         if (d == null) {
1143             d = findUidLocked(uid, mAlarmDeferrals);
1144         }
1145         return d;
1146     }
1147 
1148     /**
1149      * Remove the given deferral record from whichever queue it might be in at present
1150      * @return true if the deferral was in fact found, false if this made no changes
1151      */
removeDeferral(Deferrals d)1152     private boolean removeDeferral(Deferrals d) {
1153         boolean didRemove = mDeferredBroadcasts.remove(d);
1154         if (!didRemove) {
1155             didRemove = mAlarmDeferrals.remove(d);
1156         }
1157         return didRemove;
1158     }
1159 
1160     /**
1161      * Find the deferrals record for the given uid in the given list
1162      */
findUidLocked(final int uid, ArrayList<Deferrals> list)1163     private static Deferrals findUidLocked(final int uid, ArrayList<Deferrals> list) {
1164         final int numElements = list.size();
1165         for (int i = 0; i < numElements; i++) {
1166             Deferrals d = list.get(i);
1167             if (uid == d.uid) {
1168                 return d;
1169             }
1170         }
1171         return null;
1172     }
1173 
1174     /**
1175      * Pop the next broadcast record from the head of the given deferrals list,
1176      * if one exists.
1177      */
popLocked(ArrayList<Deferrals> list)1178     private static BroadcastRecord popLocked(ArrayList<Deferrals> list) {
1179         final Deferrals d = list.get(0);
1180         return d.broadcasts.isEmpty() ? null : d.broadcasts.remove(0);
1181     }
1182 
1183     /**
1184      * Insert the given Deferrals into the priority queue, sorted by defer-until milestone
1185      */
insertLocked(ArrayList<Deferrals> list, Deferrals d)1186     private static void insertLocked(ArrayList<Deferrals> list, Deferrals d) {
1187         // Simple linear search is appropriate here because we expect to
1188         // have very few entries in the deferral lists (i.e. very few badly-
1189         // behaving apps currently facing deferral)
1190         int i;
1191         final int numElements = list.size();
1192         for (i = 0; i < numElements; i++) {
1193             if (d.deferUntil < list.get(i).deferUntil) {
1194                 break;
1195             }
1196         }
1197         list.add(i, d);
1198     }
1199 
1200     /**
1201      * Calculate a new deferral time based on the previous time.  This should decay
1202      * toward zero, though a small nonzero floor is an option.
1203      */
calculateDeferral(long previous)1204     private long calculateDeferral(long previous) {
1205         return Math.max(mConstants.DEFERRAL_FLOOR,
1206                 (long) (previous * mConstants.DEFERRAL_DECAY_FACTOR));
1207     }
1208 
1209     // ----------------------------------
1210 
1211     @NeverCompile
dumpLocked(PrintWriter pw, String dumpPackage, String queueName, SimpleDateFormat sdf)1212     boolean dumpLocked(PrintWriter pw, String dumpPackage, String queueName,
1213             SimpleDateFormat sdf) {
1214         final Dumper dumper = new Dumper(pw, queueName, dumpPackage, sdf);
1215         boolean printed = false;
1216 
1217         dumper.setHeading("Currently in flight");
1218         dumper.setLabel("In-Flight Ordered Broadcast");
1219         if (mCurrentBroadcast != null) {
1220             dumper.dump(mCurrentBroadcast);
1221         } else {
1222             pw.println("  (null)");
1223         }
1224         printed |= dumper.didPrint();
1225 
1226         dumper.setHeading("Active alarm broadcasts");
1227         dumper.setLabel("Active Alarm Broadcast");
1228         for (BroadcastRecord br : mAlarmQueue) {
1229             dumper.dump(br);
1230         }
1231         printed |= dumper.didPrint();
1232 
1233         dumper.setHeading("Active ordered broadcasts");
1234         dumper.setLabel("Active Ordered Broadcast");
1235         for (Deferrals d : mAlarmDeferrals) {
1236             d.dumpLocked(dumper);
1237         }
1238         for (BroadcastRecord br : mOrderedBroadcasts) {
1239             dumper.dump(br);
1240         }
1241         printed |= dumper.didPrint();
1242 
1243         dumper.setHeading("Deferred ordered broadcasts");
1244         dumper.setLabel("Deferred Ordered Broadcast");
1245         for (Deferrals d : mDeferredBroadcasts) {
1246             d.dumpLocked(dumper);
1247         }
1248         printed |= dumper.didPrint();
1249 
1250         dumper.setHeading("Deferred LOCKED_BOOT_COMPLETED broadcasts");
1251         dumper.setLabel("Deferred LOCKED_BOOT_COMPLETED Broadcast");
1252         for (int i = 0, size = mUser2Deferred.size(); i < size; i++) {
1253             mUser2Deferred.valueAt(i).dump(dumper, Intent.ACTION_LOCKED_BOOT_COMPLETED);
1254         }
1255         printed |= dumper.didPrint();
1256 
1257         dumper.setHeading("Deferred BOOT_COMPLETED broadcasts");
1258         dumper.setLabel("Deferred BOOT_COMPLETED Broadcast");
1259         for (int i = 0, size = mUser2Deferred.size(); i < size; i++) {
1260             mUser2Deferred.valueAt(i).dump(dumper, Intent.ACTION_BOOT_COMPLETED);
1261         }
1262         printed |= dumper.didPrint();
1263 
1264         return printed;
1265     }
1266 }
1267