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