BroadcastQueue.java revision 684bf34ee8acc41931fac23762b13e14a22011db
1/*
2 * Copyright (C) 2012 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
17package com.android.server.am;
18
19import java.io.FileDescriptor;
20import java.io.PrintWriter;
21import java.util.ArrayList;
22
23import android.app.ActivityManager;
24import android.app.AppGlobals;
25import android.app.AppOpsManager;
26import android.content.ComponentName;
27import android.content.IIntentReceiver;
28import android.content.Intent;
29import android.content.pm.ActivityInfo;
30import android.content.pm.PackageManager;
31import android.content.pm.ResolveInfo;
32import android.os.Bundle;
33import android.os.Handler;
34import android.os.IBinder;
35import android.os.Looper;
36import android.os.Message;
37import android.os.Process;
38import android.os.RemoteException;
39import android.os.SystemClock;
40import android.os.UserHandle;
41import android.util.EventLog;
42import android.util.Log;
43import android.util.Slog;
44
45/**
46 * BROADCASTS
47 *
48 * We keep two broadcast queues and associated bookkeeping, one for those at
49 * foreground priority, and one for normal (background-priority) broadcasts.
50 */
51public final class BroadcastQueue {
52    static final String TAG = "BroadcastQueue";
53    static final String TAG_MU = ActivityManagerService.TAG_MU;
54    static final boolean DEBUG_BROADCAST = ActivityManagerService.DEBUG_BROADCAST;
55    static final boolean DEBUG_BROADCAST_LIGHT = ActivityManagerService.DEBUG_BROADCAST_LIGHT;
56    static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
57
58    static final int MAX_BROADCAST_HISTORY = ActivityManager.isLowRamDeviceStatic() ? 10 : 50;
59    static final int MAX_BROADCAST_SUMMARY_HISTORY
60            = ActivityManager.isLowRamDeviceStatic() ? 25 : 300;
61
62    final ActivityManagerService mService;
63
64    /**
65     * Recognizable moniker for this queue
66     */
67    final String mQueueName;
68
69    /**
70     * Timeout period for this queue's broadcasts
71     */
72    final long mTimeoutPeriod;
73
74    /**
75     * If true, we can delay broadcasts while waiting services to finish in the previous
76     * receiver's process.
77     */
78    final boolean mDelayBehindServices;
79
80    /**
81     * Lists of all active broadcasts that are to be executed immediately
82     * (without waiting for another broadcast to finish).  Currently this only
83     * contains broadcasts to registered receivers, to avoid spinning up
84     * a bunch of processes to execute IntentReceiver components.  Background-
85     * and foreground-priority broadcasts are queued separately.
86     */
87    final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>();
88
89    /**
90     * List of all active broadcasts that are to be executed one at a time.
91     * The object at the top of the list is the currently activity broadcasts;
92     * those after it are waiting for the top to finish.  As with parallel
93     * broadcasts, separate background- and foreground-priority queues are
94     * maintained.
95     */
96    final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>();
97
98    /**
99     * Historical data of past broadcasts, for debugging.
100     */
101    final BroadcastRecord[] mBroadcastHistory = new BroadcastRecord[MAX_BROADCAST_HISTORY];
102
103    /**
104     * Summary of historical data of past broadcasts, for debugging.
105     */
106    final Intent[] mBroadcastSummaryHistory = new Intent[MAX_BROADCAST_SUMMARY_HISTORY];
107
108    /**
109     * Set when we current have a BROADCAST_INTENT_MSG in flight.
110     */
111    boolean mBroadcastsScheduled = false;
112
113    /**
114     * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
115     */
116    boolean mPendingBroadcastTimeoutMessage;
117
118    /**
119     * Intent broadcasts that we have tried to start, but are
120     * waiting for the application's process to be created.  We only
121     * need one per scheduling class (instead of a list) because we always
122     * process broadcasts one at a time, so no others can be started while
123     * waiting for this one.
124     */
125    BroadcastRecord mPendingBroadcast = null;
126
127    /**
128     * The receiver index that is pending, to restart the broadcast if needed.
129     */
130    int mPendingBroadcastRecvIndex;
131
132    static final int BROADCAST_INTENT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG;
133    static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1;
134
135    final BroadcastHandler mHandler;
136
137    private final class BroadcastHandler extends Handler {
138        public BroadcastHandler(Looper looper) {
139            super(looper, null, true);
140        }
141
142        @Override
143        public void handleMessage(Message msg) {
144            switch (msg.what) {
145                case BROADCAST_INTENT_MSG: {
146                    if (DEBUG_BROADCAST) Slog.v(
147                            TAG, "Received BROADCAST_INTENT_MSG");
148                    processNextBroadcast(true);
149                } break;
150                case BROADCAST_TIMEOUT_MSG: {
151                    synchronized (mService) {
152                        broadcastTimeoutLocked(true);
153                    }
154                } break;
155            }
156        }
157    };
158
159    private final class AppNotResponding implements Runnable {
160        private final ProcessRecord mApp;
161        private final String mAnnotation;
162
163        public AppNotResponding(ProcessRecord app, String annotation) {
164            mApp = app;
165            mAnnotation = annotation;
166        }
167
168        @Override
169        public void run() {
170            mService.appNotResponding(mApp, null, null, false, mAnnotation);
171        }
172    }
173
174    BroadcastQueue(ActivityManagerService service, Handler handler,
175            String name, long timeoutPeriod, boolean allowDelayBehindServices) {
176        mService = service;
177        mHandler = new BroadcastHandler(handler.getLooper());
178        mQueueName = name;
179        mTimeoutPeriod = timeoutPeriod;
180        mDelayBehindServices = allowDelayBehindServices;
181    }
182
183    public boolean isPendingBroadcastProcessLocked(int pid) {
184        return mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid;
185    }
186
187    public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
188        mParallelBroadcasts.add(r);
189    }
190
191    public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
192        mOrderedBroadcasts.add(r);
193    }
194
195    public final boolean replaceParallelBroadcastLocked(BroadcastRecord r) {
196        for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
197            if (r.intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
198                if (DEBUG_BROADCAST) Slog.v(TAG,
199                        "***** DROPPING PARALLEL ["
200                + mQueueName + "]: " + r.intent);
201                mParallelBroadcasts.set(i, r);
202                return true;
203            }
204        }
205        return false;
206    }
207
208    public final boolean replaceOrderedBroadcastLocked(BroadcastRecord r) {
209        for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
210            if (r.intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
211                if (DEBUG_BROADCAST) Slog.v(TAG,
212                        "***** DROPPING ORDERED ["
213                        + mQueueName + "]: " + r.intent);
214                mOrderedBroadcasts.set(i, r);
215                return true;
216            }
217        }
218        return false;
219    }
220
221    private final void processCurBroadcastLocked(BroadcastRecord r,
222            ProcessRecord app) throws RemoteException {
223        if (DEBUG_BROADCAST)  Slog.v(TAG,
224                "Process cur broadcast " + r + " for app " + app);
225        if (app.thread == null) {
226            throw new RemoteException();
227        }
228        r.receiver = app.thread.asBinder();
229        r.curApp = app;
230        app.curReceiver = r;
231        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
232        mService.updateLruProcessLocked(app, false, null);
233        mService.updateOomAdjLocked();
234
235        // Tell the application to launch this receiver.
236        r.intent.setComponent(r.curComponent);
237
238        boolean started = false;
239        try {
240            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
241                    "Delivering to component " + r.curComponent
242                    + ": " + r);
243            mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
244            app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
245                    mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
246                    r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
247                    app.repProcState);
248            if (DEBUG_BROADCAST)  Slog.v(TAG,
249                    "Process cur broadcast " + r + " DELIVERED for app " + app);
250            started = true;
251        } finally {
252            if (!started) {
253                if (DEBUG_BROADCAST)  Slog.v(TAG,
254                        "Process cur broadcast " + r + ": NOT STARTED!");
255                r.receiver = null;
256                r.curApp = null;
257                app.curReceiver = null;
258            }
259        }
260    }
261
262    public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
263        boolean didSomething = false;
264        final BroadcastRecord br = mPendingBroadcast;
265        if (br != null && br.curApp.pid == app.pid) {
266            try {
267                mPendingBroadcast = null;
268                processCurBroadcastLocked(br, app);
269                didSomething = true;
270            } catch (Exception e) {
271                Slog.w(TAG, "Exception in new application when starting receiver "
272                        + br.curComponent.flattenToShortString(), e);
273                logBroadcastReceiverDiscardLocked(br);
274                finishReceiverLocked(br, br.resultCode, br.resultData,
275                        br.resultExtras, br.resultAbort, false);
276                scheduleBroadcastsLocked();
277                // We need to reset the state if we failed to start the receiver.
278                br.state = BroadcastRecord.IDLE;
279                throw new RuntimeException(e.getMessage());
280            }
281        }
282        return didSomething;
283    }
284
285    public void skipPendingBroadcastLocked(int pid) {
286        final BroadcastRecord br = mPendingBroadcast;
287        if (br != null && br.curApp.pid == pid) {
288            br.state = BroadcastRecord.IDLE;
289            br.nextReceiver = mPendingBroadcastRecvIndex;
290            mPendingBroadcast = null;
291            scheduleBroadcastsLocked();
292        }
293    }
294
295    public void skipCurrentReceiverLocked(ProcessRecord app) {
296        boolean reschedule = false;
297        BroadcastRecord r = app.curReceiver;
298        if (r != null) {
299            // The current broadcast is waiting for this app's receiver
300            // to be finished.  Looks like that's not going to happen, so
301            // let the broadcast continue.
302            logBroadcastReceiverDiscardLocked(r);
303            finishReceiverLocked(r, r.resultCode, r.resultData,
304                    r.resultExtras, r.resultAbort, false);
305            reschedule = true;
306        }
307
308        r = mPendingBroadcast;
309        if (r != null && r.curApp == app) {
310            if (DEBUG_BROADCAST) Slog.v(TAG,
311                    "[" + mQueueName + "] skip & discard pending app " + r);
312            logBroadcastReceiverDiscardLocked(r);
313            finishReceiverLocked(r, r.resultCode, r.resultData,
314                    r.resultExtras, r.resultAbort, false);
315            reschedule = true;
316        }
317        if (reschedule) {
318            scheduleBroadcastsLocked();
319        }
320    }
321
322    public void scheduleBroadcastsLocked() {
323        if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts ["
324                + mQueueName + "]: current="
325                + mBroadcastsScheduled);
326
327        if (mBroadcastsScheduled) {
328            return;
329        }
330        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
331        mBroadcastsScheduled = true;
332    }
333
334    public BroadcastRecord getMatchingOrderedReceiver(IBinder receiver) {
335        if (mOrderedBroadcasts.size() > 0) {
336            final BroadcastRecord r = mOrderedBroadcasts.get(0);
337            if (r != null && r.receiver == receiver) {
338                return r;
339            }
340        }
341        return null;
342    }
343
344    public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
345            String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
346        final int state = r.state;
347        final ActivityInfo receiver = r.curReceiver;
348        r.state = BroadcastRecord.IDLE;
349        if (state == BroadcastRecord.IDLE) {
350            Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
351        }
352        r.receiver = null;
353        r.intent.setComponent(null);
354        if (r.curApp != null) {
355            r.curApp.curReceiver = null;
356        }
357        if (r.curFilter != null) {
358            r.curFilter.receiverList.curBroadcast = null;
359        }
360        r.curFilter = null;
361        r.curReceiver = null;
362        r.curApp = null;
363        mPendingBroadcast = null;
364
365        r.resultCode = resultCode;
366        r.resultData = resultData;
367        r.resultExtras = resultExtras;
368        if (resultAbort && (r.intent.getFlags()&Intent.FLAG_RECEIVER_NO_ABORT) == 0) {
369            r.resultAbort = resultAbort;
370        } else {
371            r.resultAbort = false;
372        }
373
374        if (waitForServices && r.curComponent != null && r.queue.mDelayBehindServices
375                && r.queue.mOrderedBroadcasts.size() > 0
376                && r.queue.mOrderedBroadcasts.get(0) == r) {
377            ActivityInfo nextReceiver;
378            if (r.nextReceiver < r.receivers.size()) {
379                Object obj = r.receivers.get(r.nextReceiver);
380                nextReceiver = (obj instanceof ActivityInfo) ? (ActivityInfo)obj : null;
381            } else {
382                nextReceiver = null;
383            }
384            // Don't do this if the next receive is in the same process as the current one.
385            if (receiver == null || nextReceiver == null
386                    || receiver.applicationInfo.uid != nextReceiver.applicationInfo.uid
387                    || !receiver.processName.equals(nextReceiver.processName)) {
388                // In this case, we are ready to process the next receiver for the current broadcast,
389                // but are on a queue that would like to wait for services to finish before moving
390                // on.  If there are background services currently starting, then we will go into a
391                // special state where we hold off on continuing this broadcast until they are done.
392                if (mService.mServices.hasBackgroundServices(r.userId)) {
393                    Slog.i(ActivityManagerService.TAG, "Delay finish: "
394                            + r.curComponent.flattenToShortString());
395                    r.state = BroadcastRecord.WAITING_SERVICES;
396                    return false;
397                }
398            }
399        }
400
401        r.curComponent = null;
402
403        // We will process the next receiver right now if this is finishing
404        // an app receiver (which is always asynchronous) or after we have
405        // come back from calling a receiver.
406        return state == BroadcastRecord.APP_RECEIVE
407                || state == BroadcastRecord.CALL_DONE_RECEIVE;
408    }
409
410    public void backgroundServicesFinishedLocked(int userId) {
411        if (mOrderedBroadcasts.size() > 0) {
412            BroadcastRecord br = mOrderedBroadcasts.get(0);
413            if (br.userId == userId && br.state == BroadcastRecord.WAITING_SERVICES) {
414                Slog.i(ActivityManagerService.TAG, "Resuming delayed broadcast");
415                br.curComponent = null;
416                br.state = BroadcastRecord.IDLE;
417                processNextBroadcast(false);
418            }
419        }
420    }
421
422    private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
423            Intent intent, int resultCode, String data, Bundle extras,
424            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
425        // Send the intent to the receiver asynchronously using one-way binder calls.
426        if (app != null && app.thread != null) {
427            // If we have an app thread, do the call through that so it is
428            // correctly ordered with other one-way calls.
429            app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
430                    data, extras, ordered, sticky, sendingUser, app.repProcState);
431        } else {
432            receiver.performReceive(intent, resultCode, data, extras, ordered,
433                    sticky, sendingUser);
434        }
435    }
436
437    private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
438            BroadcastFilter filter, boolean ordered) {
439        boolean skip = false;
440        if (filter.requiredPermission != null) {
441            int perm = mService.checkComponentPermission(filter.requiredPermission,
442                    r.callingPid, r.callingUid, -1, true);
443            if (perm != PackageManager.PERMISSION_GRANTED) {
444                Slog.w(TAG, "Permission Denial: broadcasting "
445                        + r.intent.toString()
446                        + " from " + r.callerPackage + " (pid="
447                        + r.callingPid + ", uid=" + r.callingUid + ")"
448                        + " requires " + filter.requiredPermission
449                        + " due to registered receiver " + filter);
450                skip = true;
451            }
452        }
453        if (!skip && r.requiredPermission != null) {
454            int perm = mService.checkComponentPermission(r.requiredPermission,
455                    filter.receiverList.pid, filter.receiverList.uid, -1, true);
456            if (perm != PackageManager.PERMISSION_GRANTED) {
457                Slog.w(TAG, "Permission Denial: receiving "
458                        + r.intent.toString()
459                        + " to " + filter.receiverList.app
460                        + " (pid=" + filter.receiverList.pid
461                        + ", uid=" + filter.receiverList.uid + ")"
462                        + " requires " + r.requiredPermission
463                        + " due to sender " + r.callerPackage
464                        + " (uid " + r.callingUid + ")");
465                skip = true;
466            }
467        }
468        if (r.appOp != AppOpsManager.OP_NONE) {
469            int mode = mService.mAppOpsService.noteOperation(r.appOp,
470                    filter.receiverList.uid, filter.packageName);
471            if (mode != AppOpsManager.MODE_ALLOWED) {
472                if (DEBUG_BROADCAST)  Slog.v(TAG,
473                        "App op " + r.appOp + " not allowed for broadcast to uid "
474                        + filter.receiverList.uid + " pkg " + filter.packageName);
475                skip = true;
476            }
477        }
478        if (!skip) {
479            skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
480                    r.callingPid, r.resolvedType, filter.receiverList.uid);
481        }
482
483        if (filter.receiverList.app == null || filter.receiverList.app.crashing) {
484            Slog.w(TAG, "Skipping deliver [" + mQueueName + "] " + r
485                    + " to " + filter.receiverList + ": process crashing");
486            skip = true;
487        }
488
489        if (!skip) {
490            // If this is not being sent as an ordered broadcast, then we
491            // don't want to touch the fields that keep track of the current
492            // state of ordered broadcasts.
493            if (ordered) {
494                r.receiver = filter.receiverList.receiver.asBinder();
495                r.curFilter = filter;
496                filter.receiverList.curBroadcast = r;
497                r.state = BroadcastRecord.CALL_IN_RECEIVE;
498                if (filter.receiverList.app != null) {
499                    // Bump hosting application to no longer be in background
500                    // scheduling class.  Note that we can't do that if there
501                    // isn't an app...  but we can only be in that case for
502                    // things that directly call the IActivityManager API, which
503                    // are already core system stuff so don't matter for this.
504                    r.curApp = filter.receiverList.app;
505                    filter.receiverList.app.curReceiver = r;
506                    mService.updateOomAdjLocked(r.curApp);
507                }
508            }
509            try {
510                if (DEBUG_BROADCAST_LIGHT) {
511                    int seq = r.intent.getIntExtra("seq", -1);
512                    Slog.i(TAG, "Delivering to " + filter
513                            + " (seq=" + seq + "): " + r);
514                }
515                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
516                    new Intent(r.intent), r.resultCode, r.resultData,
517                    r.resultExtras, r.ordered, r.initialSticky, r.userId);
518                if (ordered) {
519                    r.state = BroadcastRecord.CALL_DONE_RECEIVE;
520                }
521            } catch (RemoteException e) {
522                Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
523                if (ordered) {
524                    r.receiver = null;
525                    r.curFilter = null;
526                    filter.receiverList.curBroadcast = null;
527                    if (filter.receiverList.app != null) {
528                        filter.receiverList.app.curReceiver = null;
529                    }
530                }
531            }
532        }
533    }
534
535    final void processNextBroadcast(boolean fromMsg) {
536        synchronized(mService) {
537            BroadcastRecord r;
538
539            if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast ["
540                    + mQueueName + "]: "
541                    + mParallelBroadcasts.size() + " broadcasts, "
542                    + mOrderedBroadcasts.size() + " ordered broadcasts");
543
544            mService.updateCpuStats();
545
546            if (fromMsg) {
547                mBroadcastsScheduled = false;
548            }
549
550            // First, deliver any non-serialized broadcasts right away.
551            while (mParallelBroadcasts.size() > 0) {
552                r = mParallelBroadcasts.remove(0);
553                r.dispatchTime = SystemClock.uptimeMillis();
554                r.dispatchClockTime = System.currentTimeMillis();
555                final int N = r.receivers.size();
556                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast ["
557                        + mQueueName + "] " + r);
558                for (int i=0; i<N; i++) {
559                    Object target = r.receivers.get(i);
560                    if (DEBUG_BROADCAST)  Slog.v(TAG,
561                            "Delivering non-ordered on [" + mQueueName + "] to registered "
562                            + target + ": " + r);
563                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
564                }
565                addBroadcastToHistoryLocked(r);
566                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast ["
567                        + mQueueName + "] " + r);
568            }
569
570            // Now take care of the next serialized one...
571
572            // If we are waiting for a process to come up to handle the next
573            // broadcast, then do nothing at this point.  Just in case, we
574            // check that the process we're waiting for still exists.
575            if (mPendingBroadcast != null) {
576                if (DEBUG_BROADCAST_LIGHT) {
577                    Slog.v(TAG, "processNextBroadcast ["
578                            + mQueueName + "]: waiting for "
579                            + mPendingBroadcast.curApp);
580                }
581
582                boolean isDead;
583                synchronized (mService.mPidsSelfLocked) {
584                    ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
585                    isDead = proc == null || proc.crashing;
586                }
587                if (!isDead) {
588                    // It's still alive, so keep waiting
589                    return;
590                } else {
591                    Slog.w(TAG, "pending app  ["
592                            + mQueueName + "]" + mPendingBroadcast.curApp
593                            + " died before responding to broadcast");
594                    mPendingBroadcast.state = BroadcastRecord.IDLE;
595                    mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
596                    mPendingBroadcast = null;
597                }
598            }
599
600            boolean looped = false;
601
602            do {
603                if (mOrderedBroadcasts.size() == 0) {
604                    // No more broadcasts pending, so all done!
605                    mService.scheduleAppGcsLocked();
606                    if (looped) {
607                        // If we had finished the last ordered broadcast, then
608                        // make sure all processes have correct oom and sched
609                        // adjustments.
610                        mService.updateOomAdjLocked();
611                    }
612                    return;
613                }
614                r = mOrderedBroadcasts.get(0);
615                boolean forceReceive = false;
616
617                // Ensure that even if something goes awry with the timeout
618                // detection, we catch "hung" broadcasts here, discard them,
619                // and continue to make progress.
620                //
621                // This is only done if the system is ready so that PRE_BOOT_COMPLETED
622                // receivers don't get executed with timeouts. They're intended for
623                // one time heavy lifting after system upgrades and can take
624                // significant amounts of time.
625                int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
626                if (mService.mProcessesReady && r.dispatchTime > 0) {
627                    long now = SystemClock.uptimeMillis();
628                    if ((numReceivers > 0) &&
629                            (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
630                        Slog.w(TAG, "Hung broadcast ["
631                                + mQueueName + "] discarded after timeout failure:"
632                                + " now=" + now
633                                + " dispatchTime=" + r.dispatchTime
634                                + " startTime=" + r.receiverTime
635                                + " intent=" + r.intent
636                                + " numReceivers=" + numReceivers
637                                + " nextReceiver=" + r.nextReceiver
638                                + " state=" + r.state);
639                        broadcastTimeoutLocked(false); // forcibly finish this broadcast
640                        forceReceive = true;
641                        r.state = BroadcastRecord.IDLE;
642                    }
643                }
644
645                if (r.state != BroadcastRecord.IDLE) {
646                    if (DEBUG_BROADCAST) Slog.d(TAG,
647                            "processNextBroadcast("
648                            + mQueueName + ") called when not idle (state="
649                            + r.state + ")");
650                    return;
651                }
652
653                if (r.receivers == null || r.nextReceiver >= numReceivers
654                        || r.resultAbort || forceReceive) {
655                    // No more receivers for this broadcast!  Send the final
656                    // result if requested...
657                    if (r.resultTo != null) {
658                        try {
659                            if (DEBUG_BROADCAST) {
660                                int seq = r.intent.getIntExtra("seq", -1);
661                                Slog.i(TAG, "Finishing broadcast ["
662                                        + mQueueName + "] " + r.intent.getAction()
663                                        + " seq=" + seq + " app=" + r.callerApp);
664                            }
665                            performReceiveLocked(r.callerApp, r.resultTo,
666                                new Intent(r.intent), r.resultCode,
667                                r.resultData, r.resultExtras, false, false, r.userId);
668                            // Set this to null so that the reference
669                            // (local and remote) isn't kept in the mBroadcastHistory.
670                            r.resultTo = null;
671                        } catch (RemoteException e) {
672                            Slog.w(TAG, "Failure ["
673                                    + mQueueName + "] sending broadcast result of "
674                                    + r.intent, e);
675                        }
676                    }
677
678                    if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
679                    cancelBroadcastTimeoutLocked();
680
681                    if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
682                            + r);
683
684                    // ... and on to the next...
685                    addBroadcastToHistoryLocked(r);
686                    mOrderedBroadcasts.remove(0);
687                    r = null;
688                    looped = true;
689                    continue;
690                }
691            } while (r == null);
692
693            // Get the next receiver...
694            int recIdx = r.nextReceiver++;
695
696            // Keep track of when this receiver started, and make sure there
697            // is a timeout message pending to kill it if need be.
698            r.receiverTime = SystemClock.uptimeMillis();
699            if (recIdx == 0) {
700                r.dispatchTime = r.receiverTime;
701                r.dispatchClockTime = System.currentTimeMillis();
702                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast ["
703                        + mQueueName + "] " + r);
704            }
705            if (! mPendingBroadcastTimeoutMessage) {
706                long timeoutTime = r.receiverTime + mTimeoutPeriod;
707                if (DEBUG_BROADCAST) Slog.v(TAG,
708                        "Submitting BROADCAST_TIMEOUT_MSG ["
709                        + mQueueName + "] for " + r + " at " + timeoutTime);
710                setBroadcastTimeoutLocked(timeoutTime);
711            }
712
713            Object nextReceiver = r.receivers.get(recIdx);
714            if (nextReceiver instanceof BroadcastFilter) {
715                // Simple case: this is a registered receiver who gets
716                // a direct call.
717                BroadcastFilter filter = (BroadcastFilter)nextReceiver;
718                if (DEBUG_BROADCAST)  Slog.v(TAG,
719                        "Delivering ordered ["
720                        + mQueueName + "] to registered "
721                        + filter + ": " + r);
722                deliverToRegisteredReceiverLocked(r, filter, r.ordered);
723                if (r.receiver == null || !r.ordered) {
724                    // The receiver has already finished, so schedule to
725                    // process the next one.
726                    if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing ["
727                            + mQueueName + "]: ordered="
728                            + r.ordered + " receiver=" + r.receiver);
729                    r.state = BroadcastRecord.IDLE;
730                    scheduleBroadcastsLocked();
731                }
732                return;
733            }
734
735            // Hard case: need to instantiate the receiver, possibly
736            // starting its application process to host it.
737
738            ResolveInfo info =
739                (ResolveInfo)nextReceiver;
740            ComponentName component = new ComponentName(
741                    info.activityInfo.applicationInfo.packageName,
742                    info.activityInfo.name);
743
744            boolean skip = false;
745            int perm = mService.checkComponentPermission(info.activityInfo.permission,
746                    r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
747                    info.activityInfo.exported);
748            if (perm != PackageManager.PERMISSION_GRANTED) {
749                if (!info.activityInfo.exported) {
750                    Slog.w(TAG, "Permission Denial: broadcasting "
751                            + r.intent.toString()
752                            + " from " + r.callerPackage + " (pid=" + r.callingPid
753                            + ", uid=" + r.callingUid + ")"
754                            + " is not exported from uid " + info.activityInfo.applicationInfo.uid
755                            + " due to receiver " + component.flattenToShortString());
756                } else {
757                    Slog.w(TAG, "Permission Denial: broadcasting "
758                            + r.intent.toString()
759                            + " from " + r.callerPackage + " (pid=" + r.callingPid
760                            + ", uid=" + r.callingUid + ")"
761                            + " requires " + info.activityInfo.permission
762                            + " due to receiver " + component.flattenToShortString());
763                }
764                skip = true;
765            }
766            if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
767                r.requiredPermission != null) {
768                try {
769                    perm = AppGlobals.getPackageManager().
770                            checkPermission(r.requiredPermission,
771                                    info.activityInfo.applicationInfo.packageName);
772                } catch (RemoteException e) {
773                    perm = PackageManager.PERMISSION_DENIED;
774                }
775                if (perm != PackageManager.PERMISSION_GRANTED) {
776                    Slog.w(TAG, "Permission Denial: receiving "
777                            + r.intent + " to "
778                            + component.flattenToShortString()
779                            + " requires " + r.requiredPermission
780                            + " due to sender " + r.callerPackage
781                            + " (uid " + r.callingUid + ")");
782                    skip = true;
783                }
784            }
785            if (r.appOp != AppOpsManager.OP_NONE) {
786                int mode = mService.mAppOpsService.noteOperation(r.appOp,
787                        info.activityInfo.applicationInfo.uid, info.activityInfo.packageName);
788                if (mode != AppOpsManager.MODE_ALLOWED) {
789                    if (DEBUG_BROADCAST)  Slog.v(TAG,
790                            "App op " + r.appOp + " not allowed for broadcast to uid "
791                            + info.activityInfo.applicationInfo.uid + " pkg "
792                            + info.activityInfo.packageName);
793                    skip = true;
794                }
795            }
796            if (!skip) {
797                skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
798                        r.callingPid, r.resolvedType, info.activityInfo.applicationInfo.uid);
799            }
800            boolean isSingleton = false;
801            try {
802                isSingleton = mService.isSingleton(info.activityInfo.processName,
803                        info.activityInfo.applicationInfo,
804                        info.activityInfo.name, info.activityInfo.flags);
805            } catch (SecurityException e) {
806                Slog.w(TAG, e.getMessage());
807                skip = true;
808            }
809            if ((info.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
810                if (ActivityManager.checkUidPermission(
811                        android.Manifest.permission.INTERACT_ACROSS_USERS,
812                        info.activityInfo.applicationInfo.uid)
813                                != PackageManager.PERMISSION_GRANTED) {
814                    Slog.w(TAG, "Permission Denial: Receiver " + component.flattenToShortString()
815                            + " requests FLAG_SINGLE_USER, but app does not hold "
816                            + android.Manifest.permission.INTERACT_ACROSS_USERS);
817                    skip = true;
818                }
819            }
820            if (r.curApp != null && r.curApp.crashing) {
821                // If the target process is crashing, just skip it.
822                Slog.w(TAG, "Skipping deliver ordered [" + mQueueName + "] " + r
823                        + " to " + r.curApp + ": process crashing");
824                skip = true;
825            }
826            if (!skip) {
827                boolean isAvailable = false;
828                try {
829                    isAvailable = AppGlobals.getPackageManager().isPackageAvailable(
830                            info.activityInfo.packageName,
831                            UserHandle.getUserId(info.activityInfo.applicationInfo.uid));
832                } catch (Exception e) {
833                    // all such failures mean we skip this receiver
834                    Slog.w(TAG, "Exception getting recipient info for "
835                            + info.activityInfo.packageName, e);
836                }
837                if (!isAvailable) {
838                    if (DEBUG_BROADCAST) {
839                        Slog.v(TAG, "Skipping delivery to " + info.activityInfo.packageName
840                                + " / " + info.activityInfo.applicationInfo.uid
841                                + " : package no longer available");
842                    }
843                    skip = true;
844                }
845            }
846
847            if (skip) {
848                if (DEBUG_BROADCAST)  Slog.v(TAG,
849                        "Skipping delivery of ordered ["
850                        + mQueueName + "] " + r + " for whatever reason");
851                r.receiver = null;
852                r.curFilter = null;
853                r.state = BroadcastRecord.IDLE;
854                scheduleBroadcastsLocked();
855                return;
856            }
857
858            r.state = BroadcastRecord.APP_RECEIVE;
859            String targetProcess = info.activityInfo.processName;
860            r.curComponent = component;
861            if (r.callingUid != Process.SYSTEM_UID && isSingleton) {
862                info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0);
863            }
864            r.curReceiver = info.activityInfo;
865            if (DEBUG_MU && r.callingUid > UserHandle.PER_USER_RANGE) {
866                Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, "
867                        + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = "
868                        + info.activityInfo.applicationInfo.uid);
869            }
870
871            // Broadcast is being executed, its package can't be stopped.
872            try {
873                AppGlobals.getPackageManager().setPackageStoppedState(
874                        r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
875            } catch (RemoteException e) {
876            } catch (IllegalArgumentException e) {
877                Slog.w(TAG, "Failed trying to unstop package "
878                        + r.curComponent.getPackageName() + ": " + e);
879            }
880
881            // Is this receiver's application already running?
882            ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
883                    info.activityInfo.applicationInfo.uid, false);
884            if (app != null && app.thread != null) {
885                try {
886                    app.addPackage(info.activityInfo.packageName, mService.mProcessStats);
887                    processCurBroadcastLocked(r, app);
888                    return;
889                } catch (RemoteException e) {
890                    Slog.w(TAG, "Exception when sending broadcast to "
891                          + r.curComponent, e);
892                } catch (RuntimeException e) {
893                    Log.wtf(TAG, "Failed sending broadcast to "
894                            + r.curComponent + " with " + r.intent, e);
895                    // If some unexpected exception happened, just skip
896                    // this broadcast.  At this point we are not in the call
897                    // from a client, so throwing an exception out from here
898                    // will crash the entire system instead of just whoever
899                    // sent the broadcast.
900                    logBroadcastReceiverDiscardLocked(r);
901                    finishReceiverLocked(r, r.resultCode, r.resultData,
902                            r.resultExtras, r.resultAbort, false);
903                    scheduleBroadcastsLocked();
904                    // We need to reset the state if we failed to start the receiver.
905                    r.state = BroadcastRecord.IDLE;
906                    return;
907                }
908
909                // If a dead object exception was thrown -- fall through to
910                // restart the application.
911            }
912
913            // Not running -- get it started, to be executed when the app comes up.
914            if (DEBUG_BROADCAST)  Slog.v(TAG,
915                    "Need to start app ["
916                    + mQueueName + "] " + targetProcess + " for broadcast " + r);
917            if ((r.curApp=mService.startProcessLocked(targetProcess,
918                    info.activityInfo.applicationInfo, true,
919                    r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
920                    "broadcast", r.curComponent,
921                    (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
922                            == null) {
923                // Ah, this recipient is unavailable.  Finish it if necessary,
924                // and mark the broadcast record as ready for the next.
925                Slog.w(TAG, "Unable to launch app "
926                        + info.activityInfo.applicationInfo.packageName + "/"
927                        + info.activityInfo.applicationInfo.uid + " for broadcast "
928                        + r.intent + ": process is bad");
929                logBroadcastReceiverDiscardLocked(r);
930                finishReceiverLocked(r, r.resultCode, r.resultData,
931                        r.resultExtras, r.resultAbort, false);
932                scheduleBroadcastsLocked();
933                r.state = BroadcastRecord.IDLE;
934                return;
935            }
936
937            mPendingBroadcast = r;
938            mPendingBroadcastRecvIndex = recIdx;
939        }
940    }
941
942    final void setBroadcastTimeoutLocked(long timeoutTime) {
943        if (! mPendingBroadcastTimeoutMessage) {
944            Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
945            mHandler.sendMessageAtTime(msg, timeoutTime);
946            mPendingBroadcastTimeoutMessage = true;
947        }
948    }
949
950    final void cancelBroadcastTimeoutLocked() {
951        if (mPendingBroadcastTimeoutMessage) {
952            mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this);
953            mPendingBroadcastTimeoutMessage = false;
954        }
955    }
956
957    final void broadcastTimeoutLocked(boolean fromMsg) {
958        if (fromMsg) {
959            mPendingBroadcastTimeoutMessage = false;
960        }
961
962        if (mOrderedBroadcasts.size() == 0) {
963            return;
964        }
965
966        long now = SystemClock.uptimeMillis();
967        BroadcastRecord r = mOrderedBroadcasts.get(0);
968        if (fromMsg) {
969            if (mService.mDidDexOpt) {
970                // Delay timeouts until dexopt finishes.
971                mService.mDidDexOpt = false;
972                long timeoutTime = SystemClock.uptimeMillis() + mTimeoutPeriod;
973                setBroadcastTimeoutLocked(timeoutTime);
974                return;
975            }
976            if (!mService.mProcessesReady) {
977                // Only process broadcast timeouts if the system is ready. That way
978                // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
979                // to do heavy lifting for system up.
980                return;
981            }
982
983            long timeoutTime = r.receiverTime + mTimeoutPeriod;
984            if (timeoutTime > now) {
985                // We can observe premature timeouts because we do not cancel and reset the
986                // broadcast timeout message after each receiver finishes.  Instead, we set up
987                // an initial timeout then kick it down the road a little further as needed
988                // when it expires.
989                if (DEBUG_BROADCAST) Slog.v(TAG,
990                        "Premature timeout ["
991                        + mQueueName + "] @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
992                        + timeoutTime);
993                setBroadcastTimeoutLocked(timeoutTime);
994                return;
995            }
996        }
997
998        BroadcastRecord br = mOrderedBroadcasts.get(0);
999        if (br.state == BroadcastRecord.WAITING_SERVICES) {
1000            // In this case the broadcast had already finished, but we had decided to wait
1001            // for started services to finish as well before going on.  So if we have actually
1002            // waited long enough time timeout the broadcast, let's give up on the whole thing
1003            // and just move on to the next.
1004            Slog.i(ActivityManagerService.TAG, "Waited long enough for: " + (br.curComponent != null
1005                    ? br.curComponent.flattenToShortString() : "(null)"));
1006            br.curComponent = null;
1007            br.state = BroadcastRecord.IDLE;
1008            processNextBroadcast(false);
1009            return;
1010        }
1011
1012        Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r. receiver
1013                + ", started " + (now - r.receiverTime) + "ms ago");
1014        r.receiverTime = now;
1015        r.anrCount++;
1016
1017        // Current receiver has passed its expiration date.
1018        if (r.nextReceiver <= 0) {
1019            Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
1020            return;
1021        }
1022
1023        ProcessRecord app = null;
1024        String anrMessage = null;
1025
1026        Object curReceiver = r.receivers.get(r.nextReceiver-1);
1027        Slog.w(TAG, "Receiver during timeout: " + curReceiver);
1028        logBroadcastReceiverDiscardLocked(r);
1029        if (curReceiver instanceof BroadcastFilter) {
1030            BroadcastFilter bf = (BroadcastFilter)curReceiver;
1031            if (bf.receiverList.pid != 0
1032                    && bf.receiverList.pid != ActivityManagerService.MY_PID) {
1033                synchronized (mService.mPidsSelfLocked) {
1034                    app = mService.mPidsSelfLocked.get(
1035                            bf.receiverList.pid);
1036                }
1037            }
1038        } else {
1039            app = r.curApp;
1040        }
1041
1042        if (app != null) {
1043            anrMessage = "Broadcast of " + r.intent.toString();
1044        }
1045
1046        if (mPendingBroadcast == r) {
1047            mPendingBroadcast = null;
1048        }
1049
1050        // Move on to the next receiver.
1051        finishReceiverLocked(r, r.resultCode, r.resultData,
1052                r.resultExtras, r.resultAbort, false);
1053        scheduleBroadcastsLocked();
1054
1055        if (anrMessage != null) {
1056            // Post the ANR to the handler since we do not want to process ANRs while
1057            // potentially holding our lock.
1058            mHandler.post(new AppNotResponding(app, anrMessage));
1059        }
1060    }
1061
1062    private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
1063        if (r.callingUid < 0) {
1064            // This was from a registerReceiver() call; ignore it.
1065            return;
1066        }
1067        System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
1068                MAX_BROADCAST_HISTORY-1);
1069        r.finishTime = SystemClock.uptimeMillis();
1070        mBroadcastHistory[0] = r;
1071        System.arraycopy(mBroadcastSummaryHistory, 0, mBroadcastSummaryHistory, 1,
1072                MAX_BROADCAST_SUMMARY_HISTORY-1);
1073        mBroadcastSummaryHistory[0] = r.intent;
1074    }
1075
1076    final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
1077        if (r.nextReceiver > 0) {
1078            Object curReceiver = r.receivers.get(r.nextReceiver-1);
1079            if (curReceiver instanceof BroadcastFilter) {
1080                BroadcastFilter bf = (BroadcastFilter) curReceiver;
1081                EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
1082                        bf.owningUserId, System.identityHashCode(r),
1083                        r.intent.getAction(),
1084                        r.nextReceiver - 1,
1085                        System.identityHashCode(bf));
1086            } else {
1087                ResolveInfo ri = (ResolveInfo)curReceiver;
1088                EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
1089                        UserHandle.getUserId(ri.activityInfo.applicationInfo.uid),
1090                        System.identityHashCode(r), r.intent.getAction(),
1091                        r.nextReceiver - 1, ri.toString());
1092            }
1093        } else {
1094            Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
1095                    + r);
1096            EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
1097                    -1, System.identityHashCode(r),
1098                    r.intent.getAction(),
1099                    r.nextReceiver,
1100                    "NONE");
1101        }
1102    }
1103
1104    final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
1105            int opti, boolean dumpAll, String dumpPackage, boolean needSep) {
1106        if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
1107                || mPendingBroadcast != null) {
1108            boolean printed = false;
1109            for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
1110                BroadcastRecord br = mParallelBroadcasts.get(i);
1111                if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
1112                    continue;
1113                }
1114                if (!printed) {
1115                    if (needSep) {
1116                        pw.println();
1117                    }
1118                    needSep = true;
1119                    printed = true;
1120                    pw.println("  Active broadcasts [" + mQueueName + "]:");
1121                }
1122                pw.println("  Active Broadcast " + mQueueName + " #" + i + ":");
1123                br.dump(pw, "    ");
1124            }
1125            printed = false;
1126            needSep = true;
1127            for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
1128                BroadcastRecord br = mOrderedBroadcasts.get(i);
1129                if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
1130                    continue;
1131                }
1132                if (!printed) {
1133                    if (needSep) {
1134                        pw.println();
1135                    }
1136                    needSep = true;
1137                    printed = true;
1138                    pw.println("  Active ordered broadcasts [" + mQueueName + "]:");
1139                }
1140                pw.println("  Active Ordered Broadcast " + mQueueName + " #" + i + ":");
1141                mOrderedBroadcasts.get(i).dump(pw, "    ");
1142            }
1143            if (dumpPackage == null || (mPendingBroadcast != null
1144                    && dumpPackage.equals(mPendingBroadcast.callerPackage))) {
1145                if (needSep) {
1146                    pw.println();
1147                }
1148                pw.println("  Pending broadcast [" + mQueueName + "]:");
1149                if (mPendingBroadcast != null) {
1150                    mPendingBroadcast.dump(pw, "    ");
1151                } else {
1152                    pw.println("    (null)");
1153                }
1154                needSep = true;
1155            }
1156        }
1157
1158        int i;
1159        boolean printed = false;
1160        for (i=0; i<MAX_BROADCAST_HISTORY; i++) {
1161            BroadcastRecord r = mBroadcastHistory[i];
1162            if (r == null) {
1163                break;
1164            }
1165            if (dumpPackage != null && !dumpPackage.equals(r.callerPackage)) {
1166                continue;
1167            }
1168            if (!printed) {
1169                if (needSep) {
1170                    pw.println();
1171                }
1172                needSep = true;
1173                pw.println("  Historical broadcasts [" + mQueueName + "]:");
1174                printed = true;
1175            }
1176            if (dumpAll) {
1177                pw.print("  Historical Broadcast " + mQueueName + " #");
1178                        pw.print(i); pw.println(":");
1179                r.dump(pw, "    ");
1180            } else {
1181                pw.print("  #"); pw.print(i); pw.print(": "); pw.println(r);
1182                pw.print("    ");
1183                pw.println(r.intent.toShortString(false, true, true, false));
1184                if (r.targetComp != null && r.targetComp != r.intent.getComponent()) {
1185                    pw.print("    targetComp: "); pw.println(r.targetComp.toShortString());
1186                }
1187                Bundle bundle = r.intent.getExtras();
1188                if (bundle != null) {
1189                    pw.print("    extras: "); pw.println(bundle.toString());
1190                }
1191            }
1192        }
1193
1194        if (dumpPackage == null) {
1195            if (dumpAll) {
1196                i = 0;
1197                printed = false;
1198            }
1199            for (; i<MAX_BROADCAST_SUMMARY_HISTORY; i++) {
1200                Intent intent = mBroadcastSummaryHistory[i];
1201                if (intent == null) {
1202                    break;
1203                }
1204                if (!printed) {
1205                    if (needSep) {
1206                        pw.println();
1207                    }
1208                    needSep = true;
1209                    pw.println("  Historical broadcasts summary [" + mQueueName + "]:");
1210                    printed = true;
1211                }
1212                if (!dumpAll && i >= 50) {
1213                    pw.println("  ...");
1214                    break;
1215                }
1216                pw.print("  #"); pw.print(i); pw.print(": ");
1217                pw.println(intent.toShortString(false, true, true, false));
1218                Bundle bundle = intent.getExtras();
1219                if (bundle != null) {
1220                    pw.print("    extras: "); pw.println(bundle.toString());
1221                }
1222            }
1223        }
1224
1225        return needSep;
1226    }
1227}
1228