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     /** If set message is in use */
     75     /*package*/ static final int FLAG_IN_USE = 1 << 0;
     76 
     77     /** If set message is asynchronous */
     78     /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;
     79 
     80     /** Flags to clear in the copyFrom method */
     81     /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
     82 
     83     /*package*/ int flags;
     84 
     85     /*package*/ long when;
     86 
     87     /*package*/ Bundle data;
     88 
     89     /*package*/ Handler target;
     90 
     91     /*package*/ Runnable callback;
     92 
     93     // sometimes we store linked lists of these things
     94     /*package*/ Message next;
     95 
     96     private static final Object sPoolSync = new Object();
     97     private static Message sPool;
     98     private static int sPoolSize = 0;
     99 
    100     private static final int MAX_POOL_SIZE = 50;
    101 
    102     /**
    103      * Return a new Message instance from the global pool. Allows us to
    104      * avoid allocating new objects in many cases.
    105      */
    106     public static Message obtain() {
    107         synchronized (sPoolSync) {
    108             if (sPool != null) {
    109                 Message m = sPool;
    110                 sPool = m.next;
    111                 m.next = null;
    112                 sPoolSize--;
    113                 return m;
    114             }
    115         }
    116         return new Message();
    117     }
    118 
    119     /**
    120      * Same as {@link #obtain()}, but copies the values of an existing
    121      * message (including its target) into the new one.
    122      * @param orig Original message to copy.
    123      * @return A Message object from the global pool.
    124      */
    125     public static Message obtain(Message orig) {
    126         Message m = obtain();
    127         m.what = orig.what;
    128         m.arg1 = orig.arg1;
    129         m.arg2 = orig.arg2;
    130         m.obj = orig.obj;
    131         m.replyTo = orig.replyTo;
    132         if (orig.data != null) {
    133             m.data = new Bundle(orig.data);
    134         }
    135         m.target = orig.target;
    136         m.callback = orig.callback;
    137 
    138         return m;
    139     }
    140 
    141     /**
    142      * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.
    143      * @param h  Handler to assign to the returned Message object's <em>target</em> member.
    144      * @return A Message object from the global pool.
    145      */
    146     public static Message obtain(Handler h) {
    147         Message m = obtain();
    148         m.target = h;
    149 
    150         return m;
    151     }
    152 
    153     /**
    154      * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on
    155      * the Message that is returned.
    156      * @param h  Handler to assign to the returned Message object's <em>target</em> member.
    157      * @param callback Runnable that will execute when the message is handled.
    158      * @return A Message object from the global pool.
    159      */
    160     public static Message obtain(Handler h, Runnable callback) {
    161         Message m = obtain();
    162         m.target = h;
    163         m.callback = callback;
    164 
    165         return m;
    166     }
    167 
    168     /**
    169      * Same as {@link #obtain()}, but sets the values for both <em>target</em> and
    170      * <em>what</em> members on the Message.
    171      * @param h  Value to assign to the <em>target</em> member.
    172      * @param what  Value to assign to the <em>what</em> member.
    173      * @return A Message object from the global pool.
    174      */
    175     public static Message obtain(Handler h, int what) {
    176         Message m = obtain();
    177         m.target = h;
    178         m.what = what;
    179 
    180         return m;
    181     }
    182 
    183     /**
    184      * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em>
    185      * members.
    186      * @param h  The <em>target</em> value to set.
    187      * @param what  The <em>what</em> value to set.
    188      * @param obj  The <em>object</em> method to set.
    189      * @return  A Message object from the global pool.
    190      */
    191     public static Message obtain(Handler h, int what, Object obj) {
    192         Message m = obtain();
    193         m.target = h;
    194         m.what = what;
    195         m.obj = obj;
    196 
    197         return m;
    198     }
    199 
    200     /**
    201      * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
    202      * <em>arg1</em>, and <em>arg2</em> members.
    203      *
    204      * @param h  The <em>target</em> value to set.
    205      * @param what  The <em>what</em> value to set.
    206      * @param arg1  The <em>arg1</em> value to set.
    207      * @param arg2  The <em>arg2</em> value to set.
    208      * @return  A Message object from the global pool.
    209      */
    210     public static Message obtain(Handler h, int what, int arg1, int arg2) {
    211         Message m = obtain();
    212         m.target = h;
    213         m.what = what;
    214         m.arg1 = arg1;
    215         m.arg2 = arg2;
    216 
    217         return m;
    218     }
    219 
    220     /**
    221      * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
    222      * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members.
    223      *
    224      * @param h  The <em>target</em> value to set.
    225      * @param what  The <em>what</em> value to set.
    226      * @param arg1  The <em>arg1</em> value to set.
    227      * @param arg2  The <em>arg2</em> value to set.
    228      * @param obj  The <em>obj</em> value to set.
    229      * @return  A Message object from the global pool.
    230      */
    231     public static Message obtain(Handler h, int what,
    232             int arg1, int arg2, Object obj) {
    233         Message m = obtain();
    234         m.target = h;
    235         m.what = what;
    236         m.arg1 = arg1;
    237         m.arg2 = arg2;
    238         m.obj = obj;
    239 
    240         return m;
    241     }
    242 
    243     /**
    244      * Return a Message instance to the global pool.  You MUST NOT touch
    245      * the Message after calling this function -- it has effectively been
    246      * freed.
    247      */
    248     public void recycle() {
    249         clearForRecycle();
    250 
    251         synchronized (sPoolSync) {
    252             if (sPoolSize < MAX_POOL_SIZE) {
    253                 next = sPool;
    254                 sPool = this;
    255                 sPoolSize++;
    256             }
    257         }
    258     }
    259 
    260     /**
    261      * Make this message like o.  Performs a shallow copy of the data field.
    262      * Does not copy the linked list fields, nor the timestamp or
    263      * target/callback of the original message.
    264      */
    265     public void copyFrom(Message o) {
    266         this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM;
    267         this.what = o.what;
    268         this.arg1 = o.arg1;
    269         this.arg2 = o.arg2;
    270         this.obj = o.obj;
    271         this.replyTo = o.replyTo;
    272 
    273         if (o.data != null) {
    274             this.data = (Bundle) o.data.clone();
    275         } else {
    276             this.data = null;
    277         }
    278     }
    279 
    280     /**
    281      * Return the targeted delivery time of this message, in milliseconds.
    282      */
    283     public long getWhen() {
    284         return when;
    285     }
    286 
    287     public void setTarget(Handler target) {
    288         this.target = target;
    289     }
    290 
    291     /**
    292      * Retrieve the a {@link android.os.Handler Handler} implementation that
    293      * will receive this message. The object must implement
    294      * {@link android.os.Handler#handleMessage(android.os.Message)
    295      * Handler.handleMessage()}. Each Handler has its own name-space for
    296      * message codes, so you do not need to
    297      * worry about yours conflicting with other handlers.
    298      */
    299     public Handler getTarget() {
    300         return target;
    301     }
    302 
    303     /**
    304      * Retrieve callback object that will execute when this message is handled.
    305      * This object must implement Runnable. This is called by
    306      * the <em>target</em> {@link Handler} that is receiving this Message to
    307      * dispatch it.  If
    308      * not set, the message will be dispatched to the receiving Handler's
    309      * {@link Handler#handleMessage(Message Handler.handleMessage())}.
    310      */
    311     public Runnable getCallback() {
    312         return callback;
    313     }
    314 
    315     /**
    316      * Obtains a Bundle of arbitrary data associated with this
    317      * event, lazily creating it if necessary. Set this value by calling
    318      * {@link #setData(Bundle)}.  Note that when transferring data across
    319      * processes via {@link Messenger}, you will need to set your ClassLoader
    320      * on the Bundle via {@link Bundle#setClassLoader(ClassLoader)
    321      * Bundle.setClassLoader()} so that it can instantiate your objects when
    322      * you retrieve them.
    323      * @see #peekData()
    324      * @see #setData(Bundle)
    325      */
    326     public Bundle getData() {
    327         if (data == null) {
    328             data = new Bundle();
    329         }
    330 
    331         return data;
    332     }
    333 
    334     /**
    335      * Like getData(), but does not lazily create the Bundle.  A null
    336      * is returned if the Bundle does not already exist.  See
    337      * {@link #getData} for further information on this.
    338      * @see #getData()
    339      * @see #setData(Bundle)
    340      */
    341     public Bundle peekData() {
    342         return data;
    343     }
    344 
    345     /**
    346      * Sets a Bundle of arbitrary data values. Use arg1 and arg1 members
    347      * as a lower cost way to send a few simple integer values, if you can.
    348      * @see #getData()
    349      * @see #peekData()
    350      */
    351     public void setData(Bundle data) {
    352         this.data = data;
    353     }
    354 
    355     /**
    356      * Sends this Message to the Handler specified by {@link #getTarget}.
    357      * Throws a null pointer exception if this field has not been set.
    358      */
    359     public void sendToTarget() {
    360         target.sendMessage(this);
    361     }
    362 
    363     /**
    364      * Returns true if the message is asynchronous.
    365      *
    366      * Asynchronous messages represent interrupts or events that do not require global ordering
    367      * with represent to synchronous messages.  Asynchronous messages are not subject to
    368      * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
    369      *
    370      * @return True if the message is asynchronous.
    371      *
    372      * @see #setAsynchronous(boolean)
    373      * @see MessageQueue#enqueueSyncBarrier(long)
    374      * @see MessageQueue#removeSyncBarrier(int)
    375      *
    376      * @hide
    377      */
    378     public boolean isAsynchronous() {
    379         return (flags & FLAG_ASYNCHRONOUS) != 0;
    380     }
    381 
    382     /**
    383      * Sets whether the message is asynchronous.
    384      *
    385      * Asynchronous messages represent interrupts or events that do not require global ordering
    386      * with represent to synchronous messages.  Asynchronous messages are not subject to
    387      * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
    388      *
    389      * @param async True if the message is asynchronous.
    390      *
    391      * @see #isAsynchronous()
    392      * @see MessageQueue#enqueueSyncBarrier(long)
    393      * @see MessageQueue#removeSyncBarrier(int)
    394      *
    395      * @hide
    396      */
    397     public void setAsynchronous(boolean async) {
    398         if (async) {
    399             flags |= FLAG_ASYNCHRONOUS;
    400         } else {
    401             flags &= ~FLAG_ASYNCHRONOUS;
    402         }
    403     }
    404 
    405     /*package*/ void clearForRecycle() {
    406         flags = 0;
    407         what = 0;
    408         arg1 = 0;
    409         arg2 = 0;
    410         obj = null;
    411         replyTo = null;
    412         when = 0;
    413         target = null;
    414         callback = null;
    415         data = null;
    416     }
    417 
    418     /*package*/ boolean isInUse() {
    419         return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
    420     }
    421 
    422     /*package*/ void markInUse() {
    423         flags |= FLAG_IN_USE;
    424     }
    425 
    426     /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
    427     */
    428     public Message() {
    429     }
    430 
    431     @Override
    432     public String toString() {
    433         return toString(SystemClock.uptimeMillis());
    434     }
    435 
    436     String toString(long now) {
    437         StringBuilder b = new StringBuilder();
    438         b.append("{ when=");
    439         TimeUtils.formatDuration(when - now, b);
    440 
    441         if (target != null) {
    442             if (callback != null) {
    443                 b.append(" callback=");
    444                 b.append(callback.getClass().getName());
    445             } else {
    446                 b.append(" what=");
    447                 b.append(what);
    448             }
    449 
    450             if (arg1 != 0) {
    451                 b.append(" arg1=");
    452                 b.append(arg1);
    453             }
    454 
    455             if (arg2 != 0) {
    456                 b.append(" arg2=");
    457                 b.append(arg2);
    458             }
    459 
    460             if (obj != null) {
    461                 b.append(" obj=");
    462                 b.append(obj);
    463             }
    464 
    465             b.append(" target=");
    466             b.append(target.getClass().getName());
    467         } else {
    468             b.append(" barrier=");
    469             b.append(arg1);
    470         }
    471 
    472         b.append(" }");
    473         return b.toString();
    474     }
    475 
    476     public static final Parcelable.Creator<Message> CREATOR
    477             = new Parcelable.Creator<Message>() {
    478         public Message createFromParcel(Parcel source) {
    479             Message msg = Message.obtain();
    480             msg.readFromParcel(source);
    481             return msg;
    482         }
    483 
    484         public Message[] newArray(int size) {
    485             return new Message[size];
    486         }
    487     };
    488 
    489     public int describeContents() {
    490         return 0;
    491     }
    492 
    493     public void writeToParcel(Parcel dest, int flags) {
    494         if (callback != null) {
    495             throw new RuntimeException(
    496                 "Can't marshal callbacks across processes.");
    497         }
    498         dest.writeInt(what);
    499         dest.writeInt(arg1);
    500         dest.writeInt(arg2);
    501         if (obj != null) {
    502             try {
    503                 Parcelable p = (Parcelable)obj;
    504                 dest.writeInt(1);
    505                 dest.writeParcelable(p, flags);
    506             } catch (ClassCastException e) {
    507                 throw new RuntimeException(
    508                     "Can't marshal non-Parcelable objects across processes.");
    509             }
    510         } else {
    511             dest.writeInt(0);
    512         }
    513         dest.writeLong(when);
    514         dest.writeBundle(data);
    515         Messenger.writeMessengerOrNullToParcel(replyTo, dest);
    516     }
    517 
    518     private void readFromParcel(Parcel source) {
    519         what = source.readInt();
    520         arg1 = source.readInt();
    521         arg2 = source.readInt();
    522         if (source.readInt() != 0) {
    523             obj = source.readParcelable(getClass().getClassLoader());
    524         }
    525         when = source.readLong();
    526         data = source.readBundle();
    527         replyTo = Messenger.readMessengerOrNullFromParcel(source);
    528     }
    529 }
    530