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