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