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