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