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