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