• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     /**
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 
81     /** 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      */
89     /*package*/ static final int FLAG_IN_USE = 1 << 0;
90 
91     /** If set message is asynchronous */
92     /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;
93 
94     /** Flags to clear in the copyFrom method */
95     /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
96 
97     /*package*/ int flags;
98 
99     /*package*/ long when;
100 
101     /*package*/ Bundle data;
102 
103     /*package*/ Handler target;
104 
105     /*package*/ Runnable callback;
106 
107     // sometimes we store linked lists of these things
108     /*package*/ Message next;
109 
110     private static final Object sPoolSync = new Object();
111     private static Message sPool;
112     private static int sPoolSize = 0;
113 
114     private static final int MAX_POOL_SIZE = 50;
115 
116     private static boolean gCheckRecycle = true;
117 
118     /**
119      * Return a new Message instance from the global pool. Allows us to
120      * avoid allocating new objects in many cases.
121      */
obtain()122     public static Message obtain() {
123         synchronized (sPoolSync) {
124             if (sPool != null) {
125                 Message m = sPool;
126                 sPool = m.next;
127                 m.next = null;
128                 m.flags = 0; // clear in-use flag
129                 sPoolSize--;
130                 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      */
obtain(Message orig)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;
149         m.sendingUid = orig.sendingUid;
150         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      */
obtain(Handler h)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      */
obtain(Handler h, Runnable callback)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      */
obtain(Handler h, int what)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      */
obtain(Handler h, int what, Object obj)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      */
obtain(Handler h, int what, int arg1, int arg2)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      */
obtain(Handler h, int what, int arg1, int arg2, Object obj)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 
261     /** @hide */
updateCheckRecycle(int targetSdkVersion)262     public static void updateCheckRecycle(int targetSdkVersion) {
263         if (targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) {
264             gCheckRecycle = false;
265         }
266     }
267 
268     /**
269      * 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>
275      */
recycle()276     public void recycle() {
277         if (isInUse()) {
278             if (gCheckRecycle) {
279                 throw new IllegalStateException("This message cannot be recycled because it "
280                         + "is still in use.");
281             }
282             return;
283         }
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      */
recycleUnchecked()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;
300         sendingUid = -1;
301         when = 0;
302         target = null;
303         callback = null;
304         data = null;
305 
306         synchronized (sPoolSync) {
307             if (sPoolSize < MAX_POOL_SIZE) {
308                 next = sPool;
309                 sPool = this;
310                 sPoolSize++;
311             }
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      */
copyFrom(Message o)320     public void copyFrom(Message o) {
321         this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM;
322         this.what = o.what;
323         this.arg1 = o.arg1;
324         this.arg2 = o.arg2;
325         this.obj = o.obj;
326         this.replyTo = o.replyTo;
327         this.sendingUid = o.sendingUid;
328 
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      */
getWhen()339     public long getWhen() {
340         return when;
341     }
342 
setTarget(Handler target)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      */
getTarget()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
365      * {@link Handler#handleMessage(Message Handler.handleMessage())}.
366      */
getCallback()367     public Runnable getCallback() {
368         return callback;
369     }
370 
371     /**
372      * Obtains a Bundle of arbitrary data associated with this
373      * 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)
381      */
getData()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
392      * 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)
396      */
peekData()397     public Bundle peekData() {
398         return data;
399     }
400 
401     /**
402      * Sets a Bundle of arbitrary data values. Use arg1 and arg2 members
403      * as a lower cost way to send a few simple integer values, if you can.
404      * @see #getData()
405      * @see #peekData()
406      */
setData(Bundle data)407     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      */
sendToTarget()415     public void sendToTarget() {
416         target.sendMessage(this);
417     }
418 
419     /**
420      * Returns true if the message is asynchronous, meaning that it is not
421      * subject to {@link Looper} synchronization barriers.
422      *
423      * @return True if the message is asynchronous.
424      *
425      * @see #setAsynchronous(boolean)
426      */
isAsynchronous()427     public boolean isAsynchronous() {
428         return (flags & FLAG_ASYNCHRONOUS) != 0;
429     }
430 
431     /**
432      * 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>
452      *
453      * @param async True if the message is asynchronous.
454      *
455      * @see #isAsynchronous()
456      */
setAsynchronous(boolean async)457     public void setAsynchronous(boolean async) {
458         if (async) {
459             flags |= FLAG_ASYNCHRONOUS;
460         } else {
461             flags &= ~FLAG_ASYNCHRONOUS;
462         }
463     }
464 
isInUse()465     /*package*/ boolean isInUse() {
466         return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
467     }
468 
markInUse()469     /*package*/ void markInUse() {
470         flags |= FLAG_IN_USE;
471     }
472 
473     /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
474     */
Message()475     public Message() {
476     }
477 
478     @Override
toString()479     public String toString() {
480         return toString(SystemClock.uptimeMillis());
481     }
482 
toString(long now)483     String toString(long now) {
484         StringBuilder b = new StringBuilder();
485         b.append("{ when=");
486         TimeUtils.formatDuration(when - now, b);
487 
488         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             }
496 
497             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=");
516             b.append(arg1);
517         }
518 
519         b.append(" }");
520         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 
describeContents()536     public int describeContents() {
537         return 0;
538     }
539 
writeToParcel(Parcel dest, int flags)540     public void writeToParcel(Parcel dest, int flags) {
541         if (callback != null) {
542             throw new RuntimeException(
543                 "Can't marshal callbacks across processes.");
544         }
545         dest.writeInt(what);
546         dest.writeInt(arg1);
547         dest.writeInt(arg2);
548         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         }
560         dest.writeLong(when);
561         dest.writeBundle(data);
562         Messenger.writeMessengerOrNullToParcel(replyTo, dest);
563         dest.writeInt(sendingUid);
564     }
565 
readFromParcel(Parcel source)566     private void readFromParcel(Parcel source) {
567         what = source.readInt();
568         arg1 = source.readInt();
569         arg2 = source.readInt();
570         if (source.readInt() != 0) {
571             obj = source.readParcelable(getClass().getClassLoader());
572         }
573         when = source.readLong();
574         data = source.readBundle();
575         replyTo = Messenger.readMessengerOrNullFromParcel(source);
576         sendingUid = source.readInt();
577     }
578 }
579