• 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     /** 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      */
obtain()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      */
obtain(Message orig)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      */
obtain(Handler h)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      */
obtain(Handler h, Runnable callback)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      */
obtain(Handler h, int what)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      */
obtain(Handler h, int what, Object obj)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      */
obtain(Handler h, int what, int arg1, int arg2)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      */
obtain(Handler h, int what, int arg1, int arg2, Object obj)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      */
recycle()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      */
copyFrom(Message o)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      */
getWhen()283     public long getWhen() {
284         return when;
285     }
286 
setTarget(Handler target)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      */
getTarget()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      */
getCallback()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      */
getData()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      */
peekData()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      */
setData(Bundle data)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      */
sendToTarget()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      */
isAsynchronous()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      */
setAsynchronous(boolean async)397     public void setAsynchronous(boolean async) {
398         if (async) {
399             flags |= FLAG_ASYNCHRONOUS;
400         } else {
401             flags &= ~FLAG_ASYNCHRONOUS;
402         }
403     }
404 
clearForRecycle()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 
isInUse()418     /*package*/ boolean isInUse() {
419         return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
420     }
421 
markInUse()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     */
Message()428     public Message() {
429     }
430 
431     @Override
toString()432     public String toString() {
433         return toString(SystemClock.uptimeMillis());
434     }
435 
toString(long now)436     String toString(long now) {
437         StringBuilder b = new StringBuilder();
438         b.append("{ when=");
439         TimeUtils.formatDuration(when - now, b);
440 
441         if (target != null) {
442             if (callback != null) {
443                 b.append(" callback=");
444                 b.append(callback.getClass().getName());
445             } else {
446                 b.append(" what=");
447                 b.append(what);
448             }
449 
450             if (arg1 != 0) {
451                 b.append(" arg1=");
452                 b.append(arg1);
453             }
454 
455             if (arg2 != 0) {
456                 b.append(" arg2=");
457                 b.append(arg2);
458             }
459 
460             if (obj != null) {
461                 b.append(" obj=");
462                 b.append(obj);
463             }
464 
465             b.append(" target=");
466             b.append(target.getClass().getName());
467         } else {
468             b.append(" barrier=");
469             b.append(arg1);
470         }
471 
472         b.append(" }");
473         return b.toString();
474     }
475 
476     public static final Parcelable.Creator<Message> CREATOR
477             = new Parcelable.Creator<Message>() {
478         public Message createFromParcel(Parcel source) {
479             Message msg = Message.obtain();
480             msg.readFromParcel(source);
481             return msg;
482         }
483 
484         public Message[] newArray(int size) {
485             return new Message[size];
486         }
487     };
488 
describeContents()489     public int describeContents() {
490         return 0;
491     }
492 
writeToParcel(Parcel dest, int flags)493     public void writeToParcel(Parcel dest, int flags) {
494         if (callback != null) {
495             throw new RuntimeException(
496                 "Can't marshal callbacks across processes.");
497         }
498         dest.writeInt(what);
499         dest.writeInt(arg1);
500         dest.writeInt(arg2);
501         if (obj != null) {
502             try {
503                 Parcelable p = (Parcelable)obj;
504                 dest.writeInt(1);
505                 dest.writeParcelable(p, flags);
506             } catch (ClassCastException e) {
507                 throw new RuntimeException(
508                     "Can't marshal non-Parcelable objects across processes.");
509             }
510         } else {
511             dest.writeInt(0);
512         }
513         dest.writeLong(when);
514         dest.writeBundle(data);
515         Messenger.writeMessengerOrNullToParcel(replyTo, dest);
516     }
517 
readFromParcel(Parcel source)518     private void readFromParcel(Parcel source) {
519         what = source.readInt();
520         arg1 = source.readInt();
521         arg2 = source.readInt();
522         if (source.readInt() != 0) {
523             obj = source.readParcelable(getClass().getClassLoader());
524         }
525         when = source.readLong();
526         data = source.readBundle();
527         replyTo = Messenger.readMessengerOrNullFromParcel(source);
528     }
529 }
530