blob: 8c758470c83a252fcb3123b3b7d1646216cb0767 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070019import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020
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
Dianne Hackborn75288fa2010-02-16 18:01:18 -080041 /**
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 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046 public int arg1;
47
Dianne Hackborn75288fa2010-02-16 18:01:18 -080048 /**
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 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 public int arg2;
54
Dianne Hackborn75288fa2010-02-16 18:01:18 -080055 /**
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 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 public Object obj;
66
Dianne Hackborn75288fa2010-02-16 18:01:18 -080067 /**
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.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071 */
72 public Messenger replyTo;
Wink Savillea334e7c2010-08-24 10:56:30 -070073
Dianne Hackborncb3ed1d2014-06-27 18:37:06 -070074 /**
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
Jeff Brown9867ed72014-02-28 14:00:57 -080081 /** 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 */
Jeff Browne799cb72012-02-14 11:53:33 -080089 /*package*/ static final int FLAG_IN_USE = 1 << 0;
Wink Savillea334e7c2010-08-24 10:56:30 -070090
Jeff Browne799cb72012-02-14 11:53:33 -080091 /** If set message is asynchronous */
92 /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;
Wink Savillea334e7c2010-08-24 10:56:30 -070093
94 /** Flags to clear in the copyFrom method */
Jeff Browne799cb72012-02-14 11:53:33 -080095 /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
Wink Savillea334e7c2010-08-24 10:56:30 -070096
97 /*package*/ int flags;
98
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 /*package*/ long when;
100
101 /*package*/ Bundle data;
102
Jeff Brown9867ed72014-02-28 14:00:57 -0800103 /*package*/ Handler target;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104
Jeff Brown9867ed72014-02-28 14:00:57 -0800105 /*package*/ Runnable callback;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106
107 // sometimes we store linked lists of these things
108 /*package*/ Message next;
109
Brad Fitzpatrick2405c2782011-01-25 14:48:21 -0800110 private static final Object sPoolSync = new Object();
111 private static Message sPool;
112 private static int sPoolSize = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113
Romain Guya2ad6562012-05-06 16:10:34 -0700114 private static final int MAX_POOL_SIZE = 50;
115
Dianne Hackborn7895bc22014-09-05 15:09:03 -0700116 private static boolean gCheckRecycle = true;
117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 /**
119 * Return a new Message instance from the global pool. Allows us to
120 * avoid allocating new objects in many cases.
121 */
122 public static Message obtain() {
Brad Fitzpatrick2405c2782011-01-25 14:48:21 -0800123 synchronized (sPoolSync) {
124 if (sPool != null) {
125 Message m = sPool;
126 sPool = m.next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 m.next = null;
Jeff Brown9867ed72014-02-28 14:00:57 -0800128 m.flags = 0; // clear in-use flag
Brad Fitzpatrick2405c2782011-01-25 14:48:21 -0800129 sPoolSize--;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 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 */
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;
Dianne Hackborncb3ed1d2014-06-27 18:37:06 -0700149 m.sendingUid = orig.sendingUid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 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 */
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 */
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 */
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 */
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 */
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 */
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
Dianne Hackborn7895bc22014-09-05 15:09:03 -0700261 /** @hide */
262 public static void updateCheckRecycle(int targetSdkVersion) {
Dianne Hackborn955d8d62014-10-07 20:17:19 -0700263 if (targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) {
Dianne Hackborn7895bc22014-09-05 15:09:03 -0700264 gCheckRecycle = false;
265 }
266 }
267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 /**
Jeff Brown9867ed72014-02-28 14:00:57 -0800269 * 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>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 */
276 public void recycle() {
Jeff Brown9867ed72014-02-28 14:00:57 -0800277 if (isInUse()) {
Dianne Hackborn7895bc22014-09-05 15:09:03 -0700278 if (gCheckRecycle) {
279 throw new IllegalStateException("This message cannot be recycled because it "
280 + "is still in use.");
281 }
282 return;
Jeff Brown9867ed72014-02-28 14:00:57 -0800283 }
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 */
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;
Dianne Hackborncb3ed1d2014-06-27 18:37:06 -0700300 sendingUid = -1;
Jeff Brown9867ed72014-02-28 14:00:57 -0800301 when = 0;
302 target = null;
303 callback = null;
304 data = null;
Jeff Brownfc9ff4c2011-06-10 17:56:08 -0700305
Brad Fitzpatrick2405c2782011-01-25 14:48:21 -0800306 synchronized (sPoolSync) {
307 if (sPoolSize < MAX_POOL_SIZE) {
Brad Fitzpatrick2405c2782011-01-25 14:48:21 -0800308 next = sPool;
309 sPool = this;
310 sPoolSize++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 }
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 */
320 public void copyFrom(Message o) {
Wink Savillea334e7c2010-08-24 10:56:30 -0700321 this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 this.what = o.what;
323 this.arg1 = o.arg1;
324 this.arg2 = o.arg2;
325 this.obj = o.obj;
326 this.replyTo = o.replyTo;
Dianne Hackborncb3ed1d2014-06-27 18:37:06 -0700327 this.sendingUid = o.sendingUid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328
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 */
339 public long getWhen() {
340 return when;
341 }
342
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 */
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
Dianne Hackborn75288fa2010-02-16 18:01:18 -0800365 * {@link Handler#handleMessage(Message Handler.handleMessage())}.
366 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367 public Runnable getCallback() {
368 return callback;
369 }
370
371 /**
372 * Obtains a Bundle of arbitrary data associated with this
Dianne Hackborn75288fa2010-02-16 18:01:18 -0800373 * 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)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 */
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
Dianne Hackborn75288fa2010-02-16 18:01:18 -0800392 * 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)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 */
397 public Bundle peekData() {
398 return data;
399 }
400
Dianne Hackborn75288fa2010-02-16 18:01:18 -0800401 /**
Denver Coneybeared0eb5532014-06-18 15:45:14 -0400402 * Sets a Bundle of arbitrary data values. Use arg1 and arg2 members
Dianne Hackborn75288fa2010-02-16 18:01:18 -0800403 * as a lower cost way to send a few simple integer values, if you can.
404 * @see #getData()
405 * @see #peekData()
406 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 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 */
415 public void sendToTarget() {
416 target.sendMessage(this);
417 }
418
Jeff Browne799cb72012-02-14 11:53:33 -0800419 /**
Jeff Brown9840c072014-11-11 20:21:21 -0800420 * Returns true if the message is asynchronous, meaning that it is not
421 * subject to {@link Looper} synchronization barriers.
Jeff Browne799cb72012-02-14 11:53:33 -0800422 *
423 * @return True if the message is asynchronous.
424 *
425 * @see #setAsynchronous(boolean)
Jeff Browne799cb72012-02-14 11:53:33 -0800426 */
427 public boolean isAsynchronous() {
428 return (flags & FLAG_ASYNCHRONOUS) != 0;
429 }
430
431 /**
Jeff Brown9840c072014-11-11 20:21:21 -0800432 * Sets whether the message is asynchronous, meaning that it is not
433 * subject to {@link Looper} synchronization barriers.
434 * <p>
435 * Certain operations, such as view invalidation, may introduce synchronization
436 * barriers into the {@link Looper}'s message queue to prevent subsequent messages
437 * from being delivered until some condition is met. In the case of view invalidation,
438 * messages which are posted after a call to {@link android.view.View#invalidate}
439 * are suspended by means of a synchronization barrier until the next frame is
440 * ready to be drawn. The synchronization barrier ensures that the invalidation
441 * request is completely handled before resuming.
442 * </p><p>
443 * Asynchronous messages are exempt from synchronization barriers. They typically
444 * represent interrupts, input events, and other signals that must be handled independently
445 * even while other work has been suspended.
446 * </p><p>
447 * Note that asynchronous messages may be delivered out of order with respect to
448 * synchronous messages although they are always delivered in order among themselves.
449 * If the relative order of these messages matters then they probably should not be
450 * asynchronous in the first place. Use with caution.
451 * </p>
Jeff Browne799cb72012-02-14 11:53:33 -0800452 *
453 * @param async True if the message is asynchronous.
454 *
455 * @see #isAsynchronous()
Jeff Browne799cb72012-02-14 11:53:33 -0800456 */
457 public void setAsynchronous(boolean async) {
458 if (async) {
459 flags |= FLAG_ASYNCHRONOUS;
460 } else {
461 flags &= ~FLAG_ASYNCHRONOUS;
462 }
463 }
464
Wink Savillea334e7c2010-08-24 10:56:30 -0700465 /*package*/ boolean isInUse() {
466 return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
467 }
468
469 /*package*/ void markInUse() {
470 flags |= FLAG_IN_USE;
471 }
472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
474 */
475 public Message() {
476 }
477
Jeff Brown5182c782013-10-15 20:31:52 -0700478 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 public String toString() {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700480 return toString(SystemClock.uptimeMillis());
481 }
482
483 String toString(long now) {
Jeff Brown5182c782013-10-15 20:31:52 -0700484 StringBuilder b = new StringBuilder();
485 b.append("{ when=");
486 TimeUtils.formatDuration(when - now, b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487
Jeff Brown5182c782013-10-15 20:31:52 -0700488 if (target != null) {
489 if (callback != null) {
490 b.append(" callback=");
491 b.append(callback.getClass().getName());
492 } else {
493 b.append(" what=");
494 b.append(what);
495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496
Jeff Brown5182c782013-10-15 20:31:52 -0700497 if (arg1 != 0) {
498 b.append(" arg1=");
499 b.append(arg1);
500 }
501
502 if (arg2 != 0) {
503 b.append(" arg2=");
504 b.append(arg2);
505 }
506
507 if (obj != null) {
508 b.append(" obj=");
509 b.append(obj);
510 }
511
512 b.append(" target=");
513 b.append(target.getClass().getName());
514 } else {
515 b.append(" barrier=");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516 b.append(arg1);
517 }
518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 b.append(" }");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 return b.toString();
521 }
522
523 public static final Parcelable.Creator<Message> CREATOR
524 = new Parcelable.Creator<Message>() {
525 public Message createFromParcel(Parcel source) {
526 Message msg = Message.obtain();
527 msg.readFromParcel(source);
528 return msg;
529 }
530
531 public Message[] newArray(int size) {
532 return new Message[size];
533 }
534 };
535
536 public int describeContents() {
537 return 0;
538 }
539
540 public void writeToParcel(Parcel dest, int flags) {
Dianne Hackborn75288fa2010-02-16 18:01:18 -0800541 if (callback != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 throw new RuntimeException(
Dianne Hackborn75288fa2010-02-16 18:01:18 -0800543 "Can't marshal callbacks across processes.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800544 }
545 dest.writeInt(what);
546 dest.writeInt(arg1);
547 dest.writeInt(arg2);
Dianne Hackborn75288fa2010-02-16 18:01:18 -0800548 if (obj != null) {
549 try {
550 Parcelable p = (Parcelable)obj;
551 dest.writeInt(1);
552 dest.writeParcelable(p, flags);
553 } catch (ClassCastException e) {
554 throw new RuntimeException(
555 "Can't marshal non-Parcelable objects across processes.");
556 }
557 } else {
558 dest.writeInt(0);
559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 dest.writeLong(when);
561 dest.writeBundle(data);
562 Messenger.writeMessengerOrNullToParcel(replyTo, dest);
Dianne Hackborncb3ed1d2014-06-27 18:37:06 -0700563 dest.writeInt(sendingUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 }
565
Romain Guy8f3b8e32012-03-27 16:33:45 -0700566 private void readFromParcel(Parcel source) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 what = source.readInt();
568 arg1 = source.readInt();
569 arg2 = source.readInt();
Dianne Hackborn75288fa2010-02-16 18:01:18 -0800570 if (source.readInt() != 0) {
571 obj = source.readParcelable(getClass().getClassLoader());
572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 when = source.readLong();
574 data = source.readBundle();
575 replyTo = Messenger.readMessengerOrNullFromParcel(source);
Dianne Hackborncb3ed1d2014-06-27 18:37:06 -0700576 sendingUid = source.readInt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 }
578}