• 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.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