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