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.util.TimeUtils;
20
21/**
22 *
23 * Defines a message containing a description and arbitrary data object that can be
24 * sent to a {@link Handler}.  This object contains two extra int fields and an
25 * extra object field that allow you to not do allocations in many cases.
26 *
27 * <p class="note">While the constructor of Message is public, the best way to get
28 * one of these is to call {@link #obtain Message.obtain()} or one of the
29 * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull
30 * them from a pool of recycled objects.</p>
31 */
32public final class Message implements Parcelable {
33    /**
34     * User-defined message code so that the recipient can identify
35     * what this message is about. Each {@link Handler} has its own name-space
36     * for message codes, so you do not need to worry about yours conflicting
37     * with other handlers.
38     */
39    public int what;
40
41    /**
42     * arg1 and arg2 are lower-cost alternatives to using
43     * {@link #setData(Bundle) setData()} if you only need to store a
44     * few integer values.
45     */
46    public int arg1;
47
48    /**
49     * arg1 and arg2 are lower-cost alternatives to using
50     * {@link #setData(Bundle) setData()} if you only need to store a
51     * few integer values.
52     */
53    public int arg2;
54
55    /**
56     * An arbitrary object to send to the recipient.  When using
57     * {@link Messenger} to send the message across processes this can only
58     * be non-null if it contains a Parcelable of a framework class (not one
59     * implemented by the application).   For other data transfer use
60     * {@link #setData}.
61     *
62     * <p>Note that Parcelable objects here are not supported prior to
63     * the {@link android.os.Build.VERSION_CODES#FROYO} release.
64     */
65    public Object obj;
66
67    /**
68     * Optional Messenger where replies to this message can be sent.  The
69     * semantics of exactly how this is used are up to the sender and
70     * receiver.
71     */
72    public Messenger replyTo;
73
74    /** If set message is in use */
75    /*package*/ static final int FLAG_IN_USE = 1 << 0;
76
77    /** If set message is asynchronous */
78    /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;
79
80    /** Flags to clear in the copyFrom method */
81    /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
82
83    /*package*/ int flags;
84
85    /*package*/ long when;
86
87    /*package*/ Bundle data;
88
89    /*package*/ Handler target;
90
91    /*package*/ Runnable callback;
92
93    // sometimes we store linked lists of these things
94    /*package*/ Message next;
95
96    private static final Object sPoolSync = new Object();
97    private static Message sPool;
98    private static int sPoolSize = 0;
99
100    private static final int MAX_POOL_SIZE = 50;
101
102    /**
103     * Return a new Message instance from the global pool. Allows us to
104     * avoid allocating new objects in many cases.
105     */
106    public static Message obtain() {
107        synchronized (sPoolSync) {
108            if (sPool != null) {
109                Message m = sPool;
110                sPool = m.next;
111                m.next = null;
112                sPoolSize--;
113                return m;
114            }
115        }
116        return new Message();
117    }
118
119    /**
120     * Same as {@link #obtain()}, but copies the values of an existing
121     * message (including its target) into the new one.
122     * @param orig Original message to copy.
123     * @return A Message object from the global pool.
124     */
125    public static Message obtain(Message orig) {
126        Message m = obtain();
127        m.what = orig.what;
128        m.arg1 = orig.arg1;
129        m.arg2 = orig.arg2;
130        m.obj = orig.obj;
131        m.replyTo = orig.replyTo;
132        if (orig.data != null) {
133            m.data = new Bundle(orig.data);
134        }
135        m.target = orig.target;
136        m.callback = orig.callback;
137
138        return m;
139    }
140
141    /**
142     * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.
143     * @param h  Handler to assign to the returned Message object's <em>target</em> member.
144     * @return A Message object from the global pool.
145     */
146    public static Message obtain(Handler h) {
147        Message m = obtain();
148        m.target = h;
149
150        return m;
151    }
152
153    /**
154     * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on
155     * the Message that is returned.
156     * @param h  Handler to assign to the returned Message object's <em>target</em> member.
157     * @param callback Runnable that will execute when the message is handled.
158     * @return A Message object from the global pool.
159     */
160    public static Message obtain(Handler h, Runnable callback) {
161        Message m = obtain();
162        m.target = h;
163        m.callback = callback;
164
165        return m;
166    }
167
168    /**
169     * Same as {@link #obtain()}, but sets the values for both <em>target</em> and
170     * <em>what</em> members on the Message.
171     * @param h  Value to assign to the <em>target</em> member.
172     * @param what  Value to assign to the <em>what</em> member.
173     * @return A Message object from the global pool.
174     */
175    public static Message obtain(Handler h, int what) {
176        Message m = obtain();
177        m.target = h;
178        m.what = what;
179
180        return m;
181    }
182
183    /**
184     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em>
185     * members.
186     * @param h  The <em>target</em> value to set.
187     * @param what  The <em>what</em> value to set.
188     * @param obj  The <em>object</em> method to set.
189     * @return  A Message object from the global pool.
190     */
191    public static Message obtain(Handler h, int what, Object obj) {
192        Message m = obtain();
193        m.target = h;
194        m.what = what;
195        m.obj = obj;
196
197        return m;
198    }
199
200    /**
201     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
202     * <em>arg1</em>, and <em>arg2</em> members.
203     *
204     * @param h  The <em>target</em> value to set.
205     * @param what  The <em>what</em> value to set.
206     * @param arg1  The <em>arg1</em> value to set.
207     * @param arg2  The <em>arg2</em> value to set.
208     * @return  A Message object from the global pool.
209     */
210    public static Message obtain(Handler h, int what, int arg1, int arg2) {
211        Message m = obtain();
212        m.target = h;
213        m.what = what;
214        m.arg1 = arg1;
215        m.arg2 = arg2;
216
217        return m;
218    }
219
220    /**
221     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
222     * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members.
223     *
224     * @param h  The <em>target</em> value to set.
225     * @param what  The <em>what</em> value to set.
226     * @param arg1  The <em>arg1</em> value to set.
227     * @param arg2  The <em>arg2</em> value to set.
228     * @param obj  The <em>obj</em> value to set.
229     * @return  A Message object from the global pool.
230     */
231    public static Message obtain(Handler h, int what,
232            int arg1, int arg2, Object obj) {
233        Message m = obtain();
234        m.target = h;
235        m.what = what;
236        m.arg1 = arg1;
237        m.arg2 = arg2;
238        m.obj = obj;
239
240        return m;
241    }
242
243    /**
244     * Return a Message instance to the global pool.  You MUST NOT touch
245     * the Message after calling this function -- it has effectively been
246     * freed.
247     */
248    public void recycle() {
249        clearForRecycle();
250
251        synchronized (sPoolSync) {
252            if (sPoolSize < MAX_POOL_SIZE) {
253                next = sPool;
254                sPool = this;
255                sPoolSize++;
256            }
257        }
258    }
259
260    /**
261     * Make this message like o.  Performs a shallow copy of the data field.
262     * Does not copy the linked list fields, nor the timestamp or
263     * target/callback of the original message.
264     */
265    public void copyFrom(Message o) {
266        this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM;
267        this.what = o.what;
268        this.arg1 = o.arg1;
269        this.arg2 = o.arg2;
270        this.obj = o.obj;
271        this.replyTo = o.replyTo;
272
273        if (o.data != null) {
274            this.data = (Bundle) o.data.clone();
275        } else {
276            this.data = null;
277        }
278    }
279
280    /**
281     * Return the targeted delivery time of this message, in milliseconds.
282     */
283    public long getWhen() {
284        return when;
285    }
286
287    public void setTarget(Handler target) {
288        this.target = target;
289    }
290
291    /**
292     * Retrieve the a {@link android.os.Handler Handler} implementation that
293     * will receive this message. The object must implement
294     * {@link android.os.Handler#handleMessage(android.os.Message)
295     * Handler.handleMessage()}. Each Handler has its own name-space for
296     * message codes, so you do not need to
297     * worry about yours conflicting with other handlers.
298     */
299    public Handler getTarget() {
300        return target;
301    }
302
303    /**
304     * Retrieve callback object that will execute when this message is handled.
305     * This object must implement Runnable. This is called by
306     * the <em>target</em> {@link Handler} that is receiving this Message to
307     * dispatch it.  If
308     * not set, the message will be dispatched to the receiving Handler's
309     * {@link Handler#handleMessage(Message Handler.handleMessage())}.
310     */
311    public Runnable getCallback() {
312        return callback;
313    }
314
315    /**
316     * Obtains a Bundle of arbitrary data associated with this
317     * event, lazily creating it if necessary. Set this value by calling
318     * {@link #setData(Bundle)}.  Note that when transferring data across
319     * processes via {@link Messenger}, you will need to set your ClassLoader
320     * on the Bundle via {@link Bundle#setClassLoader(ClassLoader)
321     * Bundle.setClassLoader()} so that it can instantiate your objects when
322     * you retrieve them.
323     * @see #peekData()
324     * @see #setData(Bundle)
325     */
326    public Bundle getData() {
327        if (data == null) {
328            data = new Bundle();
329        }
330
331        return data;
332    }
333
334    /**
335     * Like getData(), but does not lazily create the Bundle.  A null
336     * is returned if the Bundle does not already exist.  See
337     * {@link #getData} for further information on this.
338     * @see #getData()
339     * @see #setData(Bundle)
340     */
341    public Bundle peekData() {
342        return data;
343    }
344
345    /**
346     * Sets a Bundle of arbitrary data values. Use arg1 and arg1 members
347     * as a lower cost way to send a few simple integer values, if you can.
348     * @see #getData()
349     * @see #peekData()
350     */
351    public void setData(Bundle data) {
352        this.data = data;
353    }
354
355    /**
356     * Sends this Message to the Handler specified by {@link #getTarget}.
357     * Throws a null pointer exception if this field has not been set.
358     */
359    public void sendToTarget() {
360        target.sendMessage(this);
361    }
362
363    /**
364     * Returns true if the message is asynchronous.
365     *
366     * Asynchronous messages represent interrupts or events that do not require global ordering
367     * with represent to synchronous messages.  Asynchronous messages are not subject to
368     * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
369     *
370     * @return True if the message is asynchronous.
371     *
372     * @see #setAsynchronous(boolean)
373     * @see MessageQueue#enqueueSyncBarrier(long)
374     * @see MessageQueue#removeSyncBarrier(int)
375     *
376     * @hide
377     */
378    public boolean isAsynchronous() {
379        return (flags & FLAG_ASYNCHRONOUS) != 0;
380    }
381
382    /**
383     * Sets whether the message is asynchronous.
384     *
385     * Asynchronous messages represent interrupts or events that do not require global ordering
386     * with represent to synchronous messages.  Asynchronous messages are not subject to
387     * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
388     *
389     * @param async True if the message is asynchronous.
390     *
391     * @see #isAsynchronous()
392     * @see MessageQueue#enqueueSyncBarrier(long)
393     * @see MessageQueue#removeSyncBarrier(int)
394     *
395     * @hide
396     */
397    public void setAsynchronous(boolean async) {
398        if (async) {
399            flags |= FLAG_ASYNCHRONOUS;
400        } else {
401            flags &= ~FLAG_ASYNCHRONOUS;
402        }
403    }
404
405    /*package*/ void clearForRecycle() {
406        flags = 0;
407        what = 0;
408        arg1 = 0;
409        arg2 = 0;
410        obj = null;
411        replyTo = null;
412        when = 0;
413        target = null;
414        callback = null;
415        data = null;
416    }
417
418    /*package*/ boolean isInUse() {
419        return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
420    }
421
422    /*package*/ void markInUse() {
423        flags |= FLAG_IN_USE;
424    }
425
426    /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
427    */
428    public Message() {
429    }
430
431    public String toString() {
432        return toString(SystemClock.uptimeMillis());
433    }
434
435    String toString(long now) {
436        StringBuilder   b = new StringBuilder();
437
438        b.append("{ what=");
439        b.append(what);
440
441        b.append(" when=");
442        TimeUtils.formatDuration(when-now, b);
443
444        if (arg1 != 0) {
445            b.append(" arg1=");
446            b.append(arg1);
447        }
448
449        if (arg2 != 0) {
450            b.append(" arg2=");
451            b.append(arg2);
452        }
453
454        if (obj != null) {
455            b.append(" obj=");
456            b.append(obj);
457        }
458
459        b.append(" }");
460
461        return b.toString();
462    }
463
464    public static final Parcelable.Creator<Message> CREATOR
465            = new Parcelable.Creator<Message>() {
466        public Message createFromParcel(Parcel source) {
467            Message msg = Message.obtain();
468            msg.readFromParcel(source);
469            return msg;
470        }
471
472        public Message[] newArray(int size) {
473            return new Message[size];
474        }
475    };
476
477    public int describeContents() {
478        return 0;
479    }
480
481    public void writeToParcel(Parcel dest, int flags) {
482        if (callback != null) {
483            throw new RuntimeException(
484                "Can't marshal callbacks across processes.");
485        }
486        dest.writeInt(what);
487        dest.writeInt(arg1);
488        dest.writeInt(arg2);
489        if (obj != null) {
490            try {
491                Parcelable p = (Parcelable)obj;
492                dest.writeInt(1);
493                dest.writeParcelable(p, flags);
494            } catch (ClassCastException e) {
495                throw new RuntimeException(
496                    "Can't marshal non-Parcelable objects across processes.");
497            }
498        } else {
499            dest.writeInt(0);
500        }
501        dest.writeLong(when);
502        dest.writeBundle(data);
503        Messenger.writeMessengerOrNullToParcel(replyTo, dest);
504    }
505
506    private void readFromParcel(Parcel source) {
507        what = source.readInt();
508        arg1 = source.readInt();
509        arg2 = source.readInt();
510        if (source.readInt() != 0) {
511            obj = source.readParcelable(getClass().getClassLoader());
512        }
513        when = source.readLong();
514        data = source.readBundle();
515        replyTo = Messenger.readMessengerOrNullFromParcel(source);
516    }
517}
518