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