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