• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.content;
18 
19 import android.app.ActivityManagerNative;
20 import android.app.ActivityThread;
21 import android.app.IActivityManager;
22 import android.app.QueuedWork;
23 import android.os.Bundle;
24 import android.os.IBinder;
25 import android.os.RemoteException;
26 import android.util.Log;
27 import android.util.Slog;
28 
29 /**
30  * Base class for code that will receive intents sent by sendBroadcast().
31  *
32  * <p>If you don't need to send broadcasts across applications, consider using
33  * this class with {@link android.support.v4.content.LocalBroadcastManager} instead
34  * of the more general facilities described below.  This will give you a much
35  * more efficient implementation (no cross-process communication needed) and allow
36  * you to avoid thinking about any security issues related to other applications
37  * being able to receive or send your broadcasts.
38  *
39  * <p>You can either dynamically register an instance of this class with
40  * {@link Context#registerReceiver Context.registerReceiver()}
41  * or statically publish an implementation through the
42  * {@link android.R.styleable#AndroidManifestReceiver &lt;receiver&gt;}
43  * tag in your <code>AndroidManifest.xml</code>.
44  *
45  * <p><em><strong>Note:</strong></em>
46  * &nbsp;&nbsp;&nbsp;If registering a receiver in your
47  * {@link android.app.Activity#onResume() Activity.onResume()}
48  * implementation, you should unregister it in
49  * {@link android.app.Activity#onPause() Activity.onPause()}.
50  * (You won't receive intents when paused,
51  * and this will cut down on unnecessary system overhead). Do not unregister in
52  * {@link android.app.Activity#onSaveInstanceState(android.os.Bundle) Activity.onSaveInstanceState()},
53  * because this won't be called if the user moves back in the history
54  * stack.
55  *
56  * <p>There are two major classes of broadcasts that can be received:</p>
57  * <ul>
58  * <li> <b>Normal broadcasts</b> (sent with {@link Context#sendBroadcast(Intent)
59  * Context.sendBroadcast}) are completely asynchronous.  All receivers of the
60  * broadcast are run in an undefined order, often at the same time.  This is
61  * more efficient, but means that receivers cannot use the result or abort
62  * APIs included here.
63  * <li> <b>Ordered broadcasts</b> (sent with {@link Context#sendOrderedBroadcast(Intent, String)
64  * Context.sendOrderedBroadcast}) are delivered to one receiver at a time.
65  * As each receiver executes in turn, it can propagate a result to the next
66  * receiver, or it can completely abort the broadcast so that it won't be passed
67  * to other receivers.  The order receivers run in can be controlled with the
68  * {@link android.R.styleable#AndroidManifestIntentFilter_priority
69  * android:priority} attribute of the matching intent-filter; receivers with
70  * the same priority will be run in an arbitrary order.
71  * </ul>
72  *
73  * <p>Even in the case of normal broadcasts, the system may in some
74  * situations revert to delivering the broadcast one receiver at a time.  In
75  * particular, for receivers that may require the creation of a process, only
76  * one will be run at a time to avoid overloading the system with new processes.
77  * In this situation, however, the non-ordered semantics hold: these receivers still
78  * cannot return results or abort their broadcast.</p>
79  *
80  * <p>Note that, although the Intent class is used for sending and receiving
81  * these broadcasts, the Intent broadcast mechanism here is completely separate
82  * from Intents that are used to start Activities with
83  * {@link Context#startActivity Context.startActivity()}.
84  * There is no way for a BroadcastReceiver
85  * to see or capture Intents used with startActivity(); likewise, when
86  * you broadcast an Intent, you will never find or start an Activity.
87  * These two operations are semantically very different: starting an
88  * Activity with an Intent is a foreground operation that modifies what the
89  * user is currently interacting with; broadcasting an Intent is a background
90  * operation that the user is not normally aware of.
91  *
92  * <p>The BroadcastReceiver class (when launched as a component through
93  * a manifest's {@link android.R.styleable#AndroidManifestReceiver &lt;receiver&gt;}
94  * tag) is an important part of an
95  * <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">application's overall lifecycle</a>.</p>
96  *
97  * <p>Topics covered here:
98  * <ol>
99  * <li><a href="#Security">Security</a>
100  * <li><a href="#ReceiverLifecycle">Receiver Lifecycle</a>
101  * <li><a href="#ProcessLifecycle">Process Lifecycle</a>
102  * </ol>
103  *
104  * <div class="special reference">
105  * <h3>Developer Guides</h3>
106  * <p>For information about how to use this class to receive and resolve intents, read the
107  * <a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
108  * developer guide.</p>
109  * </div>
110  *
111  * <a name="Security"></a>
112  * <h3>Security</h3>
113  *
114  * <p>Receivers used with the {@link Context} APIs are by their nature a
115  * cross-application facility, so you must consider how other applications
116  * may be able to abuse your use of them.  Some things to consider are:
117  *
118  * <ul>
119  * <li><p>The Intent namespace is global.  Make sure that Intent action names and
120  * other strings are written in a namespace you own, or else you may inadvertantly
121  * conflict with other applications.
122  * <li><p>When you use {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)},
123  * <em>any</em> application may send broadcasts to that registered receiver.  You can
124  * control who can send broadcasts to it through permissions described below.
125  * <li><p>When you publish a receiver in your application's manifest and specify
126  * intent-filters for it, any other application can send broadcasts to it regardless
127  * of the filters you specify.  To prevent others from sending to it, make it
128  * unavailable to them with <code>android:exported="false"</code>.
129  * <li><p>When you use {@link Context#sendBroadcast(Intent)} or related methods,
130  * normally any other application can receive these broadcasts.  You can control who
131  * can receive such broadcasts through permissions described below.  Alternatively,
132  * starting with {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, you
133  * can also safely restrict the broadcast to a single application with
134  * {@link Intent#setPackage(String) Intent.setPackage}
135  * </ul>
136  *
137  * <p>None of these issues exist when using
138  * {@link android.support.v4.content.LocalBroadcastManager}, since intents
139  * broadcast it never go outside of the current process.
140  *
141  * <p>Access permissions can be enforced by either the sender or receiver
142  * of a broadcast.
143  *
144  * <p>To enforce a permission when sending, you supply a non-null
145  * <var>permission</var> argument to
146  * {@link Context#sendBroadcast(Intent, String)} or
147  * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)}.
148  * Only receivers who have been granted this permission
149  * (by requesting it with the
150  * {@link android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
151  * tag in their <code>AndroidManifest.xml</code>) will be able to receive
152  * the broadcast.
153  *
154  * <p>To enforce a permission when receiving, you supply a non-null
155  * <var>permission</var> when registering your receiver -- either when calling
156  * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)}
157  * or in the static
158  * {@link android.R.styleable#AndroidManifestReceiver &lt;receiver&gt;}
159  * tag in your <code>AndroidManifest.xml</code>.  Only broadcasters who have
160  * been granted this permission (by requesting it with the
161  * {@link android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
162  * tag in their <code>AndroidManifest.xml</code>) will be able to send an
163  * Intent to the receiver.
164  *
165  * <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a>
166  * document for more information on permissions and security in general.
167  *
168  * <a name="ReceiverLifecycle"></a>
169  * <h3>Receiver Lifecycle</h3>
170  *
171  * <p>A BroadcastReceiver object is only valid for the duration of the call
172  * to {@link #onReceive}.  Once your code returns from this function,
173  * the system considers the object to be finished and no longer active.
174  *
175  * <p>This has important repercussions to what you can do in an
176  * {@link #onReceive} implementation: anything that requires asynchronous
177  * operation is not available, because you will need to return from the
178  * function to handle the asynchronous operation, but at that point the
179  * BroadcastReceiver is no longer active and thus the system is free to kill
180  * its process before the asynchronous operation completes.
181  *
182  * <p>In particular, you may <i>not</i> show a dialog or bind to a service from
183  * within a BroadcastReceiver.  For the former, you should instead use the
184  * {@link android.app.NotificationManager} API.  For the latter, you can
185  * use {@link android.content.Context#startService Context.startService()} to
186  * send a command to the service.
187  *
188  * <a name="ProcessLifecycle"></a>
189  * <h3>Process Lifecycle</h3>
190  *
191  * <p>A process that is currently executing a BroadcastReceiver (that is,
192  * currently running the code in its {@link #onReceive} method) is
193  * considered to be a foreground process and will be kept running by the
194  * system except under cases of extreme memory pressure.
195  *
196  * <p>Once you return from onReceive(), the BroadcastReceiver is no longer
197  * active, and its hosting process is only as important as any other application
198  * components that are running in it.  This is especially important because if
199  * that process was only hosting the BroadcastReceiver (a common case for
200  * applications that the user has never or not recently interacted with), then
201  * upon returning from onReceive() the system will consider its process
202  * to be empty and aggressively kill it so that resources are available for other
203  * more important processes.
204  *
205  * <p>This means that for longer-running operations you will often use
206  * a {@link android.app.Service} in conjunction with a BroadcastReceiver to keep
207  * the containing process active for the entire time of your operation.
208  */
209 public abstract class BroadcastReceiver {
210     private PendingResult mPendingResult;
211     private boolean mDebugUnregister;
212 
213     /**
214      * State for a result that is pending for a broadcast receiver.  Returned
215      * by {@link BroadcastReceiver#goAsync() goAsync()}
216      * while in {@link BroadcastReceiver#onReceive BroadcastReceiver.onReceive()}.
217      * This allows you to return from onReceive() without having the broadcast
218      * terminate; you must call {@link #finish()} once you are done with the
219      * broadcast.  This allows you to process the broadcast off of the main
220      * thread of your app.
221      *
222      * <p>Note on threading: the state inside of this class is not itself
223      * thread-safe, however you can use it from any thread if you properly
224      * sure that you do not have races.  Typically this means you will hand
225      * the entire object to another thread, which will be solely responsible
226      * for setting any results and finally calling {@link #finish()}.
227      */
228     public static class PendingResult {
229         /** @hide */
230         public static final int TYPE_COMPONENT = 0;
231         /** @hide */
232         public static final int TYPE_REGISTERED = 1;
233         /** @hide */
234         public static final int TYPE_UNREGISTERED = 2;
235 
236         final int mType;
237         final boolean mOrderedHint;
238         final boolean mInitialStickyHint;
239         final IBinder mToken;
240 
241         int mResultCode;
242         String mResultData;
243         Bundle mResultExtras;
244         boolean mAbortBroadcast;
245         boolean mFinished;
246 
247         /** @hide */
PendingResult(int resultCode, String resultData, Bundle resultExtras, int type, boolean ordered, boolean sticky, IBinder token)248         public PendingResult(int resultCode, String resultData, Bundle resultExtras,
249                 int type, boolean ordered, boolean sticky, IBinder token) {
250             mResultCode = resultCode;
251             mResultData = resultData;
252             mResultExtras = resultExtras;
253             mType = type;
254             mOrderedHint = ordered;
255             mInitialStickyHint = sticky;
256             mToken = token;
257         }
258 
259         /**
260          * Version of {@link BroadcastReceiver#setResultCode(int)
261          * BroadcastReceiver.setResultCode(int)} for
262          * asynchronous broadcast handling.
263          */
setResultCode(int code)264         public final void setResultCode(int code) {
265             checkSynchronousHint();
266             mResultCode = code;
267         }
268 
269         /**
270          * Version of {@link BroadcastReceiver#getResultCode()
271          * BroadcastReceiver.getResultCode()} for
272          * asynchronous broadcast handling.
273          */
getResultCode()274         public final int getResultCode() {
275             return mResultCode;
276         }
277 
278         /**
279          * Version of {@link BroadcastReceiver#setResultData(String)
280          * BroadcastReceiver.setResultData(String)} for
281          * asynchronous broadcast handling.
282          */
setResultData(String data)283         public final void setResultData(String data) {
284             checkSynchronousHint();
285             mResultData = data;
286         }
287 
288         /**
289          * Version of {@link BroadcastReceiver#getResultData()
290          * BroadcastReceiver.getResultData()} for
291          * asynchronous broadcast handling.
292          */
getResultData()293         public final String getResultData() {
294             return mResultData;
295         }
296 
297         /**
298          * Version of {@link BroadcastReceiver#setResultExtras(Bundle)
299          * BroadcastReceiver.setResultExtras(Bundle)} for
300          * asynchronous broadcast handling.
301          */
setResultExtras(Bundle extras)302         public final void setResultExtras(Bundle extras) {
303             checkSynchronousHint();
304             mResultExtras = extras;
305         }
306 
307         /**
308          * Version of {@link BroadcastReceiver#getResultExtras(boolean)
309          * BroadcastReceiver.getResultExtras(boolean)} for
310          * asynchronous broadcast handling.
311          */
getResultExtras(boolean makeMap)312         public final Bundle getResultExtras(boolean makeMap) {
313             Bundle e = mResultExtras;
314             if (!makeMap) return e;
315             if (e == null) mResultExtras = e = new Bundle();
316             return e;
317         }
318 
319         /**
320          * Version of {@link BroadcastReceiver#setResult(int, String, Bundle)
321          * BroadcastReceiver.setResult(int, String, Bundle)} for
322          * asynchronous broadcast handling.
323          */
setResult(int code, String data, Bundle extras)324         public final void setResult(int code, String data, Bundle extras) {
325             checkSynchronousHint();
326             mResultCode = code;
327             mResultData = data;
328             mResultExtras = extras;
329         }
330 
331         /**
332          * Version of {@link BroadcastReceiver#getAbortBroadcast()
333          * BroadcastReceiver.getAbortBroadcast()} for
334          * asynchronous broadcast handling.
335          */
getAbortBroadcast()336         public final boolean getAbortBroadcast() {
337             return mAbortBroadcast;
338         }
339 
340         /**
341          * Version of {@link BroadcastReceiver#abortBroadcast()
342          * BroadcastReceiver.abortBroadcast()} for
343          * asynchronous broadcast handling.
344          */
abortBroadcast()345         public final void abortBroadcast() {
346             checkSynchronousHint();
347             mAbortBroadcast = true;
348         }
349 
350         /**
351          * Version of {@link BroadcastReceiver#clearAbortBroadcast()
352          * BroadcastReceiver.clearAbortBroadcast()} for
353          * asynchronous broadcast handling.
354          */
clearAbortBroadcast()355         public final void clearAbortBroadcast() {
356             mAbortBroadcast = false;
357         }
358 
359         /**
360          * Finish the broadcast.  The current result will be sent and the
361          * next broadcast will proceed.
362          */
finish()363         public final void finish() {
364             if (mType == TYPE_COMPONENT) {
365                 final IActivityManager mgr = ActivityManagerNative.getDefault();
366                 if (QueuedWork.hasPendingWork()) {
367                     // If this is a broadcast component, we need to make sure any
368                     // queued work is complete before telling AM we are done, so
369                     // we don't have our process killed before that.  We now know
370                     // there is pending work; put another piece of work at the end
371                     // of the list to finish the broadcast, so we don't block this
372                     // thread (which may be the main thread) to have it finished.
373                     //
374                     // Note that we don't need to use QueuedWork.add() with the
375                     // runnable, since we know the AM is waiting for us until the
376                     // executor gets to it.
377                     QueuedWork.singleThreadExecutor().execute( new Runnable() {
378                         @Override public void run() {
379                             if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
380                                     "Finishing broadcast after work to component " + mToken);
381                             sendFinished(mgr);
382                         }
383                     });
384                 } else {
385                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
386                             "Finishing broadcast to component " + mToken);
387                     sendFinished(mgr);
388                 }
389             } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
390                 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
391                         "Finishing broadcast to " + mToken);
392                 final IActivityManager mgr = ActivityManagerNative.getDefault();
393                 sendFinished(mgr);
394             }
395         }
396 
397         /** @hide */
setExtrasClassLoader(ClassLoader cl)398         public void setExtrasClassLoader(ClassLoader cl) {
399             if (mResultExtras != null) {
400                 mResultExtras.setClassLoader(cl);
401             }
402         }
403 
404         /** @hide */
sendFinished(IActivityManager am)405         public void sendFinished(IActivityManager am) {
406             synchronized (this) {
407                 if (mFinished) {
408                     throw new IllegalStateException("Broadcast already finished");
409                 }
410                 mFinished = true;
411 
412                 try {
413                     if (mResultExtras != null) {
414                         mResultExtras.setAllowFds(false);
415                     }
416                     if (mOrderedHint) {
417                         am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
418                                 mAbortBroadcast);
419                     } else {
420                         // This broadcast was sent to a component; it is not ordered,
421                         // but we still need to tell the activity manager we are done.
422                         am.finishReceiver(mToken, 0, null, null, false);
423                     }
424                 } catch (RemoteException ex) {
425                 }
426             }
427         }
428 
checkSynchronousHint()429         void checkSynchronousHint() {
430             // Note that we don't assert when receiving the initial sticky value,
431             // since that may have come from an ordered broadcast.  We'll catch
432             // them later when the real broadcast happens again.
433             if (mOrderedHint || mInitialStickyHint) {
434                 return;
435             }
436             RuntimeException e = new RuntimeException(
437                     "BroadcastReceiver trying to return result during a non-ordered broadcast");
438             e.fillInStackTrace();
439             Log.e("BroadcastReceiver", e.getMessage(), e);
440         }
441     }
442 
BroadcastReceiver()443     public BroadcastReceiver() {
444     }
445 
446     /**
447      * This method is called when the BroadcastReceiver is receiving an Intent
448      * broadcast.  During this time you can use the other methods on
449      * BroadcastReceiver to view/modify the current result values.  This method
450      * is always called within the main thread of its process, unless you
451      * explicitly asked for it to be scheduled on a different thread using
452      * {@link android.content.Context#registerReceiver(BroadcastReceiver,
453      * IntentFilter, String, android.os.Handler)}. When it runs on the main
454      * thread you should
455      * never perform long-running operations in it (there is a timeout of
456      * 10 seconds that the system allows before considering the receiver to
457      * be blocked and a candidate to be killed). You cannot launch a popup dialog
458      * in your implementation of onReceive().
459      *
460      * <p><b>If this BroadcastReceiver was launched through a &lt;receiver&gt; tag,
461      * then the object is no longer alive after returning from this
462      * function.</b>  This means you should not perform any operations that
463      * return a result to you asynchronously -- in particular, for interacting
464      * with services, you should use
465      * {@link Context#startService(Intent)} instead of
466      * {@link Context#bindService(Intent, ServiceConnection, int)}.  If you wish
467      * to interact with a service that is already running, you can use
468      * {@link #peekService}.
469      *
470      * <p>The Intent filters used in {@link android.content.Context#registerReceiver}
471      * and in application manifests are <em>not</em> guaranteed to be exclusive. They
472      * are hints to the operating system about how to find suitable recipients. It is
473      * possible for senders to force delivery to specific recipients, bypassing filter
474      * resolution.  For this reason, {@link #onReceive(Context, Intent) onReceive()}
475      * implementations should respond only to known actions, ignoring any unexpected
476      * Intents that they may receive.
477      *
478      * @param context The Context in which the receiver is running.
479      * @param intent The Intent being received.
480      */
onReceive(Context context, Intent intent)481     public abstract void onReceive(Context context, Intent intent);
482 
483     /**
484      * This can be called by an application in {@link #onReceive} to allow
485      * it to keep the broadcast active after returning from that function.
486      * This does <em>not</em> change the expectation of being relatively
487      * responsive to the broadcast (finishing it within 10s), but does allow
488      * the implementation to move work related to it over to another thread
489      * to avoid glitching the main UI thread due to disk IO.
490      *
491      * @return Returns a {@link PendingResult} representing the result of
492      * the active broadcast.  The BroadcastRecord itself is no longer active;
493      * all data and other interaction must go through {@link PendingResult}
494      * APIs.  The {@link PendingResult#finish PendingResult.finish()} method
495      * must be called once processing of the broadcast is done.
496      */
goAsync()497     public final PendingResult goAsync() {
498         PendingResult res = mPendingResult;
499         mPendingResult = null;
500         return res;
501     }
502 
503     /**
504      * Provide a binder to an already-running service.  This method is synchronous
505      * and will not start the target service if it is not present, so it is safe
506      * to call from {@link #onReceive}.
507      *
508      * @param myContext The Context that had been passed to {@link #onReceive(Context, Intent)}
509      * @param service The Intent indicating the service you wish to use.  See {@link
510      * Context#startService(Intent)} for more information.
511      */
peekService(Context myContext, Intent service)512     public IBinder peekService(Context myContext, Intent service) {
513         IActivityManager am = ActivityManagerNative.getDefault();
514         IBinder binder = null;
515         try {
516             service.setAllowFds(false);
517             binder = am.peekService(service, service.resolveTypeIfNeeded(
518                     myContext.getContentResolver()));
519         } catch (RemoteException e) {
520         }
521         return binder;
522     }
523 
524     /**
525      * Change the current result code of this broadcast; only works with
526      * broadcasts sent through
527      * {@link Context#sendOrderedBroadcast(Intent, String)
528      * Context.sendOrderedBroadcast}.  Often uses the
529      * Activity {@link android.app.Activity#RESULT_CANCELED} and
530      * {@link android.app.Activity#RESULT_OK} constants, though the
531      * actual meaning of this value is ultimately up to the broadcaster.
532      *
533      * <p class="note">This method does not work with non-ordered broadcasts such
534      * as those sent with {@link Context#sendBroadcast(Intent)
535      * Context.sendBroadcast}</p>
536      *
537      * @param code The new result code.
538      *
539      * @see #setResult(int, String, Bundle)
540      */
setResultCode(int code)541     public final void setResultCode(int code) {
542         checkSynchronousHint();
543         mPendingResult.mResultCode = code;
544     }
545 
546     /**
547      * Retrieve the current result code, as set by the previous receiver.
548      *
549      * @return int The current result code.
550      */
getResultCode()551     public final int getResultCode() {
552         return mPendingResult != null ? mPendingResult.mResultCode : 0;
553     }
554 
555     /**
556      * Change the current result data of this broadcast; only works with
557      * broadcasts sent through
558      * {@link Context#sendOrderedBroadcast(Intent, String)
559      * Context.sendOrderedBroadcast}.  This is an arbitrary
560      * string whose interpretation is up to the broadcaster.
561      *
562      * <p><strong>This method does not work with non-ordered broadcasts such
563      * as those sent with {@link Context#sendBroadcast(Intent)
564      * Context.sendBroadcast}</strong></p>
565      *
566      * @param data The new result data; may be null.
567      *
568      * @see #setResult(int, String, Bundle)
569      */
setResultData(String data)570     public final void setResultData(String data) {
571         checkSynchronousHint();
572         mPendingResult.mResultData = data;
573     }
574 
575     /**
576      * Retrieve the current result data, as set by the previous receiver.
577      * Often this is null.
578      *
579      * @return String The current result data; may be null.
580      */
getResultData()581     public final String getResultData() {
582         return mPendingResult != null ? mPendingResult.mResultData : null;
583     }
584 
585     /**
586      * Change the current result extras of this broadcast; only works with
587      * broadcasts sent through
588      * {@link Context#sendOrderedBroadcast(Intent, String)
589      * Context.sendOrderedBroadcast}.  This is a Bundle
590      * holding arbitrary data, whose interpretation is up to the
591      * broadcaster.  Can be set to null.  Calling this method completely
592      * replaces the current map (if any).
593      *
594      * <p><strong>This method does not work with non-ordered broadcasts such
595      * as those sent with {@link Context#sendBroadcast(Intent)
596      * Context.sendBroadcast}</strong></p>
597      *
598      * @param extras The new extra data map; may be null.
599      *
600      * @see #setResult(int, String, Bundle)
601      */
setResultExtras(Bundle extras)602     public final void setResultExtras(Bundle extras) {
603         checkSynchronousHint();
604         mPendingResult.mResultExtras = extras;
605     }
606 
607     /**
608      * Retrieve the current result extra data, as set by the previous receiver.
609      * Any changes you make to the returned Map will be propagated to the next
610      * receiver.
611      *
612      * @param makeMap If true then a new empty Map will be made for you if the
613      *                current Map is null; if false you should be prepared to
614      *                receive a null Map.
615      *
616      * @return Map The current extras map.
617      */
getResultExtras(boolean makeMap)618     public final Bundle getResultExtras(boolean makeMap) {
619         if (mPendingResult == null) {
620             return null;
621         }
622         Bundle e = mPendingResult.mResultExtras;
623         if (!makeMap) return e;
624         if (e == null) mPendingResult.mResultExtras = e = new Bundle();
625         return e;
626     }
627 
628     /**
629      * Change all of the result data returned from this broadcasts; only works
630      * with broadcasts sent through
631      * {@link Context#sendOrderedBroadcast(Intent, String)
632      * Context.sendOrderedBroadcast}.  All current result data is replaced
633      * by the value given to this method.
634      *
635      * <p><strong>This method does not work with non-ordered broadcasts such
636      * as those sent with {@link Context#sendBroadcast(Intent)
637      * Context.sendBroadcast}</strong></p>
638      *
639      * @param code The new result code.  Often uses the
640      * Activity {@link android.app.Activity#RESULT_CANCELED} and
641      * {@link android.app.Activity#RESULT_OK} constants, though the
642      * actual meaning of this value is ultimately up to the broadcaster.
643      * @param data The new result data.  This is an arbitrary
644      * string whose interpretation is up to the broadcaster; may be null.
645      * @param extras The new extra data map.  This is a Bundle
646      * holding arbitrary data, whose interpretation is up to the
647      * broadcaster.  Can be set to null.  This completely
648      * replaces the current map (if any).
649      */
setResult(int code, String data, Bundle extras)650     public final void setResult(int code, String data, Bundle extras) {
651         checkSynchronousHint();
652         mPendingResult.mResultCode = code;
653         mPendingResult.mResultData = data;
654         mPendingResult.mResultExtras = extras;
655     }
656 
657     /**
658      * Returns the flag indicating whether or not this receiver should
659      * abort the current broadcast.
660      *
661      * @return True if the broadcast should be aborted.
662      */
getAbortBroadcast()663     public final boolean getAbortBroadcast() {
664         return mPendingResult != null ? mPendingResult.mAbortBroadcast : false;
665     }
666 
667     /**
668      * Sets the flag indicating that this receiver should abort the
669      * current broadcast; only works with broadcasts sent through
670      * {@link Context#sendOrderedBroadcast(Intent, String)
671      * Context.sendOrderedBroadcast}.  This will prevent
672      * any other broadcast receivers from receiving the broadcast. It will still
673      * call {@link #onReceive} of the BroadcastReceiver that the caller of
674      * {@link Context#sendOrderedBroadcast(Intent, String)
675      * Context.sendOrderedBroadcast} passed in.
676      *
677      * <p><strong>This method does not work with non-ordered broadcasts such
678      * as those sent with {@link Context#sendBroadcast(Intent)
679      * Context.sendBroadcast}</strong></p>
680      */
abortBroadcast()681     public final void abortBroadcast() {
682         checkSynchronousHint();
683         mPendingResult.mAbortBroadcast = true;
684     }
685 
686     /**
687      * Clears the flag indicating that this receiver should abort the current
688      * broadcast.
689      */
clearAbortBroadcast()690     public final void clearAbortBroadcast() {
691         if (mPendingResult != null) {
692             mPendingResult.mAbortBroadcast = false;
693         }
694     }
695 
696     /**
697      * Returns true if the receiver is currently processing an ordered
698      * broadcast.
699      */
isOrderedBroadcast()700     public final boolean isOrderedBroadcast() {
701         return mPendingResult != null ? mPendingResult.mOrderedHint : false;
702     }
703 
704     /**
705      * Returns true if the receiver is currently processing the initial
706      * value of a sticky broadcast -- that is, the value that was last
707      * broadcast and is currently held in the sticky cache, so this is
708      * not directly the result of a broadcast right now.
709      */
isInitialStickyBroadcast()710     public final boolean isInitialStickyBroadcast() {
711         return mPendingResult != null ? mPendingResult.mInitialStickyHint : false;
712     }
713 
714     /**
715      * For internal use, sets the hint about whether this BroadcastReceiver is
716      * running in ordered mode.
717      */
setOrderedHint(boolean isOrdered)718     public final void setOrderedHint(boolean isOrdered) {
719         // Accidentally left in the SDK.
720     }
721 
722     /**
723      * For internal use to set the result data that is active. @hide
724      */
setPendingResult(PendingResult result)725     public final void setPendingResult(PendingResult result) {
726         mPendingResult = result;
727     }
728 
729     /**
730      * For internal use to set the result data that is active. @hide
731      */
getPendingResult()732     public final PendingResult getPendingResult() {
733         return mPendingResult;
734     }
735 
736     /**
737      * Control inclusion of debugging help for mismatched
738      * calls to {@ Context#registerReceiver(BroadcastReceiver, IntentFilter)
739      * Context.registerReceiver()}.
740      * If called with true, before given to registerReceiver(), then the
741      * callstack of the following {@link Context#unregisterReceiver(BroadcastReceiver)
742      * Context.unregisterReceiver()} call is retained, to be printed if a later
743      * incorrect unregister call is made.  Note that doing this requires retaining
744      * information about the BroadcastReceiver for the lifetime of the app,
745      * resulting in a leak -- this should only be used for debugging.
746      */
setDebugUnregister(boolean debug)747     public final void setDebugUnregister(boolean debug) {
748         mDebugUnregister = debug;
749     }
750 
751     /**
752      * Return the last value given to {@link #setDebugUnregister}.
753      */
getDebugUnregister()754     public final boolean getDebugUnregister() {
755         return mDebugUnregister;
756     }
757 
checkSynchronousHint()758     void checkSynchronousHint() {
759         if (mPendingResult == null) {
760             throw new IllegalStateException("Call while result is not pending");
761         }
762 
763         // Note that we don't assert when receiving the initial sticky value,
764         // since that may have come from an ordered broadcast.  We'll catch
765         // them later when the real broadcast happens again.
766         if (mPendingResult.mOrderedHint || mPendingResult.mInitialStickyHint) {
767             return;
768         }
769         RuntimeException e = new RuntimeException(
770                 "BroadcastReceiver trying to return result during a non-ordered broadcast");
771         e.fillInStackTrace();
772         Log.e("BroadcastReceiver", e.getMessage(), e);
773     }
774 }
775 
776