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 
17 package android.os;
18 
19 import android.os.MessageProto;
20 import android.util.TimeUtils;
21 import 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  */
34 public 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      */
obtain()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      */
obtain(Message orig)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      */
obtain(Handler h)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      */
obtain(Handler h, Runnable callback)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      */
obtain(Handler h, int what)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      */
obtain(Handler h, int what, Object obj)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      */
obtain(Handler h, int what, int arg1, int arg2)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      */
obtain(Handler h, int what, int arg1, int arg2, Object obj)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 */
updateCheckRecycle(int targetSdkVersion)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      */
recycle()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      */
recycleUnchecked()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      */
copyFrom(Message o)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      */
getWhen()343     public long getWhen() {
344         return when;
345     }
346 
setTarget(Handler target)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      */
getTarget()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      */
getCallback()371     public Runnable getCallback() {
372         return callback;
373     }
374 
375     /** @hide */
setCallback(Runnable r)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      */
getData()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      */
peekData()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      */
setData(Bundle data)417     public void setData(Bundle data) {
418         this.data = data;
419     }
420 
421     /**
422      * Chainable setter for {@link #what}
423      *
424      * @hide
425      */
setWhat(int what)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      */
sendToTarget()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      */
isAsynchronous()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      */
setAsynchronous(boolean async)477     public void setAsynchronous(boolean async) {
478         if (async) {
479             flags |= FLAG_ASYNCHRONOUS;
480         } else {
481             flags &= ~FLAG_ASYNCHRONOUS;
482         }
483     }
484 
isInUse()485     /*package*/ boolean isInUse() {
486         return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
487     }
488 
markInUse()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     */
Message()495     public Message() {
496     }
497 
498     @Override
toString()499     public String toString() {
500         return toString(SystemClock.uptimeMillis());
501     }
502 
toString(long now)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 
writeToProto(ProtoOutputStream proto, long fieldId)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 
describeContents()587     public int describeContents() {
588         return 0;
589     }
590 
writeToParcel(Parcel dest, int flags)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 
readFromParcel(Parcel source)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