• 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.annotation.NonNull;
20 import android.annotation.SystemApi;
21 import android.app.ActivityManager;
22 import android.app.ActivityThread;
23 import android.app.IActivityManager;
24 import android.app.QueuedWork;
25 import android.compat.annotation.UnsupportedAppUsage;
26 import android.os.Build;
27 import android.os.Bundle;
28 import android.os.IBinder;
29 import android.os.RemoteException;
30 import android.os.Trace;
31 import android.os.UserHandle;
32 import android.util.Log;
33 import android.util.Slog;
34 
35 /**
36  * Base class for code that receives and handles broadcast intents sent by
37  * {@link android.content.Context#sendBroadcast(Intent)}.
38  *
39  * <p>You can either dynamically register an instance of this class with
40  * {@link Context#registerReceiver Context.registerReceiver()}
41  * or statically declare an implementation with the
42  * {@link android.R.styleable#AndroidManifestReceiver &lt;receiver&gt;}
43  * tag in your <code>AndroidManifest.xml</code>.
44  *
45  * <div class="special reference">
46  * <h3>Developer Guides</h3>
47  * <p>For more information about using BroadcastReceiver, read the
48  * <a href="{@docRoot}guide/components/broadcasts.html">Broadcasts</a> developer guide.</p></div>
49  *
50  */
51 public abstract class BroadcastReceiver {
52     @UnsupportedAppUsage
53     private PendingResult mPendingResult;
54     private boolean mDebugUnregister;
55 
56     /**
57      * State for a result that is pending for a broadcast receiver.  Returned
58      * by {@link BroadcastReceiver#goAsync() goAsync()}
59      * while in {@link BroadcastReceiver#onReceive BroadcastReceiver.onReceive()}.
60      * This allows you to return from onReceive() without having the broadcast
61      * terminate; you must call {@link #finish()} once you are done with the
62      * broadcast.  This allows you to process the broadcast off of the main
63      * thread of your app.
64      *
65      * <p>Note on threading: the state inside of this class is not itself
66      * thread-safe, however you can use it from any thread if you properly
67      * sure that you do not have races.  Typically this means you will hand
68      * the entire object to another thread, which will be solely responsible
69      * for setting any results and finally calling {@link #finish()}.
70      */
71     public static class PendingResult {
72         /** @hide */
73         public static final int TYPE_COMPONENT = 0;
74         /** @hide */
75         public static final int TYPE_REGISTERED = 1;
76         /** @hide */
77         public static final int TYPE_UNREGISTERED = 2;
78 
79         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
80         final int mType;
81         @UnsupportedAppUsage
82         final boolean mOrderedHint;
83         @UnsupportedAppUsage
84         final boolean mInitialStickyHint;
85         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
86         final IBinder mToken;
87         @UnsupportedAppUsage
88         final int mSendingUser;
89         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
90         final int mFlags;
91 
92         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
93         int mResultCode;
94         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
95         String mResultData;
96         @UnsupportedAppUsage
97         Bundle mResultExtras;
98         @UnsupportedAppUsage
99         boolean mAbortBroadcast;
100         @UnsupportedAppUsage
101         boolean mFinished;
102         String mReceiverClassName;
103 
104         /** @hide */
105         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
PendingResult(int resultCode, String resultData, Bundle resultExtras, int type, boolean ordered, boolean sticky, IBinder token, int userId, int flags)106         public PendingResult(int resultCode, String resultData, Bundle resultExtras, int type,
107                 boolean ordered, boolean sticky, IBinder token, int userId, int flags) {
108             mResultCode = resultCode;
109             mResultData = resultData;
110             mResultExtras = resultExtras;
111             mType = type;
112             mOrderedHint = ordered;
113             mInitialStickyHint = sticky;
114             mToken = token;
115             mSendingUser = userId;
116             mFlags = flags;
117         }
118 
119         /**
120          * Version of {@link BroadcastReceiver#setResultCode(int)
121          * BroadcastReceiver.setResultCode(int)} for
122          * asynchronous broadcast handling.
123          */
setResultCode(int code)124         public final void setResultCode(int code) {
125             checkSynchronousHint();
126             mResultCode = code;
127         }
128 
129         /**
130          * Version of {@link BroadcastReceiver#getResultCode()
131          * BroadcastReceiver.getResultCode()} for
132          * asynchronous broadcast handling.
133          */
getResultCode()134         public final int getResultCode() {
135             return mResultCode;
136         }
137 
138         /**
139          * Version of {@link BroadcastReceiver#setResultData(String)
140          * BroadcastReceiver.setResultData(String)} for
141          * asynchronous broadcast handling.
142          */
setResultData(String data)143         public final void setResultData(String data) {
144             checkSynchronousHint();
145             mResultData = data;
146         }
147 
148         /**
149          * Version of {@link BroadcastReceiver#getResultData()
150          * BroadcastReceiver.getResultData()} for
151          * asynchronous broadcast handling.
152          */
getResultData()153         public final String getResultData() {
154             return mResultData;
155         }
156 
157         /**
158          * Version of {@link BroadcastReceiver#setResultExtras(Bundle)
159          * BroadcastReceiver.setResultExtras(Bundle)} for
160          * asynchronous broadcast handling.
161          */
setResultExtras(Bundle extras)162         public final void setResultExtras(Bundle extras) {
163             checkSynchronousHint();
164             mResultExtras = extras;
165         }
166 
167         /**
168          * Version of {@link BroadcastReceiver#getResultExtras(boolean)
169          * BroadcastReceiver.getResultExtras(boolean)} for
170          * asynchronous broadcast handling.
171          */
getResultExtras(boolean makeMap)172         public final Bundle getResultExtras(boolean makeMap) {
173             Bundle e = mResultExtras;
174             if (!makeMap) return e;
175             if (e == null) mResultExtras = e = new Bundle();
176             return e;
177         }
178 
179         /**
180          * Version of {@link BroadcastReceiver#setResult(int, String, Bundle)
181          * BroadcastReceiver.setResult(int, String, Bundle)} for
182          * asynchronous broadcast handling.
183          */
setResult(int code, String data, Bundle extras)184         public final void setResult(int code, String data, Bundle extras) {
185             checkSynchronousHint();
186             mResultCode = code;
187             mResultData = data;
188             mResultExtras = extras;
189         }
190 
191         /**
192          * Version of {@link BroadcastReceiver#getAbortBroadcast()
193          * BroadcastReceiver.getAbortBroadcast()} for
194          * asynchronous broadcast handling.
195          */
getAbortBroadcast()196         public final boolean getAbortBroadcast() {
197             return mAbortBroadcast;
198         }
199 
200         /**
201          * Version of {@link BroadcastReceiver#abortBroadcast()
202          * BroadcastReceiver.abortBroadcast()} for
203          * asynchronous broadcast handling.
204          */
abortBroadcast()205         public final void abortBroadcast() {
206             checkSynchronousHint();
207             mAbortBroadcast = true;
208         }
209 
210         /**
211          * Version of {@link BroadcastReceiver#clearAbortBroadcast()
212          * BroadcastReceiver.clearAbortBroadcast()} for
213          * asynchronous broadcast handling.
214          */
clearAbortBroadcast()215         public final void clearAbortBroadcast() {
216             mAbortBroadcast = false;
217         }
218 
219         /**
220          * Finish the broadcast.  The current result will be sent and the
221          * next broadcast will proceed.
222          */
finish()223         public final void finish() {
224             if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
225                 Trace.traceCounter(Trace.TRACE_TAG_ACTIVITY_MANAGER,
226                         "PendingResult#finish#ClassName:" + mReceiverClassName,
227                         1);
228             }
229 
230             if (mType == TYPE_COMPONENT) {
231                 final IActivityManager mgr = ActivityManager.getService();
232                 if (QueuedWork.hasPendingWork()) {
233                     // If this is a broadcast component, we need to make sure any
234                     // queued work is complete before telling AM we are done, so
235                     // we don't have our process killed before that.  We now know
236                     // there is pending work; put another piece of work at the end
237                     // of the list to finish the broadcast, so we don't block this
238                     // thread (which may be the main thread) to have it finished.
239                     //
240                     // Note that we don't need to use QueuedWork.addFinisher() with the
241                     // runnable, since we know the AM is waiting for us until the
242                     // executor gets to it.
243                     QueuedWork.queue(new Runnable() {
244                         @Override public void run() {
245                             if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
246                                     "Finishing broadcast after work to component " + mToken);
247                             sendFinished(mgr);
248                         }
249                     }, false);
250                 } else {
251                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
252                             "Finishing broadcast to component " + mToken);
253                     sendFinished(mgr);
254                 }
255             } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
256                 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
257                         "Finishing broadcast to " + mToken);
258                 final IActivityManager mgr = ActivityManager.getService();
259                 sendFinished(mgr);
260             }
261         }
262 
263         /** @hide */
setExtrasClassLoader(ClassLoader cl)264         public void setExtrasClassLoader(ClassLoader cl) {
265             if (mResultExtras != null) {
266                 mResultExtras.setClassLoader(cl);
267             }
268         }
269 
270         /** @hide */
sendFinished(IActivityManager am)271         public void sendFinished(IActivityManager am) {
272             synchronized (this) {
273                 if (mFinished) {
274                     throw new IllegalStateException("Broadcast already finished");
275                 }
276                 mFinished = true;
277 
278                 try {
279                     if (mResultExtras != null) {
280                         mResultExtras.setAllowFds(false);
281                     }
282                     if (mOrderedHint) {
283                         am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
284                                 mAbortBroadcast, mFlags);
285                     } else {
286                         // This broadcast was sent to a component; it is not ordered,
287                         // but we still need to tell the activity manager we are done.
288                         am.finishReceiver(mToken, 0, null, null, false, mFlags);
289                     }
290                 } catch (RemoteException ex) {
291                 }
292             }
293         }
294 
295         /** @hide */
getSendingUserId()296         public int getSendingUserId() {
297             return mSendingUser;
298         }
299 
checkSynchronousHint()300         void checkSynchronousHint() {
301             // Note that we don't assert when receiving the initial sticky value,
302             // since that may have come from an ordered broadcast.  We'll catch
303             // them later when the real broadcast happens again.
304             if (mOrderedHint || mInitialStickyHint) {
305                 return;
306             }
307             RuntimeException e = new RuntimeException(
308                     "BroadcastReceiver trying to return result during a non-ordered broadcast");
309             e.fillInStackTrace();
310             Log.e("BroadcastReceiver", e.getMessage(), e);
311         }
312     }
313 
BroadcastReceiver()314     public BroadcastReceiver() {
315     }
316 
317     /**
318      * This method is called when the BroadcastReceiver is receiving an Intent
319      * broadcast.  During this time you can use the other methods on
320      * BroadcastReceiver to view/modify the current result values.  This method
321      * is always called within the main thread of its process, unless you
322      * explicitly asked for it to be scheduled on a different thread using
323      * {@link android.content.Context#registerReceiver(BroadcastReceiver,
324      * IntentFilter, String, android.os.Handler)}. When it runs on the main
325      * thread you should
326      * never perform long-running operations in it (there is a timeout of
327      * 10 seconds that the system allows before considering the receiver to
328      * be blocked and a candidate to be killed). You cannot launch a popup dialog
329      * in your implementation of onReceive().
330      *
331      * <p><b>If this BroadcastReceiver was launched through a &lt;receiver&gt; tag,
332      * then the object is no longer alive after returning from this
333      * function.</b> This means you should not perform any operations that
334      * return a result to you asynchronously. If you need to perform any follow up
335      * background work, schedule a {@link android.app.job.JobService} with
336      * {@link android.app.job.JobScheduler}.
337      *
338      * If you wish to interact with a service that is already running and previously
339      * bound using {@link android.content.Context#bindService(Intent, ServiceConnection, int) bindService()},
340      * you can use {@link #peekService}.
341      *
342      * <p>The Intent filters used in {@link android.content.Context#registerReceiver}
343      * and in application manifests are <em>not</em> guaranteed to be exclusive. They
344      * are hints to the operating system about how to find suitable recipients. It is
345      * possible for senders to force delivery to specific recipients, bypassing filter
346      * resolution.  For this reason, {@link #onReceive(Context, Intent) onReceive()}
347      * implementations should respond only to known actions, ignoring any unexpected
348      * Intents that they may receive.
349      *
350      * @param context The Context in which the receiver is running.
351      * @param intent The Intent being received.
352      */
onReceive(Context context, Intent intent)353     public abstract void onReceive(Context context, Intent intent);
354 
355     /**
356      * This can be called by an application in {@link #onReceive} to allow
357      * it to keep the broadcast active after returning from that function.
358      * This does <em>not</em> change the expectation of being relatively
359      * responsive to the broadcast, but does allow
360      * the implementation to move work related to it over to another thread
361      * to avoid glitching the main UI thread due to disk IO.
362      *
363      * <p>As a general rule, broadcast receivers are allowed to run for up to 10 seconds
364      * before they system will consider them non-responsive and ANR the app.  Since these usually
365      * execute on the app's main thread, they are already bound by the ~5 second time limit
366      * of various operations that can happen there (not to mention just avoiding UI jank), so
367      * the receive limit is generally not of concern.  However, once you use {@code goAsync}, though
368      * able to be off the main thread, the broadcast execution limit still applies, and that
369      * includes the time spent between calling this method and ultimately
370      * {@link PendingResult#finish() PendingResult.finish()}.</p>
371      *
372      * <p>If you are taking advantage of this method to have more time to execute, it is useful
373      * to know that the available time can be longer in certain situations.  In particular, if
374      * the broadcast you are receiving is not a foreground broadcast (that is, the sender has not
375      * used {@link Intent#FLAG_RECEIVER_FOREGROUND}), then more time is allowed for the receivers
376      * to run, allowing them to execute for 30 seconds or even a bit more.  This is something that
377      * receivers should rarely take advantage of (long work should be punted to another system
378      * facility such as {@link android.app.job.JobScheduler}, {@link android.app.Service}, or
379      * see especially {@link androidx.core.app.JobIntentService}), but can be useful in
380      * certain rare cases where it is necessary to do some work as soon as the broadcast is
381      * delivered.  Keep in mind that the work you do here will block further broadcasts until
382      * it completes, so taking advantage of this at all excessively can be counter-productive
383      * and cause later events to be received more slowly.</p>
384      *
385      * @return Returns a {@link PendingResult} representing the result of
386      * the active broadcast.  The BroadcastRecord itself is no longer active;
387      * all data and other interaction must go through {@link PendingResult}
388      * APIs.  The {@link PendingResult#finish PendingResult.finish()} method
389      * must be called once processing of the broadcast is done.
390      */
goAsync()391     public final PendingResult goAsync() {
392         PendingResult res = mPendingResult;
393         mPendingResult = null;
394 
395         if (res != null && Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
396             res.mReceiverClassName = getClass().getName();
397             Trace.traceCounter(Trace.TRACE_TAG_ACTIVITY_MANAGER,
398                     "BroadcastReceiver#goAsync#ClassName:" + res.mReceiverClassName,
399                     1);
400         }
401 
402         return res;
403     }
404 
405     /**
406      * Provide a binder to an already-bound service.  This method is synchronous
407      * and will not start the target service if it is not present, so it is safe
408      * to call from {@link #onReceive}.
409      *
410      * For peekService() to return a non null {@link android.os.IBinder} interface
411      * the service must have published it before. In other words some component
412      * must have called {@link android.content.Context#bindService(Intent, ServiceConnection, int)} on it.
413      *
414      * @param myContext The Context that had been passed to {@link #onReceive(Context, Intent)}
415      * @param service Identifies the already-bound service you wish to use. See
416      * {@link android.content.Context#bindService(Intent, ServiceConnection, int)}
417      * for more information.
418      */
peekService(Context myContext, Intent service)419     public IBinder peekService(Context myContext, Intent service) {
420         IActivityManager am = ActivityManager.getService();
421         IBinder binder = null;
422         try {
423             service.prepareToLeaveProcess(myContext);
424             binder = am.peekService(service, service.resolveTypeIfNeeded(
425                     myContext.getContentResolver()), myContext.getOpPackageName());
426         } catch (RemoteException e) {
427         }
428         return binder;
429     }
430 
431     /**
432      * Change the current result code of this broadcast; only works with
433      * broadcasts sent through
434      * {@link Context#sendOrderedBroadcast(Intent, String)
435      * Context.sendOrderedBroadcast}.  Often uses the
436      * Activity {@link android.app.Activity#RESULT_CANCELED} and
437      * {@link android.app.Activity#RESULT_OK} constants, though the
438      * actual meaning of this value is ultimately up to the broadcaster.
439      *
440      * <p class="note">This method does not work with non-ordered broadcasts such
441      * as those sent with {@link Context#sendBroadcast(Intent)
442      * Context.sendBroadcast}</p>
443      *
444      * @param code The new result code.
445      *
446      * @see #setResult(int, String, Bundle)
447      */
setResultCode(int code)448     public final void setResultCode(int code) {
449         checkSynchronousHint();
450         mPendingResult.mResultCode = code;
451     }
452 
453     /**
454      * Retrieve the current result code, as set by the previous receiver.
455      *
456      * @return int The current result code.
457      */
getResultCode()458     public final int getResultCode() {
459         return mPendingResult != null ? mPendingResult.mResultCode : 0;
460     }
461 
462     /**
463      * Change the current result data of this broadcast; only works with
464      * broadcasts sent through
465      * {@link Context#sendOrderedBroadcast(Intent, String)
466      * Context.sendOrderedBroadcast}.  This is an arbitrary
467      * string whose interpretation is up to the broadcaster.
468      *
469      * <p><strong>This method does not work with non-ordered broadcasts such
470      * as those sent with {@link Context#sendBroadcast(Intent)
471      * Context.sendBroadcast}</strong></p>
472      *
473      * @param data The new result data; may be null.
474      *
475      * @see #setResult(int, String, Bundle)
476      */
setResultData(String data)477     public final void setResultData(String data) {
478         checkSynchronousHint();
479         mPendingResult.mResultData = data;
480     }
481 
482     /**
483      * Retrieve the current result data, as set by the previous receiver.
484      * Often this is null.
485      *
486      * @return String The current result data; may be null.
487      */
getResultData()488     public final String getResultData() {
489         return mPendingResult != null ? mPendingResult.mResultData : null;
490     }
491 
492     /**
493      * Change the current result extras of this broadcast; only works with
494      * broadcasts sent through
495      * {@link Context#sendOrderedBroadcast(Intent, String)
496      * Context.sendOrderedBroadcast}.  This is a Bundle
497      * holding arbitrary data, whose interpretation is up to the
498      * broadcaster.  Can be set to null.  Calling this method completely
499      * replaces the current map (if any).
500      *
501      * <p><strong>This method does not work with non-ordered broadcasts such
502      * as those sent with {@link Context#sendBroadcast(Intent)
503      * Context.sendBroadcast}</strong></p>
504      *
505      * @param extras The new extra data map; may be null.
506      *
507      * @see #setResult(int, String, Bundle)
508      */
setResultExtras(Bundle extras)509     public final void setResultExtras(Bundle extras) {
510         checkSynchronousHint();
511         mPendingResult.mResultExtras = extras;
512     }
513 
514     /**
515      * Retrieve the current result extra data, as set by the previous receiver.
516      * Any changes you make to the returned Map will be propagated to the next
517      * receiver.
518      *
519      * @param makeMap If true then a new empty Map will be made for you if the
520      *                current Map is null; if false you should be prepared to
521      *                receive a null Map.
522      *
523      * @return Map The current extras map.
524      */
getResultExtras(boolean makeMap)525     public final Bundle getResultExtras(boolean makeMap) {
526         if (mPendingResult == null) {
527             return null;
528         }
529         Bundle e = mPendingResult.mResultExtras;
530         if (!makeMap) return e;
531         if (e == null) mPendingResult.mResultExtras = e = new Bundle();
532         return e;
533     }
534 
535     /**
536      * Change all of the result data returned from this broadcasts; only works
537      * with broadcasts sent through
538      * {@link Context#sendOrderedBroadcast(Intent, String)
539      * Context.sendOrderedBroadcast}.  All current result data is replaced
540      * by the value given to this method.
541      *
542      * <p><strong>This method does not work with non-ordered broadcasts such
543      * as those sent with {@link Context#sendBroadcast(Intent)
544      * Context.sendBroadcast}</strong></p>
545      *
546      * @param code The new result code.  Often uses the
547      * Activity {@link android.app.Activity#RESULT_CANCELED} and
548      * {@link android.app.Activity#RESULT_OK} constants, though the
549      * actual meaning of this value is ultimately up to the broadcaster.
550      * @param data The new result data.  This is an arbitrary
551      * string whose interpretation is up to the broadcaster; may be null.
552      * @param extras The new extra data map.  This is a Bundle
553      * holding arbitrary data, whose interpretation is up to the
554      * broadcaster.  Can be set to null.  This completely
555      * replaces the current map (if any).
556      */
setResult(int code, String data, Bundle extras)557     public final void setResult(int code, String data, Bundle extras) {
558         checkSynchronousHint();
559         mPendingResult.mResultCode = code;
560         mPendingResult.mResultData = data;
561         mPendingResult.mResultExtras = extras;
562     }
563 
564     /**
565      * Returns the flag indicating whether or not this receiver should
566      * abort the current broadcast.
567      *
568      * @return True if the broadcast should be aborted.
569      */
getAbortBroadcast()570     public final boolean getAbortBroadcast() {
571         return mPendingResult != null ? mPendingResult.mAbortBroadcast : false;
572     }
573 
574     /**
575      * Sets the flag indicating that this receiver should abort the
576      * current broadcast; only works with broadcasts sent through
577      * {@link Context#sendOrderedBroadcast(Intent, String)
578      * Context.sendOrderedBroadcast}.  This will prevent
579      * any other broadcast receivers from receiving the broadcast. It will still
580      * call {@link #onReceive} of the BroadcastReceiver that the caller of
581      * {@link Context#sendOrderedBroadcast(Intent, String)
582      * Context.sendOrderedBroadcast} passed in.
583      *
584      * <p><strong>This method does not work with non-ordered broadcasts such
585      * as those sent with {@link Context#sendBroadcast(Intent)
586      * Context.sendBroadcast}</strong></p>
587      */
abortBroadcast()588     public final void abortBroadcast() {
589         checkSynchronousHint();
590         mPendingResult.mAbortBroadcast = true;
591     }
592 
593     /**
594      * Clears the flag indicating that this receiver should abort the current
595      * broadcast.
596      */
clearAbortBroadcast()597     public final void clearAbortBroadcast() {
598         if (mPendingResult != null) {
599             mPendingResult.mAbortBroadcast = false;
600         }
601     }
602 
603     /**
604      * Returns true if the receiver is currently processing an ordered
605      * broadcast.
606      */
isOrderedBroadcast()607     public final boolean isOrderedBroadcast() {
608         return mPendingResult != null ? mPendingResult.mOrderedHint : false;
609     }
610 
611     /**
612      * Returns true if the receiver is currently processing the initial
613      * value of a sticky broadcast -- that is, the value that was last
614      * broadcast and is currently held in the sticky cache, so this is
615      * not directly the result of a broadcast right now.
616      */
isInitialStickyBroadcast()617     public final boolean isInitialStickyBroadcast() {
618         return mPendingResult != null ? mPendingResult.mInitialStickyHint : false;
619     }
620 
621     /**
622      * For internal use, sets the hint about whether this BroadcastReceiver is
623      * running in ordered mode.
624      */
setOrderedHint(boolean isOrdered)625     public final void setOrderedHint(boolean isOrdered) {
626         // Accidentally left in the SDK.
627     }
628 
629     /**
630      * For internal use to set the result data that is active. @hide
631      */
632     @UnsupportedAppUsage
setPendingResult(PendingResult result)633     public final void setPendingResult(PendingResult result) {
634         mPendingResult = result;
635     }
636 
637     /**
638      * For internal use to set the result data that is active. @hide
639      */
640     @UnsupportedAppUsage
getPendingResult()641     public final PendingResult getPendingResult() {
642         return mPendingResult;
643     }
644 
645     /**
646      * Returns the user that the broadcast was sent to.
647      *
648      * <p>It can be used in a receiver registered by
649      * {@link Context#registerReceiverForAllUsers Context.registerReceiverForAllUsers()}
650      * to determine on which user the broadcast was sent.
651      *
652      * @hide
653      */
654     @SystemApi
getSendingUser()655     public final @NonNull UserHandle getSendingUser() {
656         return UserHandle.of(getSendingUserId());
657     }
658 
659     /** @hide */
getSendingUserId()660     public int getSendingUserId() {
661         return mPendingResult.mSendingUser;
662     }
663 
664     /**
665      * Control inclusion of debugging help for mismatched
666      * calls to {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
667      * Context.registerReceiver()}.
668      * If called with true, before given to registerReceiver(), then the
669      * callstack of the following {@link Context#unregisterReceiver(BroadcastReceiver)
670      * Context.unregisterReceiver()} call is retained, to be printed if a later
671      * incorrect unregister call is made.  Note that doing this requires retaining
672      * information about the BroadcastReceiver for the lifetime of the app,
673      * resulting in a leak -- this should only be used for debugging.
674      */
setDebugUnregister(boolean debug)675     public final void setDebugUnregister(boolean debug) {
676         mDebugUnregister = debug;
677     }
678 
679     /**
680      * Return the last value given to {@link #setDebugUnregister}.
681      */
getDebugUnregister()682     public final boolean getDebugUnregister() {
683         return mDebugUnregister;
684     }
685 
checkSynchronousHint()686     void checkSynchronousHint() {
687         if (mPendingResult == null) {
688             throw new IllegalStateException("Call while result is not pending");
689         }
690 
691         // Note that we don't assert when receiving the initial sticky value,
692         // since that may have come from an ordered broadcast.  We'll catch
693         // them later when the real broadcast happens again.
694         if (mPendingResult.mOrderedHint || mPendingResult.mInitialStickyHint) {
695             return;
696         }
697         RuntimeException e = new RuntimeException(
698                 "BroadcastReceiver trying to return result during a non-ordered broadcast");
699         e.fillInStackTrace();
700         Log.e("BroadcastReceiver", e.getMessage(), e);
701     }
702 }
703 
704