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