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