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