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 <receiver>} 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 <receiver> 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