Message.java revision 47864180918702768d26f48ec3213c935cea0c4b
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    /** 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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
251    public void recycle() {
252        synchronized (sPoolSync) {
253            if (sPoolSize < MAX_POOL_SIZE) {
254                clearForRecycle();
255                next = sPool;
256                sPool = this;
257                sPoolSize++;
258            }
259        }
260    }
261
262    /**
263     * Make this message like o.  Performs a shallow copy of the data field.
264     * Does not copy the linked list fields, nor the timestamp or
265     * target/callback of the original message.
266     */
267    public void copyFrom(Message o) {
268        this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM;
269        this.what = o.what;
270        this.arg1 = o.arg1;
271        this.arg2 = o.arg2;
272        this.obj = o.obj;
273        this.replyTo = o.replyTo;
274
275        if (o.data != null) {
276            this.data = (Bundle) o.data.clone();
277        } else {
278            this.data = null;
279        }
280    }
281
282    /**
283     * Return the targeted delivery time of this message, in milliseconds.
284     */
285    public long getWhen() {
286        return when;
287    }
288
289    public void setTarget(Handler target) {
290        this.target = target;
291    }
292
293    /**
294     * Retrieve the a {@link android.os.Handler Handler} implementation that
295     * will receive this message. The object must implement
296     * {@link android.os.Handler#handleMessage(android.os.Message)
297     * Handler.handleMessage()}. Each Handler has its own name-space for
298     * message codes, so you do not need to
299     * worry about yours conflicting with other handlers.
300     */
301    public Handler getTarget() {
302        return target;
303    }
304
305    /**
306     * Retrieve callback object that will execute when this message is handled.
307     * This object must implement Runnable. This is called by
308     * the <em>target</em> {@link Handler} that is receiving this Message to
309     * dispatch it.  If
310     * not set, the message will be dispatched to the receiving Handler's
311     * {@link Handler#handleMessage(Message Handler.handleMessage())}.
312     */
313    public Runnable getCallback() {
314        return callback;
315    }
316
317    /**
318     * Obtains a Bundle of arbitrary data associated with this
319     * event, lazily creating it if necessary. Set this value by calling
320     * {@link #setData(Bundle)}.  Note that when transferring data across
321     * processes via {@link Messenger}, you will need to set your ClassLoader
322     * on the Bundle via {@link Bundle#setClassLoader(ClassLoader)
323     * Bundle.setClassLoader()} so that it can instantiate your objects when
324     * you retrieve them.
325     * @see #peekData()
326     * @see #setData(Bundle)
327     */
328    public Bundle getData() {
329        if (data == null) {
330            data = new Bundle();
331        }
332
333        return data;
334    }
335
336    /**
337     * Like getData(), but does not lazily create the Bundle.  A null
338     * is returned if the Bundle does not already exist.  See
339     * {@link #getData} for further information on this.
340     * @see #getData()
341     * @see #setData(Bundle)
342     */
343    public Bundle peekData() {
344        return data;
345    }
346
347    /**
348     * Sets a Bundle of arbitrary data values. Use arg1 and arg1 members
349     * as a lower cost way to send a few simple integer values, if you can.
350     * @see #getData()
351     * @see #peekData()
352     */
353    public void setData(Bundle data) {
354        this.data = data;
355    }
356
357    /**
358     * Sends this Message to the Handler specified by {@link #getTarget}.
359     * Throws a null pointer exception if this field has not been set.
360     */
361    public void sendToTarget() {
362        target.sendMessage(this);
363    }
364
365    /*package*/ void clearForRecycle() {
366        flags = 0;
367        what = 0;
368        arg1 = 0;
369        arg2 = 0;
370        obj = null;
371        replyTo = null;
372        when = 0;
373        target = null;
374        callback = null;
375        data = null;
376    }
377
378    /*package*/ boolean isInUse() {
379        return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
380    }
381
382    /*package*/ void markInUse() {
383        flags |= FLAG_IN_USE;
384    }
385
386    /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
387    */
388    public Message() {
389    }
390
391    public String toString() {
392        return toString(SystemClock.uptimeMillis());
393    }
394
395    String toString(long now) {
396        StringBuilder   b = new StringBuilder();
397
398        b.append("{ what=");
399        b.append(what);
400
401        b.append(" when=");
402        TimeUtils.formatDuration(when-now, b);
403
404        if (arg1 != 0) {
405            b.append(" arg1=");
406            b.append(arg1);
407        }
408
409        if (arg2 != 0) {
410            b.append(" arg2=");
411            b.append(arg2);
412        }
413
414        if (obj != null) {
415            b.append(" obj=");
416            b.append(obj);
417        }
418
419        b.append(" }");
420
421        return b.toString();
422    }
423
424    public static final Parcelable.Creator<Message> CREATOR
425            = new Parcelable.Creator<Message>() {
426        public Message createFromParcel(Parcel source) {
427            Message msg = Message.obtain();
428            msg.readFromParcel(source);
429            return msg;
430        }
431
432        public Message[] newArray(int size) {
433            return new Message[size];
434        }
435    };
436
437    public int describeContents() {
438        return 0;
439    }
440
441    public void writeToParcel(Parcel dest, int flags) {
442        if (callback != null) {
443            throw new RuntimeException(
444                "Can't marshal callbacks across processes.");
445        }
446        dest.writeInt(what);
447        dest.writeInt(arg1);
448        dest.writeInt(arg2);
449        if (obj != null) {
450            try {
451                Parcelable p = (Parcelable)obj;
452                dest.writeInt(1);
453                dest.writeParcelable(p, flags);
454            } catch (ClassCastException e) {
455                throw new RuntimeException(
456                    "Can't marshal non-Parcelable objects across processes.");
457            }
458        } else {
459            dest.writeInt(0);
460        }
461        dest.writeLong(when);
462        dest.writeBundle(data);
463        Messenger.writeMessengerOrNullToParcel(replyTo, dest);
464    }
465
466    private final void readFromParcel(Parcel source) {
467        what = source.readInt();
468        arg1 = source.readInt();
469        arg2 = source.readInt();
470        if (source.readInt() != 0) {
471            obj = source.readParcelable(getClass().getClassLoader());
472        }
473        when = source.readLong();
474        data = source.readBundle();
475        replyTo = Messenger.readMessengerOrNullFromParcel(source);
476    }
477}
478