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