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