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