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.Bundle;
     20 import android.os.Parcel;
     21 import android.os.Parcelable;
     22 import android.util.TimeUtils;
     23 
     24 /**
     25  *
     26  * Defines a message containing a description and arbitrary data object that can be
     27  * sent to a {@link Handler}.  This object contains two extra int fields and an
     28  * extra object field that allow you to not do allocations in many cases.
     29  *
     30  * <p class="note">While the constructor of Message is public, the best way to get
     31  * one of these is to call {@link #obtain Message.obtain()} or one of the
     32  * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull
     33  * them from a pool of recycled objects.</p>
     34  */
     35 public final class Message implements Parcelable {
     36     /**
     37      * User-defined message code so that the recipient can identify
     38      * what this message is about. Each {@link Handler} has its own name-space
     39      * for message codes, so you do not need to worry about yours conflicting
     40      * with other handlers.
     41      */
     42     public int what;
     43 
     44     /**
     45      * arg1 and arg2 are lower-cost alternatives to using
     46      * {@link #setData(Bundle) setData()} if you only need to store a
     47      * few integer values.
     48      */
     49     public int arg1;
     50 
     51     /**
     52      * arg1 and arg2 are lower-cost alternatives to using
     53      * {@link #setData(Bundle) setData()} if you only need to store a
     54      * few integer values.
     55      */
     56     public int arg2;
     57 
     58     /**
     59      * An arbitrary object to send to the recipient.  When using
     60      * {@link Messenger} to send the message across processes this can only
     61      * be non-null if it contains a Parcelable of a framework class (not one
     62      * implemented by the application).   For other data transfer use
     63      * {@link #setData}.
     64      *
     65      * <p>Note that Parcelable objects here are not supported prior to
     66      * the {@link android.os.Build.VERSION_CODES#FROYO} release.
     67      */
     68     public Object obj;
     69 
     70     /**
     71      * Optional Messenger where replies to this message can be sent.  The
     72      * semantics of exactly how this is used are up to the sender and
     73      * receiver.
     74      */
     75     public Messenger replyTo;
     76 
     77     /*package*/ long when;
     78 
     79     /*package*/ Bundle data;
     80 
     81     /*package*/ Handler target;
     82 
     83     /*package*/ Runnable callback;
     84 
     85     // sometimes we store linked lists of these things
     86     /*package*/ Message next;
     87 
     88     private static Object mPoolSync = new Object();
     89     private static Message mPool;
     90     private static int mPoolSize = 0;
     91 
     92     private static final int MAX_POOL_SIZE = 10;
     93 
     94     /**
     95      * Return a new Message instance from the global pool. Allows us to
     96      * avoid allocating new objects in many cases.
     97      */
     98     public static Message obtain() {
     99         synchronized (mPoolSync) {
    100             if (mPool != null) {
    101                 Message m = mPool;
    102                 mPool = m.next;
    103                 m.next = null;
    104                 return m;
    105             }
    106         }
    107         return new Message();
    108     }
    109 
    110     /**
    111      * Same as {@link #obtain()}, but copies the values of an existing
    112      * message (including its target) into the new one.
    113      * @param orig Original message to copy.
    114      * @return A Message object from the global pool.
    115      */
    116     public static Message obtain(Message orig) {
    117         Message m = obtain();
    118         m.what = orig.what;
    119         m.arg1 = orig.arg1;
    120         m.arg2 = orig.arg2;
    121         m.obj = orig.obj;
    122         m.replyTo = orig.replyTo;
    123         if (orig.data != null) {
    124             m.data = new Bundle(orig.data);
    125         }
    126         m.target = orig.target;
    127         m.callback = orig.callback;
    128 
    129         return m;
    130     }
    131 
    132     /**
    133      * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.
    134      * @param h  Handler to assign to the returned Message object's <em>target</em> member.
    135      * @return A Message object from the global pool.
    136      */
    137     public static Message obtain(Handler h) {
    138         Message m = obtain();
    139         m.target = h;
    140 
    141         return m;
    142     }
    143 
    144     /**
    145      * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on
    146      * the Message that is returned.
    147      * @param h  Handler to assign to the returned Message object's <em>target</em> member.
    148      * @param callback Runnable that will execute when the message is handled.
    149      * @return A Message object from the global pool.
    150      */
    151     public static Message obtain(Handler h, Runnable callback) {
    152         Message m = obtain();
    153         m.target = h;
    154         m.callback = callback;
    155 
    156         return m;
    157     }
    158 
    159     /**
    160      * Same as {@link #obtain()}, but sets the values for both <em>target</em> and
    161      * <em>what</em> members on the Message.
    162      * @param h  Value to assign to the <em>target</em> member.
    163      * @param what  Value to assign to the <em>what</em> member.
    164      * @return A Message object from the global pool.
    165      */
    166     public static Message obtain(Handler h, int what) {
    167         Message m = obtain();
    168         m.target = h;
    169         m.what = what;
    170 
    171         return m;
    172     }
    173 
    174     /**
    175      * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em>
    176      * members.
    177      * @param h  The <em>target</em> value to set.
    178      * @param what  The <em>what</em> value to set.
    179      * @param obj  The <em>object</em> method to set.
    180      * @return  A Message object from the global pool.
    181      */
    182     public static Message obtain(Handler h, int what, Object obj) {
    183         Message m = obtain();
    184         m.target = h;
    185         m.what = what;
    186         m.obj = obj;
    187 
    188         return m;
    189     }
    190 
    191     /**
    192      * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
    193      * <em>arg1</em>, and <em>arg2</em> members.
    194      *
    195      * @param h  The <em>target</em> value to set.
    196      * @param what  The <em>what</em> value to set.
    197      * @param arg1  The <em>arg1</em> value to set.
    198      * @param arg2  The <em>arg2</em> value to set.
    199      * @return  A Message object from the global pool.
    200      */
    201     public static Message obtain(Handler h, int what, int arg1, int arg2) {
    202         Message m = obtain();
    203         m.target = h;
    204         m.what = what;
    205         m.arg1 = arg1;
    206         m.arg2 = arg2;
    207 
    208         return m;
    209     }
    210 
    211     /**
    212      * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
    213      * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members.
    214      *
    215      * @param h  The <em>target</em> value to set.
    216      * @param what  The <em>what</em> value to set.
    217      * @param arg1  The <em>arg1</em> value to set.
    218      * @param arg2  The <em>arg2</em> value to set.
    219      * @param obj  The <em>obj</em> value to set.
    220      * @return  A Message object from the global pool.
    221      */
    222     public static Message obtain(Handler h, int what,
    223             int arg1, int arg2, Object obj) {
    224         Message m = obtain();
    225         m.target = h;
    226         m.what = what;
    227         m.arg1 = arg1;
    228         m.arg2 = arg2;
    229         m.obj = obj;
    230 
    231         return m;
    232     }
    233 
    234     /**
    235      * Return a Message instance to the global pool.  You MUST NOT touch
    236      * the Message after calling this function -- it has effectively been
    237      * freed.
    238      */
    239     public void recycle() {
    240         synchronized (mPoolSync) {
    241             if (mPoolSize < MAX_POOL_SIZE) {
    242                 clearForRecycle();
    243 
    244                 next = mPool;
    245                 mPool = this;
    246             }
    247         }
    248     }
    249 
    250     /**
    251      * Make this message like o.  Performs a shallow copy of the data field.
    252      * Does not copy the linked list fields, nor the timestamp or
    253      * target/callback of the original message.
    254      */
    255     public void copyFrom(Message o) {
    256         this.what = o.what;
    257         this.arg1 = o.arg1;
    258         this.arg2 = o.arg2;
    259         this.obj = o.obj;
    260         this.replyTo = o.replyTo;
    261 
    262         if (o.data != null) {
    263             this.data = (Bundle) o.data.clone();
    264         } else {
    265             this.data = null;
    266         }
    267     }
    268 
    269     /**
    270      * Return the targeted delivery time of this message, in milliseconds.
    271      */
    272     public long getWhen() {
    273         return when;
    274     }
    275 
    276     public void setTarget(Handler target) {
    277         this.target = target;
    278     }
    279 
    280     /**
    281      * Retrieve the a {@link android.os.Handler Handler} implementation that
    282      * will receive this message. The object must implement
    283      * {@link android.os.Handler#handleMessage(android.os.Message)
    284      * Handler.handleMessage()}. Each Handler has its own name-space for
    285      * message codes, so you do not need to
    286      * worry about yours conflicting with other handlers.
    287      */
    288     public Handler getTarget() {
    289         return target;
    290     }
    291 
    292     /**
    293      * Retrieve callback object that will execute when this message is handled.
    294      * This object must implement Runnable. This is called by
    295      * the <em>target</em> {@link Handler} that is receiving this Message to
    296      * dispatch it.  If
    297      * not set, the message will be dispatched to the receiving Handler's
    298      * {@link Handler#handleMessage(Message Handler.handleMessage())}.
    299      */
    300     public Runnable getCallback() {
    301         return callback;
    302     }
    303 
    304     /**
    305      * Obtains a Bundle of arbitrary data associated with this
    306      * event, lazily creating it if necessary. Set this value by calling
    307      * {@link #setData(Bundle)}.  Note that when transferring data across
    308      * processes via {@link Messenger}, you will need to set your ClassLoader
    309      * on the Bundle via {@link Bundle#setClassLoader(ClassLoader)
    310      * Bundle.setClassLoader()} so that it can instantiate your objects when
    311      * you retrieve them.
    312      * @see #peekData()
    313      * @see #setData(Bundle)
    314      */
    315     public Bundle getData() {
    316         if (data == null) {
    317             data = new Bundle();
    318         }
    319 
    320         return data;
    321     }
    322 
    323     /**
    324      * Like getData(), but does not lazily create the Bundle.  A null
    325      * is returned if the Bundle does not already exist.  See
    326      * {@link #getData} for further information on this.
    327      * @see #getData()
    328      * @see #setData(Bundle)
    329      */
    330     public Bundle peekData() {
    331         return data;
    332     }
    333 
    334     /**
    335      * Sets a Bundle of arbitrary data values. Use arg1 and arg1 members
    336      * as a lower cost way to send a few simple integer values, if you can.
    337      * @see #getData()
    338      * @see #peekData()
    339      */
    340     public void setData(Bundle data) {
    341         this.data = data;
    342     }
    343 
    344     /**
    345      * Sends this Message to the Handler specified by {@link #getTarget}.
    346      * Throws a null pointer exception if this field has not been set.
    347      */
    348     public void sendToTarget() {
    349         target.sendMessage(this);
    350     }
    351 
    352     /*package*/ void clearForRecycle() {
    353         what = 0;
    354         arg1 = 0;
    355         arg2 = 0;
    356         obj = null;
    357         replyTo = null;
    358         when = 0;
    359         target = null;
    360         callback = null;
    361         data = null;
    362     }
    363 
    364     /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
    365     */
    366     public Message() {
    367     }
    368 
    369     public String toString() {
    370         return toString(SystemClock.uptimeMillis());
    371     }
    372 
    373     String toString(long now) {
    374         StringBuilder   b = new StringBuilder();
    375 
    376         b.append("{ what=");
    377         b.append(what);
    378 
    379         b.append(" when=");
    380         TimeUtils.formatDuration(when-now, b);
    381 
    382         if (arg1 != 0) {
    383             b.append(" arg1=");
    384             b.append(arg1);
    385         }
    386 
    387         if (arg2 != 0) {
    388             b.append(" arg2=");
    389             b.append(arg2);
    390         }
    391 
    392         if (obj != null) {
    393             b.append(" obj=");
    394             b.append(obj);
    395         }
    396 
    397         b.append(" }");
    398 
    399         return b.toString();
    400     }
    401 
    402     public static final Parcelable.Creator<Message> CREATOR
    403             = new Parcelable.Creator<Message>() {
    404         public Message createFromParcel(Parcel source) {
    405             Message msg = Message.obtain();
    406             msg.readFromParcel(source);
    407             return msg;
    408         }
    409 
    410         public Message[] newArray(int size) {
    411             return new Message[size];
    412         }
    413     };
    414 
    415     public int describeContents() {
    416         return 0;
    417     }
    418 
    419     public void writeToParcel(Parcel dest, int flags) {
    420         if (callback != null) {
    421             throw new RuntimeException(
    422                 "Can't marshal callbacks across processes.");
    423         }
    424         dest.writeInt(what);
    425         dest.writeInt(arg1);
    426         dest.writeInt(arg2);
    427         if (obj != null) {
    428             try {
    429                 Parcelable p = (Parcelable)obj;
    430                 dest.writeInt(1);
    431                 dest.writeParcelable(p, flags);
    432             } catch (ClassCastException e) {
    433                 throw new RuntimeException(
    434                     "Can't marshal non-Parcelable objects across processes.");
    435             }
    436         } else {
    437             dest.writeInt(0);
    438         }
    439         dest.writeLong(when);
    440         dest.writeBundle(data);
    441         Messenger.writeMessengerOrNullToParcel(replyTo, dest);
    442     }
    443 
    444     private final void readFromParcel(Parcel source) {
    445         what = source.readInt();
    446         arg1 = source.readInt();
    447         arg2 = source.readInt();
    448         if (source.readInt() != 0) {
    449             obj = source.readParcelable(getClass().getClassLoader());
    450         }
    451         when = source.readLong();
    452         data = source.readBundle();
    453         replyTo = Messenger.readMessengerOrNullFromParcel(source);
    454     }
    455 }
    456 
    457