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