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