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