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