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