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.MessageProto;
20import android.util.TimeUtils;
21import android.util.proto.ProtoOutputStream;
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 */
34public 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    /**
44     * arg1 and arg2 are lower-cost alternatives to using
45     * {@link #setData(Bundle) setData()} if you only need to store a
46     * few integer values.
47     */
48    public int arg1;
49
50    /**
51     * arg1 and arg2 are lower-cost alternatives to using
52     * {@link #setData(Bundle) setData()} if you only need to store a
53     * few integer values.
54     */
55    public int arg2;
56
57    /**
58     * An arbitrary object to send to the recipient.  When using
59     * {@link Messenger} to send the message across processes this can only
60     * be non-null if it contains a Parcelable of a framework class (not one
61     * implemented by the application).   For other data transfer use
62     * {@link #setData}.
63     *
64     * <p>Note that Parcelable objects here are not supported prior to
65     * the {@link android.os.Build.VERSION_CODES#FROYO} release.
66     */
67    public Object obj;
68
69    /**
70     * Optional Messenger where replies to this message can be sent.  The
71     * semantics of exactly how this is used are up to the sender and
72     * receiver.
73     */
74    public Messenger replyTo;
75
76    /**
77     * Optional field indicating the uid that sent the message.  This is
78     * only valid for messages posted by a {@link Messenger}; otherwise,
79     * it will be -1.
80     */
81    public int sendingUid = -1;
82
83    /** If set message is in use.
84     * This flag is set when the message is enqueued and remains set while it
85     * is delivered and afterwards when it is recycled.  The flag is only cleared
86     * when a new message is created or obtained since that is the only time that
87     * applications are allowed to modify the contents of the message.
88     *
89     * It is an error to attempt to enqueue or recycle a message that is already in use.
90     */
91    /*package*/ static final int FLAG_IN_USE = 1 << 0;
92
93    /** If set message is asynchronous */
94    /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;
95
96    /** Flags to clear in the copyFrom method */
97    /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
98
99    /*package*/ int flags;
100
101    /*package*/ long when;
102
103    /*package*/ Bundle data;
104
105    /*package*/ Handler target;
106
107    /*package*/ Runnable callback;
108
109    // sometimes we store linked lists of these things
110    /*package*/ Message next;
111
112
113    /** @hide */
114    public static final Object sPoolSync = new Object();
115    private static Message sPool;
116    private static int sPoolSize = 0;
117
118    private static final int MAX_POOL_SIZE = 50;
119
120    private static boolean gCheckRecycle = true;
121
122    /**
123     * Return a new Message instance from the global pool. Allows us to
124     * avoid allocating new objects in many cases.
125     */
126    public static Message obtain() {
127        synchronized (sPoolSync) {
128            if (sPool != null) {
129                Message m = sPool;
130                sPool = m.next;
131                m.next = null;
132                m.flags = 0; // clear in-use flag
133                sPoolSize--;
134                return m;
135            }
136        }
137        return new Message();
138    }
139
140    /**
141     * Same as {@link #obtain()}, but copies the values of an existing
142     * message (including its target) into the new one.
143     * @param orig Original message to copy.
144     * @return A Message object from the global pool.
145     */
146    public static Message obtain(Message orig) {
147        Message m = obtain();
148        m.what = orig.what;
149        m.arg1 = orig.arg1;
150        m.arg2 = orig.arg2;
151        m.obj = orig.obj;
152        m.replyTo = orig.replyTo;
153        m.sendingUid = orig.sendingUid;
154        if (orig.data != null) {
155            m.data = new Bundle(orig.data);
156        }
157        m.target = orig.target;
158        m.callback = orig.callback;
159
160        return m;
161    }
162
163    /**
164     * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.
165     * @param h  Handler to assign to the returned Message object's <em>target</em> member.
166     * @return A Message object from the global pool.
167     */
168    public static Message obtain(Handler h) {
169        Message m = obtain();
170        m.target = h;
171
172        return m;
173    }
174
175    /**
176     * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on
177     * the Message that is returned.
178     * @param h  Handler to assign to the returned Message object's <em>target</em> member.
179     * @param callback Runnable that will execute when the message is handled.
180     * @return A Message object from the global pool.
181     */
182    public static Message obtain(Handler h, Runnable callback) {
183        Message m = obtain();
184        m.target = h;
185        m.callback = callback;
186
187        return m;
188    }
189
190    /**
191     * Same as {@link #obtain()}, but sets the values for both <em>target</em> and
192     * <em>what</em> members on the Message.
193     * @param h  Value to assign to the <em>target</em> member.
194     * @param what  Value to assign to the <em>what</em> member.
195     * @return A Message object from the global pool.
196     */
197    public static Message obtain(Handler h, int what) {
198        Message m = obtain();
199        m.target = h;
200        m.what = what;
201
202        return m;
203    }
204
205    /**
206     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em>
207     * members.
208     * @param h  The <em>target</em> value to set.
209     * @param what  The <em>what</em> value to set.
210     * @param obj  The <em>object</em> method to set.
211     * @return  A Message object from the global pool.
212     */
213    public static Message obtain(Handler h, int what, Object obj) {
214        Message m = obtain();
215        m.target = h;
216        m.what = what;
217        m.obj = obj;
218
219        return m;
220    }
221
222    /**
223     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
224     * <em>arg1</em>, and <em>arg2</em> members.
225     *
226     * @param h  The <em>target</em> value to set.
227     * @param what  The <em>what</em> value to set.
228     * @param arg1  The <em>arg1</em> value to set.
229     * @param arg2  The <em>arg2</em> value to set.
230     * @return  A Message object from the global pool.
231     */
232    public static Message obtain(Handler h, int what, int arg1, int arg2) {
233        Message m = obtain();
234        m.target = h;
235        m.what = what;
236        m.arg1 = arg1;
237        m.arg2 = arg2;
238
239        return m;
240    }
241
242    /**
243     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
244     * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members.
245     *
246     * @param h  The <em>target</em> value to set.
247     * @param what  The <em>what</em> value to set.
248     * @param arg1  The <em>arg1</em> value to set.
249     * @param arg2  The <em>arg2</em> value to set.
250     * @param obj  The <em>obj</em> value to set.
251     * @return  A Message object from the global pool.
252     */
253    public static Message obtain(Handler h, int what,
254            int arg1, int arg2, Object obj) {
255        Message m = obtain();
256        m.target = h;
257        m.what = what;
258        m.arg1 = arg1;
259        m.arg2 = arg2;
260        m.obj = obj;
261
262        return m;
263    }
264
265    /** @hide */
266    public static void updateCheckRecycle(int targetSdkVersion) {
267        if (targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) {
268            gCheckRecycle = false;
269        }
270    }
271
272    /**
273     * Return a Message instance to the global pool.
274     * <p>
275     * You MUST NOT touch the Message after calling this function because it has
276     * effectively been freed.  It is an error to recycle a message that is currently
277     * enqueued or that is in the process of being delivered to a Handler.
278     * </p>
279     */
280    public void recycle() {
281        if (isInUse()) {
282            if (gCheckRecycle) {
283                throw new IllegalStateException("This message cannot be recycled because it "
284                        + "is still in use.");
285            }
286            return;
287        }
288        recycleUnchecked();
289    }
290
291    /**
292     * Recycles a Message that may be in-use.
293     * Used internally by the MessageQueue and Looper when disposing of queued Messages.
294     */
295    void recycleUnchecked() {
296        // Mark the message as in use while it remains in the recycled object pool.
297        // Clear out all other details.
298        flags = FLAG_IN_USE;
299        what = 0;
300        arg1 = 0;
301        arg2 = 0;
302        obj = null;
303        replyTo = null;
304        sendingUid = -1;
305        when = 0;
306        target = null;
307        callback = null;
308        data = null;
309
310        synchronized (sPoolSync) {
311            if (sPoolSize < MAX_POOL_SIZE) {
312                next = sPool;
313                sPool = this;
314                sPoolSize++;
315            }
316        }
317    }
318
319    /**
320     * Make this message like o.  Performs a shallow copy of the data field.
321     * Does not copy the linked list fields, nor the timestamp or
322     * target/callback of the original message.
323     */
324    public void copyFrom(Message o) {
325        this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM;
326        this.what = o.what;
327        this.arg1 = o.arg1;
328        this.arg2 = o.arg2;
329        this.obj = o.obj;
330        this.replyTo = o.replyTo;
331        this.sendingUid = o.sendingUid;
332
333        if (o.data != null) {
334            this.data = (Bundle) o.data.clone();
335        } else {
336            this.data = null;
337        }
338    }
339
340    /**
341     * Return the targeted delivery time of this message, in milliseconds.
342     */
343    public long getWhen() {
344        return when;
345    }
346
347    public void setTarget(Handler target) {
348        this.target = target;
349    }
350
351    /**
352     * Retrieve the a {@link android.os.Handler Handler} implementation that
353     * will receive this message. The object must implement
354     * {@link android.os.Handler#handleMessage(android.os.Message)
355     * Handler.handleMessage()}. Each Handler has its own name-space for
356     * message codes, so you do not need to
357     * worry about yours conflicting with other handlers.
358     */
359    public Handler getTarget() {
360        return target;
361    }
362
363    /**
364     * Retrieve callback object that will execute when this message is handled.
365     * This object must implement Runnable. This is called by
366     * the <em>target</em> {@link Handler} that is receiving this Message to
367     * dispatch it.  If
368     * not set, the message will be dispatched to the receiving Handler's
369     * {@link Handler#handleMessage(Message Handler.handleMessage())}.
370     */
371    public Runnable getCallback() {
372        return callback;
373    }
374
375    /** @hide */
376    public Message setCallback(Runnable r) {
377        callback = r;
378        return this;
379    }
380
381    /**
382     * Obtains a Bundle of arbitrary data associated with this
383     * event, lazily creating it if necessary. Set this value by calling
384     * {@link #setData(Bundle)}.  Note that when transferring data across
385     * processes via {@link Messenger}, you will need to set your ClassLoader
386     * on the Bundle via {@link Bundle#setClassLoader(ClassLoader)
387     * Bundle.setClassLoader()} so that it can instantiate your objects when
388     * you retrieve them.
389     * @see #peekData()
390     * @see #setData(Bundle)
391     */
392    public Bundle getData() {
393        if (data == null) {
394            data = new Bundle();
395        }
396
397        return data;
398    }
399
400    /**
401     * Like getData(), but does not lazily create the Bundle.  A null
402     * is returned if the Bundle does not already exist.  See
403     * {@link #getData} for further information on this.
404     * @see #getData()
405     * @see #setData(Bundle)
406     */
407    public Bundle peekData() {
408        return data;
409    }
410
411    /**
412     * Sets a Bundle of arbitrary data values. Use arg1 and arg2 members
413     * as a lower cost way to send a few simple integer values, if you can.
414     * @see #getData()
415     * @see #peekData()
416     */
417    public void setData(Bundle data) {
418        this.data = data;
419    }
420
421    /**
422     * Chainable setter for {@link #what}
423     *
424     * @hide
425     */
426    public Message setWhat(int what) {
427        this.what = what;
428        return this;
429    }
430
431    /**
432     * Sends this Message to the Handler specified by {@link #getTarget}.
433     * Throws a null pointer exception if this field has not been set.
434     */
435    public void sendToTarget() {
436        target.sendMessage(this);
437    }
438
439    /**
440     * Returns true if the message is asynchronous, meaning that it is not
441     * subject to {@link Looper} synchronization barriers.
442     *
443     * @return True if the message is asynchronous.
444     *
445     * @see #setAsynchronous(boolean)
446     */
447    public boolean isAsynchronous() {
448        return (flags & FLAG_ASYNCHRONOUS) != 0;
449    }
450
451    /**
452     * Sets whether the message is asynchronous, meaning that it is not
453     * subject to {@link Looper} synchronization barriers.
454     * <p>
455     * Certain operations, such as view invalidation, may introduce synchronization
456     * barriers into the {@link Looper}'s message queue to prevent subsequent messages
457     * from being delivered until some condition is met.  In the case of view invalidation,
458     * messages which are posted after a call to {@link android.view.View#invalidate}
459     * are suspended by means of a synchronization barrier until the next frame is
460     * ready to be drawn.  The synchronization barrier ensures that the invalidation
461     * request is completely handled before resuming.
462     * </p><p>
463     * Asynchronous messages are exempt from synchronization barriers.  They typically
464     * represent interrupts, input events, and other signals that must be handled independently
465     * even while other work has been suspended.
466     * </p><p>
467     * Note that asynchronous messages may be delivered out of order with respect to
468     * synchronous messages although they are always delivered in order among themselves.
469     * If the relative order of these messages matters then they probably should not be
470     * asynchronous in the first place.  Use with caution.
471     * </p>
472     *
473     * @param async True if the message is asynchronous.
474     *
475     * @see #isAsynchronous()
476     */
477    public void setAsynchronous(boolean async) {
478        if (async) {
479            flags |= FLAG_ASYNCHRONOUS;
480        } else {
481            flags &= ~FLAG_ASYNCHRONOUS;
482        }
483    }
484
485    /*package*/ boolean isInUse() {
486        return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
487    }
488
489    /*package*/ void markInUse() {
490        flags |= FLAG_IN_USE;
491    }
492
493    /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
494    */
495    public Message() {
496    }
497
498    @Override
499    public String toString() {
500        return toString(SystemClock.uptimeMillis());
501    }
502
503    String toString(long now) {
504        StringBuilder b = new StringBuilder();
505        b.append("{ when=");
506        TimeUtils.formatDuration(when - now, b);
507
508        if (target != null) {
509            if (callback != null) {
510                b.append(" callback=");
511                b.append(callback.getClass().getName());
512            } else {
513                b.append(" what=");
514                b.append(what);
515            }
516
517            if (arg1 != 0) {
518                b.append(" arg1=");
519                b.append(arg1);
520            }
521
522            if (arg2 != 0) {
523                b.append(" arg2=");
524                b.append(arg2);
525            }
526
527            if (obj != null) {
528                b.append(" obj=");
529                b.append(obj);
530            }
531
532            b.append(" target=");
533            b.append(target.getClass().getName());
534        } else {
535            b.append(" barrier=");
536            b.append(arg1);
537        }
538
539        b.append(" }");
540        return b.toString();
541    }
542
543    void writeToProto(ProtoOutputStream proto, long fieldId) {
544        final long messageToken = proto.start(fieldId);
545        proto.write(MessageProto.WHEN, when);
546
547        if (target != null) {
548            if (callback != null) {
549                proto.write(MessageProto.CALLBACK, callback.getClass().getName());
550            } else {
551                proto.write(MessageProto.WHAT, what);
552            }
553
554            if (arg1 != 0) {
555                proto.write(MessageProto.ARG1, arg1);
556            }
557
558            if (arg2 != 0) {
559                proto.write(MessageProto.ARG2, arg2);
560            }
561
562            if (obj != null) {
563                proto.write(MessageProto.OBJ, obj.toString());
564            }
565
566            proto.write(MessageProto.TARGET, target.getClass().getName());
567        } else {
568            proto.write(MessageProto.BARRIER, arg1);
569        }
570
571        proto.end(messageToken);
572    }
573
574    public static final Parcelable.Creator<Message> CREATOR
575            = new Parcelable.Creator<Message>() {
576        public Message createFromParcel(Parcel source) {
577            Message msg = Message.obtain();
578            msg.readFromParcel(source);
579            return msg;
580        }
581
582        public Message[] newArray(int size) {
583            return new Message[size];
584        }
585    };
586
587    public int describeContents() {
588        return 0;
589    }
590
591    public void writeToParcel(Parcel dest, int flags) {
592        if (callback != null) {
593            throw new RuntimeException(
594                "Can't marshal callbacks across processes.");
595        }
596        dest.writeInt(what);
597        dest.writeInt(arg1);
598        dest.writeInt(arg2);
599        if (obj != null) {
600            try {
601                Parcelable p = (Parcelable)obj;
602                dest.writeInt(1);
603                dest.writeParcelable(p, flags);
604            } catch (ClassCastException e) {
605                throw new RuntimeException(
606                    "Can't marshal non-Parcelable objects across processes.");
607            }
608        } else {
609            dest.writeInt(0);
610        }
611        dest.writeLong(when);
612        dest.writeBundle(data);
613        Messenger.writeMessengerOrNullToParcel(replyTo, dest);
614        dest.writeInt(sendingUid);
615    }
616
617    private void readFromParcel(Parcel source) {
618        what = source.readInt();
619        arg1 = source.readInt();
620        arg2 = source.readInt();
621        if (source.readInt() != 0) {
622            obj = source.readParcelable(getClass().getClassLoader());
623        }
624        when = source.readLong();
625        data = source.readBundle();
626        replyTo = Messenger.readMessengerOrNullFromParcel(source);
627        sendingUid = source.readInt();
628    }
629}
630