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