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.os; 18 19 import android.annotation.Nullable; 20 import android.compat.annotation.UnsupportedAppUsage; 21 import android.util.TimeUtils; 22 import android.util.proto.ProtoOutputStream; 23 24 import com.android.internal.annotations.VisibleForTesting; 25 26 /** 27 * 28 * Defines a message containing a description and arbitrary data object that can be 29 * sent to a {@link Handler}. This object contains two extra int fields and an 30 * extra object field that allow you to not do allocations in many cases. 31 * 32 * <p class="note">While the constructor of Message is public, the best way to get 33 * one of these is to call {@link #obtain Message.obtain()} or one of the 34 * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull 35 * them from a pool of recycled objects.</p> 36 */ 37 @android.ravenwood.annotation.RavenwoodKeepWholeClass 38 public final class Message implements Parcelable { 39 /** 40 * User-defined message code so that the recipient can identify 41 * what this message is about. Each {@link Handler} has its own name-space 42 * for message codes, so you do not need to worry about yours conflicting 43 * with other handlers. 44 */ 45 public int what; 46 47 /** 48 * arg1 and arg2 are lower-cost alternatives to using 49 * {@link #setData(Bundle) setData()} if you only need to store a 50 * few integer values. 51 */ 52 public int arg1; 53 54 /** 55 * arg1 and arg2 are lower-cost alternatives to using 56 * {@link #setData(Bundle) setData()} if you only need to store a 57 * few integer values. 58 */ 59 public int arg2; 60 61 /** 62 * An arbitrary object to send to the recipient. When using 63 * {@link Messenger} to send the message across processes this can only 64 * be non-null if it contains a Parcelable of a framework class (not one 65 * implemented by the application). For other data transfer use 66 * {@link #setData}. 67 * 68 * <p>Note that Parcelable objects here are not supported prior to 69 * the {@link android.os.Build.VERSION_CODES#FROYO} release. 70 */ 71 public Object obj; 72 73 /** 74 * Optional Messenger where replies to this message can be sent. The 75 * semantics of exactly how this is used are up to the sender and 76 * receiver. 77 */ 78 public Messenger replyTo; 79 80 /** 81 * Indicates that the uid is not set; 82 * 83 * @hide Only for use within the system server. 84 */ 85 public static final int UID_NONE = -1; 86 87 /** 88 * Optional field indicating the uid that sent the message. This is 89 * only valid for messages posted by a {@link Messenger}; otherwise, 90 * it will be -1. 91 */ 92 public int sendingUid = UID_NONE; 93 94 /** 95 * Optional field indicating the uid that caused this message to be enqueued. 96 * 97 * @hide Only for use within the system server. 98 */ 99 public int workSourceUid = UID_NONE; 100 101 /** If set message is in use. 102 * This flag is set when the message is enqueued and remains set while it 103 * is delivered and afterwards when it is recycled. The flag is only cleared 104 * when a new message is created or obtained since that is the only time that 105 * applications are allowed to modify the contents of the message. 106 * 107 * It is an error to attempt to enqueue or recycle a message that is already in use. 108 */ 109 /*package*/ static final int FLAG_IN_USE = 1 << 0; 110 111 /** If set message is asynchronous */ 112 /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1; 113 114 /** Flags to clear in the copyFrom method */ 115 /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE; 116 117 @UnsupportedAppUsage 118 /*package*/ int flags; 119 120 /** 121 * The targeted delivery time of this message. The time-base is 122 * {@link SystemClock#uptimeMillis}. 123 * @hide Only for use within the tests. 124 */ 125 @UnsupportedAppUsage 126 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) 127 public long when; 128 129 /*package*/ Bundle data; 130 131 @UnsupportedAppUsage 132 /*package*/ Handler target; 133 134 @UnsupportedAppUsage 135 /*package*/ Runnable callback; 136 137 // sometimes we store linked lists of these things 138 @UnsupportedAppUsage 139 /*package*/ Message next; 140 141 142 /** @hide */ 143 public static final Object sPoolSync = new Object(); 144 private static Message sPool; 145 private static int sPoolSize = 0; 146 147 private static final int MAX_POOL_SIZE = 50; 148 149 private static boolean gCheckRecycle = true; 150 151 /** 152 * Return a new Message instance from the global pool. Allows us to 153 * avoid allocating new objects in many cases. 154 */ obtain()155 public static Message obtain() { 156 synchronized (sPoolSync) { 157 if (sPool != null) { 158 Message m = sPool; 159 sPool = m.next; 160 m.next = null; 161 m.flags = 0; // clear in-use flag 162 sPoolSize--; 163 return m; 164 } 165 } 166 return new Message(); 167 } 168 169 /** 170 * Same as {@link #obtain()}, but copies the values of an existing 171 * message (including its target) into the new one. 172 * @param orig Original message to copy. 173 * @return A Message object from the global pool. 174 */ obtain(Message orig)175 public static Message obtain(Message orig) { 176 Message m = obtain(); 177 m.what = orig.what; 178 m.arg1 = orig.arg1; 179 m.arg2 = orig.arg2; 180 m.obj = orig.obj; 181 m.replyTo = orig.replyTo; 182 m.sendingUid = orig.sendingUid; 183 m.workSourceUid = orig.workSourceUid; 184 if (orig.data != null) { 185 m.data = new Bundle(orig.data); 186 } 187 m.target = orig.target; 188 m.callback = orig.callback; 189 190 return m; 191 } 192 193 /** 194 * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned. 195 * @param h Handler to assign to the returned Message object's <em>target</em> member. 196 * @return A Message object from the global pool. 197 */ obtain(Handler h)198 public static Message obtain(Handler h) { 199 Message m = obtain(); 200 m.target = h; 201 202 return m; 203 } 204 205 /** 206 * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on 207 * the Message that is returned. 208 * @param h Handler to assign to the returned Message object's <em>target</em> member. 209 * @param callback Runnable that will execute when the message is handled. 210 * @return A Message object from the global pool. 211 */ obtain(Handler h, Runnable callback)212 public static Message obtain(Handler h, Runnable callback) { 213 Message m = obtain(); 214 m.target = h; 215 m.callback = callback; 216 217 return m; 218 } 219 220 /** 221 * Same as {@link #obtain()}, but sets the values for both <em>target</em> and 222 * <em>what</em> members on the Message. 223 * @param h Value to assign to the <em>target</em> member. 224 * @param what Value to assign to the <em>what</em> member. 225 * @return A Message object from the global pool. 226 */ obtain(Handler h, int what)227 public static Message obtain(Handler h, int what) { 228 Message m = obtain(); 229 m.target = h; 230 m.what = what; 231 232 return m; 233 } 234 235 /** 236 * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em> 237 * members. 238 * @param h The <em>target</em> value to set. 239 * @param what The <em>what</em> value to set. 240 * @param obj The <em>object</em> method to set. 241 * @return A Message object from the global pool. 242 */ obtain(Handler h, int what, Object obj)243 public static Message obtain(Handler h, int what, Object obj) { 244 Message m = obtain(); 245 m.target = h; 246 m.what = what; 247 m.obj = obj; 248 249 return m; 250 } 251 252 /** 253 * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, 254 * <em>arg1</em>, and <em>arg2</em> members. 255 * 256 * @param h The <em>target</em> value to set. 257 * @param what The <em>what</em> value to set. 258 * @param arg1 The <em>arg1</em> value to set. 259 * @param arg2 The <em>arg2</em> value to set. 260 * @return A Message object from the global pool. 261 */ obtain(Handler h, int what, int arg1, int arg2)262 public static Message obtain(Handler h, int what, int arg1, int arg2) { 263 Message m = obtain(); 264 m.target = h; 265 m.what = what; 266 m.arg1 = arg1; 267 m.arg2 = arg2; 268 269 return m; 270 } 271 272 /** 273 * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, 274 * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members. 275 * 276 * @param h The <em>target</em> value to set. 277 * @param what The <em>what</em> value to set. 278 * @param arg1 The <em>arg1</em> value to set. 279 * @param arg2 The <em>arg2</em> value to set. 280 * @param obj The <em>obj</em> value to set. 281 * @return A Message object from the global pool. 282 */ obtain(Handler h, int what, int arg1, int arg2, Object obj)283 public static Message obtain(Handler h, int what, 284 int arg1, int arg2, Object obj) { 285 Message m = obtain(); 286 m.target = h; 287 m.what = what; 288 m.arg1 = arg1; 289 m.arg2 = arg2; 290 m.obj = obj; 291 292 return m; 293 } 294 295 /** @hide */ updateCheckRecycle(int targetSdkVersion)296 public static void updateCheckRecycle(int targetSdkVersion) { 297 if (targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) { 298 gCheckRecycle = false; 299 } 300 } 301 302 /** 303 * Return a Message instance to the global pool. 304 * <p> 305 * You MUST NOT touch the Message after calling this function because it has 306 * effectively been freed. It is an error to recycle a message that is currently 307 * enqueued or that is in the process of being delivered to a Handler. 308 * </p> 309 */ recycle()310 public void recycle() { 311 if (isInUse()) { 312 if (gCheckRecycle) { 313 throw new IllegalStateException("This message cannot be recycled because it " 314 + "is still in use."); 315 } 316 return; 317 } 318 recycleUnchecked(); 319 } 320 321 /** 322 * Recycles a Message that may be in-use. 323 * Used internally by the MessageQueue and Looper when disposing of queued Messages. 324 */ 325 @UnsupportedAppUsage recycleUnchecked()326 void recycleUnchecked() { 327 // Mark the message as in use while it remains in the recycled object pool. 328 // Clear out all other details. 329 flags = FLAG_IN_USE; 330 what = 0; 331 arg1 = 0; 332 arg2 = 0; 333 obj = null; 334 replyTo = null; 335 sendingUid = UID_NONE; 336 workSourceUid = UID_NONE; 337 when = 0; 338 target = null; 339 callback = null; 340 data = null; 341 342 synchronized (sPoolSync) { 343 if (sPoolSize < MAX_POOL_SIZE) { 344 next = sPool; 345 sPool = this; 346 sPoolSize++; 347 } 348 } 349 } 350 351 /** 352 * Make this message like o. Performs a shallow copy of the data field. 353 * Does not copy the linked list fields, nor the timestamp or 354 * target/callback of the original message. 355 */ copyFrom(Message o)356 public void copyFrom(Message o) { 357 this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM; 358 this.what = o.what; 359 this.arg1 = o.arg1; 360 this.arg2 = o.arg2; 361 this.obj = o.obj; 362 this.replyTo = o.replyTo; 363 this.sendingUid = o.sendingUid; 364 this.workSourceUid = o.workSourceUid; 365 366 if (o.data != null) { 367 this.data = (Bundle) o.data.clone(); 368 } else { 369 this.data = null; 370 } 371 } 372 373 /** 374 * Return the targeted delivery time of this message, in milliseconds. 375 */ getWhen()376 public long getWhen() { 377 return when; 378 } 379 setTarget(Handler target)380 public void setTarget(Handler target) { 381 this.target = target; 382 } 383 384 /** 385 * Retrieve the {@link android.os.Handler Handler} implementation that 386 * will receive this message. The object must implement 387 * {@link android.os.Handler#handleMessage(android.os.Message) 388 * Handler.handleMessage()}. Each Handler has its own name-space for 389 * message codes, so you do not need to 390 * worry about yours conflicting with other handlers. 391 */ getTarget()392 public Handler getTarget() { 393 return target; 394 } 395 396 /** 397 * Retrieve callback object that will execute when this message is handled. 398 * This object must implement Runnable. This is called by 399 * the <em>target</em> {@link Handler} that is receiving this Message to 400 * dispatch it. If 401 * not set, the message will be dispatched to the receiving Handler's 402 * {@link Handler#handleMessage(Message)}. 403 */ getCallback()404 public Runnable getCallback() { 405 return callback; 406 } 407 408 /** @hide */ 409 @UnsupportedAppUsage setCallback(Runnable r)410 public Message setCallback(Runnable r) { 411 callback = r; 412 return this; 413 } 414 415 /** 416 * Obtains a Bundle of arbitrary data associated with this 417 * event, lazily creating it if necessary. Set this value by calling 418 * {@link #setData(Bundle)}. Note that when transferring data across 419 * processes via {@link Messenger}, you will need to set your ClassLoader 420 * on the Bundle via {@link Bundle#setClassLoader(ClassLoader) 421 * Bundle.setClassLoader()} so that it can instantiate your objects when 422 * you retrieve them. 423 * @see #peekData() 424 * @see #setData(Bundle) 425 */ getData()426 public Bundle getData() { 427 if (data == null) { 428 data = new Bundle(); 429 } 430 431 return data; 432 } 433 434 /** 435 * Like getData(), but does not lazily create the Bundle. A null 436 * is returned if the Bundle does not already exist. See 437 * {@link #getData} for further information on this. 438 * @see #getData() 439 * @see #setData(Bundle) 440 */ 441 @Nullable peekData()442 public Bundle peekData() { 443 return data; 444 } 445 446 /** 447 * Sets a Bundle of arbitrary data values. Use arg1 and arg2 members 448 * as a lower cost way to send a few simple integer values, if you can. 449 * @see #getData() 450 * @see #peekData() 451 */ setData(Bundle data)452 public void setData(Bundle data) { 453 this.data = data; 454 } 455 456 /** 457 * Chainable setter for {@link #what} 458 * 459 * @hide 460 */ setWhat(int what)461 public Message setWhat(int what) { 462 this.what = what; 463 return this; 464 } 465 466 /** 467 * Sends this Message to the Handler specified by {@link #getTarget}. 468 * Throws a null pointer exception if this field has not been set. 469 */ sendToTarget()470 public void sendToTarget() { 471 target.sendMessage(this); 472 } 473 474 /** 475 * Returns true if the message is asynchronous, meaning that it is not 476 * subject to {@link Looper} synchronization barriers. 477 * 478 * @return True if the message is asynchronous. 479 * 480 * @see #setAsynchronous(boolean) 481 */ isAsynchronous()482 public boolean isAsynchronous() { 483 return (flags & FLAG_ASYNCHRONOUS) != 0; 484 } 485 486 /** 487 * Sets whether the message is asynchronous, meaning that it is not 488 * subject to {@link Looper} synchronization barriers. 489 * <p> 490 * Certain operations, such as view invalidation, may introduce synchronization 491 * barriers into the {@link Looper}'s message queue to prevent subsequent messages 492 * from being delivered until some condition is met. In the case of view invalidation, 493 * messages which are posted after a call to {@link android.view.View#invalidate} 494 * are suspended by means of a synchronization barrier until the next frame is 495 * ready to be drawn. The synchronization barrier ensures that the invalidation 496 * request is completely handled before resuming. 497 * </p><p> 498 * Asynchronous messages are exempt from synchronization barriers. They typically 499 * represent interrupts, input events, and other signals that must be handled independently 500 * even while other work has been suspended. 501 * </p><p> 502 * Note that asynchronous messages may be delivered out of order with respect to 503 * synchronous messages although they are always delivered in order among themselves. 504 * If the relative order of these messages matters then they probably should not be 505 * asynchronous in the first place. Use with caution. 506 * </p> 507 * 508 * @param async True if the message is asynchronous. 509 * 510 * @see #isAsynchronous() 511 */ setAsynchronous(boolean async)512 public void setAsynchronous(boolean async) { 513 if (async) { 514 flags |= FLAG_ASYNCHRONOUS; 515 } else { 516 flags &= ~FLAG_ASYNCHRONOUS; 517 } 518 } 519 isInUse()520 /*package*/ boolean isInUse() { 521 return ((flags & FLAG_IN_USE) == FLAG_IN_USE); 522 } 523 524 @UnsupportedAppUsage markInUse()525 /*package*/ void markInUse() { 526 flags |= FLAG_IN_USE; 527 } 528 529 /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}). 530 */ Message()531 public Message() { 532 } 533 534 @Override toString()535 public String toString() { 536 return toString(SystemClock.uptimeMillis()); 537 } 538 539 @UnsupportedAppUsage toString(long now)540 String toString(long now) { 541 StringBuilder b = new StringBuilder(); 542 b.append("{ when="); 543 TimeUtils.formatDuration(when - now, b); 544 545 if (target != null) { 546 if (callback != null) { 547 b.append(" callback="); 548 b.append(callback.getClass().getName()); 549 } else { 550 b.append(" what="); 551 b.append(what); 552 } 553 554 if (arg1 != 0) { 555 b.append(" arg1="); 556 b.append(arg1); 557 } 558 559 if (arg2 != 0) { 560 b.append(" arg2="); 561 b.append(arg2); 562 } 563 564 if (obj != null) { 565 b.append(" obj="); 566 b.append(obj); 567 } 568 569 b.append(" target="); 570 b.append(target.getClass().getName()); 571 } else { 572 b.append(" barrier="); 573 b.append(arg1); 574 } 575 576 b.append(" }"); 577 return b.toString(); 578 } 579 dumpDebug(ProtoOutputStream proto, long fieldId)580 void dumpDebug(ProtoOutputStream proto, long fieldId) { 581 final long messageToken = proto.start(fieldId); 582 proto.write(MessageProto.WHEN, when); 583 584 if (target != null) { 585 if (callback != null) { 586 proto.write(MessageProto.CALLBACK, callback.getClass().getName()); 587 } else { 588 proto.write(MessageProto.WHAT, what); 589 } 590 591 if (arg1 != 0) { 592 proto.write(MessageProto.ARG1, arg1); 593 } 594 595 if (arg2 != 0) { 596 proto.write(MessageProto.ARG2, arg2); 597 } 598 599 if (obj != null) { 600 proto.write(MessageProto.OBJ, obj.toString()); 601 } 602 603 proto.write(MessageProto.TARGET, target.getClass().getName()); 604 } else { 605 proto.write(MessageProto.BARRIER, arg1); 606 } 607 608 proto.end(messageToken); 609 } 610 611 public static final @android.annotation.NonNull Parcelable.Creator<Message> CREATOR 612 = new Parcelable.Creator<Message>() { 613 public Message createFromParcel(Parcel source) { 614 Message msg = Message.obtain(); 615 msg.readFromParcel(source); 616 return msg; 617 } 618 619 public Message[] newArray(int size) { 620 return new Message[size]; 621 } 622 }; 623 describeContents()624 public int describeContents() { 625 return 0; 626 } 627 writeToParcel(Parcel dest, int flags)628 public void writeToParcel(Parcel dest, int flags) { 629 if (callback != null) { 630 throw new RuntimeException( 631 "Can't marshal callbacks across processes."); 632 } 633 dest.writeInt(what); 634 dest.writeInt(arg1); 635 dest.writeInt(arg2); 636 if (obj != null) { 637 try { 638 Parcelable p = (Parcelable)obj; 639 dest.writeInt(1); 640 dest.writeParcelable(p, flags); 641 } catch (ClassCastException e) { 642 throw new RuntimeException( 643 "Can't marshal non-Parcelable objects across processes."); 644 } 645 } else { 646 dest.writeInt(0); 647 } 648 dest.writeLong(when); 649 dest.writeBundle(data); 650 Messenger.writeMessengerOrNullToParcel(replyTo, dest); 651 dest.writeInt(sendingUid); 652 dest.writeInt(workSourceUid); 653 } 654 readFromParcel(Parcel source)655 private void readFromParcel(Parcel source) { 656 what = source.readInt(); 657 arg1 = source.readInt(); 658 arg2 = source.readInt(); 659 if (source.readInt() != 0) { 660 obj = source.readParcelable(getClass().getClassLoader(), java.lang.Object.class); 661 } 662 when = source.readLong(); 663 data = source.readBundle(); 664 replyTo = Messenger.readMessengerOrNullFromParcel(source); 665 sendingUid = source.readInt(); 666 workSourceUid = source.readInt(); 667 } 668 } 669