• 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 
23 /**
24  *
25  * Defines a message containing a description and arbitrary data object that can be
26  * sent to a {@link Handler}.  This object contains two extra int fields and an
27  * extra object field that allow you to not do allocations in many cases.
28  *
29  * <p class="note">While the constructor of Message is public, the best way to get
30  * one of these is to call {@link #obtain Message.obtain()} or one of the
31  * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull
32  * them from a pool of recycled objects.</p>
33  */
34 public final class Message implements Parcelable {
35     /**
36      * User-defined message code so that the recipient can identify
37      * what this message is about. Each {@link Handler} has its own name-space
38      * for message codes, so you do not need to worry about yours conflicting
39      * with other handlers.
40      */
41     public int what;
42 
43     // Use these fields instead of using the class's Bundle if you can.
44     /** arg1 and arg2 are lower-cost alternatives to using {@link #setData(Bundle) setData()}
45     if you only need to store a few integer values. */
46     public int arg1;
47 
48     /** arg1 and arg2 are lower-cost alternatives to using {@link #setData(Bundle) setData()}
49     if you only need to store a few integer values.*/
50     public int arg2;
51 
52     /** An arbitrary object to send to the recipient.  This must be null when
53      * sending messages across processes. */
54     public Object obj;
55 
56     /** Optional Messenger where replies to this message can be sent.
57      */
58     public Messenger replyTo;
59 
60     /*package*/ long when;
61 
62     /*package*/ Bundle data;
63 
64     /*package*/ Handler target;
65 
66     /*package*/ Runnable callback;
67 
68     // sometimes we store linked lists of these things
69     /*package*/ Message next;
70 
71     private static Object mPoolSync = new Object();
72     private static Message mPool;
73     private static int mPoolSize = 0;
74 
75     private static final int MAX_POOL_SIZE = 10;
76 
77     /**
78      * Return a new Message instance from the global pool. Allows us to
79      * avoid allocating new objects in many cases.
80      */
obtain()81     public static Message obtain() {
82         synchronized (mPoolSync) {
83             if (mPool != null) {
84                 Message m = mPool;
85                 mPool = m.next;
86                 m.next = null;
87                 return m;
88             }
89         }
90         return new Message();
91     }
92 
93     /**
94      * Same as {@link #obtain()}, but copies the values of an existing
95      * message (including its target) into the new one.
96      * @param orig Original message to copy.
97      * @return A Message object from the global pool.
98      */
obtain(Message orig)99     public static Message obtain(Message orig) {
100         Message m = obtain();
101         m.what = orig.what;
102         m.arg1 = orig.arg1;
103         m.arg2 = orig.arg2;
104         m.obj = orig.obj;
105         m.replyTo = orig.replyTo;
106         if (orig.data != null) {
107             m.data = new Bundle(orig.data);
108         }
109         m.target = orig.target;
110         m.callback = orig.callback;
111 
112         return m;
113     }
114 
115     /**
116      * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.
117      * @param h  Handler to assign to the returned Message object's <em>target</em> member.
118      * @return A Message object from the global pool.
119      */
obtain(Handler h)120     public static Message obtain(Handler h) {
121         Message m = obtain();
122         m.target = h;
123 
124         return m;
125     }
126 
127     /**
128      * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on
129      * the Message that is returned.
130      * @param h  Handler to assign to the returned Message object's <em>target</em> member.
131      * @param callback Runnable that will execute when the message is handled.
132      * @return A Message object from the global pool.
133      */
obtain(Handler h, Runnable callback)134     public static Message obtain(Handler h, Runnable callback) {
135         Message m = obtain();
136         m.target = h;
137         m.callback = callback;
138 
139         return m;
140     }
141 
142     /**
143      * Same as {@link #obtain()}, but sets the values for both <em>target</em> and
144      * <em>what</em> members on the Message.
145      * @param h  Value to assign to the <em>target</em> member.
146      * @param what  Value to assign to the <em>what</em> member.
147      * @return A Message object from the global pool.
148      */
obtain(Handler h, int what)149     public static Message obtain(Handler h, int what) {
150         Message m = obtain();
151         m.target = h;
152         m.what = what;
153 
154         return m;
155     }
156 
157     /**
158      * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em>
159      * members.
160      * @param h  The <em>target</em> value to set.
161      * @param what  The <em>what</em> value to set.
162      * @param obj  The <em>object</em> method to set.
163      * @return  A Message object from the global pool.
164      */
obtain(Handler h, int what, Object obj)165     public static Message obtain(Handler h, int what, Object obj) {
166         Message m = obtain();
167         m.target = h;
168         m.what = what;
169         m.obj = obj;
170 
171         return m;
172     }
173 
174     /**
175      * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
176      * <em>arg1</em>, and <em>arg2</em> members.
177      *
178      * @param h  The <em>target</em> value to set.
179      * @param what  The <em>what</em> value to set.
180      * @param arg1  The <em>arg1</em> value to set.
181      * @param arg2  The <em>arg2</em> value to set.
182      * @return  A Message object from the global pool.
183      */
obtain(Handler h, int what, int arg1, int arg2)184     public static Message obtain(Handler h, int what, int arg1, int arg2) {
185         Message m = obtain();
186         m.target = h;
187         m.what = what;
188         m.arg1 = arg1;
189         m.arg2 = arg2;
190 
191         return m;
192     }
193 
194     /**
195      * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
196      * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members.
197      *
198      * @param h  The <em>target</em> value to set.
199      * @param what  The <em>what</em> value to set.
200      * @param arg1  The <em>arg1</em> value to set.
201      * @param arg2  The <em>arg2</em> value to set.
202      * @param obj  The <em>obj</em> value to set.
203      * @return  A Message object from the global pool.
204      */
obtain(Handler h, int what, int arg1, int arg2, Object obj)205     public static Message obtain(Handler h, int what,
206             int arg1, int arg2, Object obj) {
207         Message m = obtain();
208         m.target = h;
209         m.what = what;
210         m.arg1 = arg1;
211         m.arg2 = arg2;
212         m.obj = obj;
213 
214         return m;
215     }
216 
217     /**
218      * Return a Message instance to the global pool.  You MUST NOT touch
219      * the Message after calling this function -- it has effectively been
220      * freed.
221      */
recycle()222     public void recycle() {
223         synchronized (mPoolSync) {
224             if (mPoolSize < MAX_POOL_SIZE) {
225                 clearForRecycle();
226 
227                 next = mPool;
228                 mPool = this;
229             }
230         }
231     }
232 
233     /**
234      * Make this message like o.  Performs a shallow copy of the data field.
235      * Does not copy the linked list fields, nor the timestamp or
236      * target/callback of the original message.
237      */
copyFrom(Message o)238     public void copyFrom(Message o) {
239         this.what = o.what;
240         this.arg1 = o.arg1;
241         this.arg2 = o.arg2;
242         this.obj = o.obj;
243         this.replyTo = o.replyTo;
244 
245         if (o.data != null) {
246             this.data = (Bundle) o.data.clone();
247         } else {
248             this.data = null;
249         }
250     }
251 
252     /**
253      * Return the targeted delivery time of this message, in milliseconds.
254      */
getWhen()255     public long getWhen() {
256         return when;
257     }
258 
setTarget(Handler target)259     public void setTarget(Handler target) {
260         this.target = target;
261     }
262 
263     /**
264      * Retrieve the a {@link android.os.Handler Handler} implementation that
265      * will receive this message. The object must implement
266      * {@link android.os.Handler#handleMessage(android.os.Message)
267      * Handler.handleMessage()}. Each Handler has its own name-space for
268      * message codes, so you do not need to
269      * worry about yours conflicting with other handlers.
270      */
getTarget()271     public Handler getTarget() {
272         return target;
273     }
274 
275     /**
276      * Retrieve callback object that will execute when this message is handled.
277      * This object must implement Runnable. This is called by
278      * the <em>target</em> {@link Handler} that is receiving this Message to
279      * dispatch it.  If
280      * not set, the message will be dispatched to the receiving Handler's
281      * {@link Handler#handleMessage(Message Handler.handleMessage())}. */
getCallback()282     public Runnable getCallback() {
283         return callback;
284     }
285 
286     /**
287      * Obtains a Bundle of arbitrary data associated with this
288      * event, lazily creating it if necessary. Set this value by calling {@link #setData(Bundle)}.
289      */
getData()290     public Bundle getData() {
291         if (data == null) {
292             data = new Bundle();
293         }
294 
295         return data;
296     }
297 
298     /**
299      * Like getData(), but does not lazily create the Bundle.  A null
300      * is returned if the Bundle does not already exist.
301      */
peekData()302     public Bundle peekData() {
303         return data;
304     }
305 
306     /** Sets a Bundle of arbitrary data values. Use arg1 and arg1 members
307      * as a lower cost way to send a few simple integer values, if you can. */
setData(Bundle data)308     public void setData(Bundle data) {
309         this.data = data;
310     }
311 
312     /**
313      * Sends this Message to the Handler specified by {@link #getTarget}.
314      * Throws a null pointer exception if this field has not been set.
315      */
sendToTarget()316     public void sendToTarget() {
317         target.sendMessage(this);
318     }
319 
clearForRecycle()320     /*package*/ void clearForRecycle() {
321         what = 0;
322         arg1 = 0;
323         arg2 = 0;
324         obj = null;
325         replyTo = null;
326         when = 0;
327         target = null;
328         callback = null;
329         data = null;
330     }
331 
332     /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
333     */
Message()334     public Message() {
335     }
336 
toString()337     public String toString() {
338         StringBuilder   b = new StringBuilder();
339 
340         b.append("{ what=");
341         b.append(what);
342 
343         b.append(" when=");
344         b.append(when);
345 
346         if (arg1 != 0) {
347             b.append(" arg1=");
348             b.append(arg1);
349         }
350 
351         if (arg2 != 0) {
352             b.append(" arg2=");
353             b.append(arg2);
354         }
355 
356         if (obj != null) {
357             b.append(" obj=");
358             b.append(obj);
359         }
360 
361         b.append(" }");
362 
363         return b.toString();
364     }
365 
366     public static final Parcelable.Creator<Message> CREATOR
367             = new Parcelable.Creator<Message>() {
368         public Message createFromParcel(Parcel source) {
369             Message msg = Message.obtain();
370             msg.readFromParcel(source);
371             return msg;
372         }
373 
374         public Message[] newArray(int size) {
375             return new Message[size];
376         }
377     };
378 
describeContents()379     public int describeContents() {
380         return 0;
381     }
382 
writeToParcel(Parcel dest, int flags)383     public void writeToParcel(Parcel dest, int flags) {
384         if (obj != null || callback != null) {
385             throw new RuntimeException(
386                 "Can't marshal objects across processes.");
387         }
388         dest.writeInt(what);
389         dest.writeInt(arg1);
390         dest.writeInt(arg2);
391         dest.writeLong(when);
392         dest.writeBundle(data);
393         Messenger.writeMessengerOrNullToParcel(replyTo, dest);
394     }
395 
readFromParcel(Parcel source)396     private final void readFromParcel(Parcel source) {
397         what = source.readInt();
398         arg1 = source.readInt();
399         arg2 = source.readInt();
400         when = source.readLong();
401         data = source.readBundle();
402         replyTo = Messenger.readMessengerOrNullFromParcel(source);
403     }
404 }
405 
406