|  | /* | 
|  | * Copyright (C) 2006 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | package android.os; | 
|  |  | 
|  | import android.compat.annotation.UnsupportedAppUsage; | 
|  | import android.util.TimeUtils; | 
|  | import android.util.proto.ProtoOutputStream; | 
|  |  | 
|  | import com.android.internal.annotations.VisibleForTesting; | 
|  |  | 
|  | /** | 
|  | * | 
|  | * Defines a message containing a description and arbitrary data object that can be | 
|  | * sent to a {@link Handler}.  This object contains two extra int fields and an | 
|  | * extra object field that allow you to not do allocations in many cases. | 
|  | * | 
|  | * <p class="note">While the constructor of Message is public, the best way to get | 
|  | * one of these is to call {@link #obtain Message.obtain()} or one of the | 
|  | * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull | 
|  | * them from a pool of recycled objects.</p> | 
|  | */ | 
|  | public final class Message implements Parcelable { | 
|  | /** | 
|  | * User-defined message code so that the recipient can identify | 
|  | * what this message is about. Each {@link Handler} has its own name-space | 
|  | * for message codes, so you do not need to worry about yours conflicting | 
|  | * with other handlers. | 
|  | */ | 
|  | public int what; | 
|  |  | 
|  | /** | 
|  | * arg1 and arg2 are lower-cost alternatives to using | 
|  | * {@link #setData(Bundle) setData()} if you only need to store a | 
|  | * few integer values. | 
|  | */ | 
|  | public int arg1; | 
|  |  | 
|  | /** | 
|  | * arg1 and arg2 are lower-cost alternatives to using | 
|  | * {@link #setData(Bundle) setData()} if you only need to store a | 
|  | * few integer values. | 
|  | */ | 
|  | public int arg2; | 
|  |  | 
|  | /** | 
|  | * An arbitrary object to send to the recipient.  When using | 
|  | * {@link Messenger} to send the message across processes this can only | 
|  | * be non-null if it contains a Parcelable of a framework class (not one | 
|  | * implemented by the application).   For other data transfer use | 
|  | * {@link #setData}. | 
|  | * | 
|  | * <p>Note that Parcelable objects here are not supported prior to | 
|  | * the {@link android.os.Build.VERSION_CODES#FROYO} release. | 
|  | */ | 
|  | public Object obj; | 
|  |  | 
|  | /** | 
|  | * Optional Messenger where replies to this message can be sent.  The | 
|  | * semantics of exactly how this is used are up to the sender and | 
|  | * receiver. | 
|  | */ | 
|  | public Messenger replyTo; | 
|  |  | 
|  | /** | 
|  | * Indicates that the uid is not set; | 
|  | * | 
|  | * @hide Only for use within the system server. | 
|  | */ | 
|  | public static final int UID_NONE = -1; | 
|  |  | 
|  | /** | 
|  | * Optional field indicating the uid that sent the message.  This is | 
|  | * only valid for messages posted by a {@link Messenger}; otherwise, | 
|  | * it will be -1. | 
|  | */ | 
|  | public int sendingUid = UID_NONE; | 
|  |  | 
|  | /** | 
|  | * Optional field indicating the uid that caused this message to be enqueued. | 
|  | * | 
|  | * @hide Only for use within the system server. | 
|  | */ | 
|  | public int workSourceUid = UID_NONE; | 
|  |  | 
|  | /** If set message is in use. | 
|  | * This flag is set when the message is enqueued and remains set while it | 
|  | * is delivered and afterwards when it is recycled.  The flag is only cleared | 
|  | * when a new message is created or obtained since that is the only time that | 
|  | * applications are allowed to modify the contents of the message. | 
|  | * | 
|  | * It is an error to attempt to enqueue or recycle a message that is already in use. | 
|  | */ | 
|  | /*package*/ static final int FLAG_IN_USE = 1 << 0; | 
|  |  | 
|  | /** If set message is asynchronous */ | 
|  | /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1; | 
|  |  | 
|  | /** Flags to clear in the copyFrom method */ | 
|  | /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE; | 
|  |  | 
|  | @UnsupportedAppUsage | 
|  | /*package*/ int flags; | 
|  |  | 
|  | /** | 
|  | * The targeted delivery time of this message. The time-base is | 
|  | * {@link SystemClock#uptimeMillis}. | 
|  | * @hide Only for use within the tests. | 
|  | */ | 
|  | @UnsupportedAppUsage | 
|  | @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) | 
|  | public long when; | 
|  |  | 
|  | /*package*/ Bundle data; | 
|  |  | 
|  | @UnsupportedAppUsage | 
|  | /*package*/ Handler target; | 
|  |  | 
|  | @UnsupportedAppUsage | 
|  | /*package*/ Runnable callback; | 
|  |  | 
|  | // sometimes we store linked lists of these things | 
|  | @UnsupportedAppUsage | 
|  | /*package*/ Message next; | 
|  |  | 
|  |  | 
|  | /** @hide */ | 
|  | public static final Object sPoolSync = new Object(); | 
|  | private static Message sPool; | 
|  | private static int sPoolSize = 0; | 
|  |  | 
|  | private static final int MAX_POOL_SIZE = 50; | 
|  |  | 
|  | private static boolean gCheckRecycle = true; | 
|  |  | 
|  | /** | 
|  | * Return a new Message instance from the global pool. Allows us to | 
|  | * avoid allocating new objects in many cases. | 
|  | */ | 
|  | public static Message obtain() { | 
|  | synchronized (sPoolSync) { | 
|  | if (sPool != null) { | 
|  | Message m = sPool; | 
|  | sPool = m.next; | 
|  | m.next = null; | 
|  | m.flags = 0; // clear in-use flag | 
|  | sPoolSize--; | 
|  | return m; | 
|  | } | 
|  | } | 
|  | return new Message(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Same as {@link #obtain()}, but copies the values of an existing | 
|  | * message (including its target) into the new one. | 
|  | * @param orig Original message to copy. | 
|  | * @return A Message object from the global pool. | 
|  | */ | 
|  | public static Message obtain(Message orig) { | 
|  | Message m = obtain(); | 
|  | m.what = orig.what; | 
|  | m.arg1 = orig.arg1; | 
|  | m.arg2 = orig.arg2; | 
|  | m.obj = orig.obj; | 
|  | m.replyTo = orig.replyTo; | 
|  | m.sendingUid = orig.sendingUid; | 
|  | m.workSourceUid = orig.workSourceUid; | 
|  | if (orig.data != null) { | 
|  | m.data = new Bundle(orig.data); | 
|  | } | 
|  | m.target = orig.target; | 
|  | m.callback = orig.callback; | 
|  |  | 
|  | return m; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned. | 
|  | * @param h  Handler to assign to the returned Message object's <em>target</em> member. | 
|  | * @return A Message object from the global pool. | 
|  | */ | 
|  | public static Message obtain(Handler h) { | 
|  | Message m = obtain(); | 
|  | m.target = h; | 
|  |  | 
|  | return m; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on | 
|  | * the Message that is returned. | 
|  | * @param h  Handler to assign to the returned Message object's <em>target</em> member. | 
|  | * @param callback Runnable that will execute when the message is handled. | 
|  | * @return A Message object from the global pool. | 
|  | */ | 
|  | public static Message obtain(Handler h, Runnable callback) { | 
|  | Message m = obtain(); | 
|  | m.target = h; | 
|  | m.callback = callback; | 
|  |  | 
|  | return m; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Same as {@link #obtain()}, but sets the values for both <em>target</em> and | 
|  | * <em>what</em> members on the Message. | 
|  | * @param h  Value to assign to the <em>target</em> member. | 
|  | * @param what  Value to assign to the <em>what</em> member. | 
|  | * @return A Message object from the global pool. | 
|  | */ | 
|  | public static Message obtain(Handler h, int what) { | 
|  | Message m = obtain(); | 
|  | m.target = h; | 
|  | m.what = what; | 
|  |  | 
|  | return m; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em> | 
|  | * members. | 
|  | * @param h  The <em>target</em> value to set. | 
|  | * @param what  The <em>what</em> value to set. | 
|  | * @param obj  The <em>object</em> method to set. | 
|  | * @return  A Message object from the global pool. | 
|  | */ | 
|  | public static Message obtain(Handler h, int what, Object obj) { | 
|  | Message m = obtain(); | 
|  | m.target = h; | 
|  | m.what = what; | 
|  | m.obj = obj; | 
|  |  | 
|  | return m; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, | 
|  | * <em>arg1</em>, and <em>arg2</em> members. | 
|  | * | 
|  | * @param h  The <em>target</em> value to set. | 
|  | * @param what  The <em>what</em> value to set. | 
|  | * @param arg1  The <em>arg1</em> value to set. | 
|  | * @param arg2  The <em>arg2</em> value to set. | 
|  | * @return  A Message object from the global pool. | 
|  | */ | 
|  | public static Message obtain(Handler h, int what, int arg1, int arg2) { | 
|  | Message m = obtain(); | 
|  | m.target = h; | 
|  | m.what = what; | 
|  | m.arg1 = arg1; | 
|  | m.arg2 = arg2; | 
|  |  | 
|  | return m; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, | 
|  | * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members. | 
|  | * | 
|  | * @param h  The <em>target</em> value to set. | 
|  | * @param what  The <em>what</em> value to set. | 
|  | * @param arg1  The <em>arg1</em> value to set. | 
|  | * @param arg2  The <em>arg2</em> value to set. | 
|  | * @param obj  The <em>obj</em> value to set. | 
|  | * @return  A Message object from the global pool. | 
|  | */ | 
|  | public static Message obtain(Handler h, int what, | 
|  | int arg1, int arg2, Object obj) { | 
|  | Message m = obtain(); | 
|  | m.target = h; | 
|  | m.what = what; | 
|  | m.arg1 = arg1; | 
|  | m.arg2 = arg2; | 
|  | m.obj = obj; | 
|  |  | 
|  | return m; | 
|  | } | 
|  |  | 
|  | /** @hide */ | 
|  | public static void updateCheckRecycle(int targetSdkVersion) { | 
|  | if (targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) { | 
|  | gCheckRecycle = false; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Return a Message instance to the global pool. | 
|  | * <p> | 
|  | * You MUST NOT touch the Message after calling this function because it has | 
|  | * effectively been freed.  It is an error to recycle a message that is currently | 
|  | * enqueued or that is in the process of being delivered to a Handler. | 
|  | * </p> | 
|  | */ | 
|  | public void recycle() { | 
|  | if (isInUse()) { | 
|  | if (gCheckRecycle) { | 
|  | throw new IllegalStateException("This message cannot be recycled because it " | 
|  | + "is still in use."); | 
|  | } | 
|  | return; | 
|  | } | 
|  | recycleUnchecked(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Recycles a Message that may be in-use. | 
|  | * Used internally by the MessageQueue and Looper when disposing of queued Messages. | 
|  | */ | 
|  | @UnsupportedAppUsage | 
|  | void recycleUnchecked() { | 
|  | // Mark the message as in use while it remains in the recycled object pool. | 
|  | // Clear out all other details. | 
|  | flags = FLAG_IN_USE; | 
|  | what = 0; | 
|  | arg1 = 0; | 
|  | arg2 = 0; | 
|  | obj = null; | 
|  | replyTo = null; | 
|  | sendingUid = UID_NONE; | 
|  | workSourceUid = UID_NONE; | 
|  | when = 0; | 
|  | target = null; | 
|  | callback = null; | 
|  | data = null; | 
|  |  | 
|  | synchronized (sPoolSync) { | 
|  | if (sPoolSize < MAX_POOL_SIZE) { | 
|  | next = sPool; | 
|  | sPool = this; | 
|  | sPoolSize++; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Make this message like o.  Performs a shallow copy of the data field. | 
|  | * Does not copy the linked list fields, nor the timestamp or | 
|  | * target/callback of the original message. | 
|  | */ | 
|  | public void copyFrom(Message o) { | 
|  | this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM; | 
|  | this.what = o.what; | 
|  | this.arg1 = o.arg1; | 
|  | this.arg2 = o.arg2; | 
|  | this.obj = o.obj; | 
|  | this.replyTo = o.replyTo; | 
|  | this.sendingUid = o.sendingUid; | 
|  | this.workSourceUid = o.workSourceUid; | 
|  |  | 
|  | if (o.data != null) { | 
|  | this.data = (Bundle) o.data.clone(); | 
|  | } else { | 
|  | this.data = null; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Return the targeted delivery time of this message, in milliseconds. | 
|  | */ | 
|  | public long getWhen() { | 
|  | return when; | 
|  | } | 
|  |  | 
|  | public void setTarget(Handler target) { | 
|  | this.target = target; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Retrieve the {@link android.os.Handler Handler} implementation that | 
|  | * will receive this message. The object must implement | 
|  | * {@link android.os.Handler#handleMessage(android.os.Message) | 
|  | * Handler.handleMessage()}. Each Handler has its own name-space for | 
|  | * message codes, so you do not need to | 
|  | * worry about yours conflicting with other handlers. | 
|  | */ | 
|  | public Handler getTarget() { | 
|  | return target; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Retrieve callback object that will execute when this message is handled. | 
|  | * This object must implement Runnable. This is called by | 
|  | * the <em>target</em> {@link Handler} that is receiving this Message to | 
|  | * dispatch it.  If | 
|  | * not set, the message will be dispatched to the receiving Handler's | 
|  | * {@link Handler#handleMessage(Message)}. | 
|  | */ | 
|  | public Runnable getCallback() { | 
|  | return callback; | 
|  | } | 
|  |  | 
|  | /** @hide */ | 
|  | @UnsupportedAppUsage | 
|  | public Message setCallback(Runnable r) { | 
|  | callback = r; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Obtains a Bundle of arbitrary data associated with this | 
|  | * event, lazily creating it if necessary. Set this value by calling | 
|  | * {@link #setData(Bundle)}.  Note that when transferring data across | 
|  | * processes via {@link Messenger}, you will need to set your ClassLoader | 
|  | * on the Bundle via {@link Bundle#setClassLoader(ClassLoader) | 
|  | * Bundle.setClassLoader()} so that it can instantiate your objects when | 
|  | * you retrieve them. | 
|  | * @see #peekData() | 
|  | * @see #setData(Bundle) | 
|  | */ | 
|  | public Bundle getData() { | 
|  | if (data == null) { | 
|  | data = new Bundle(); | 
|  | } | 
|  |  | 
|  | return data; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Like getData(), but does not lazily create the Bundle.  A null | 
|  | * is returned if the Bundle does not already exist.  See | 
|  | * {@link #getData} for further information on this. | 
|  | * @see #getData() | 
|  | * @see #setData(Bundle) | 
|  | */ | 
|  | public Bundle peekData() { | 
|  | return data; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets a Bundle of arbitrary data values. Use arg1 and arg2 members | 
|  | * as a lower cost way to send a few simple integer values, if you can. | 
|  | * @see #getData() | 
|  | * @see #peekData() | 
|  | */ | 
|  | public void setData(Bundle data) { | 
|  | this.data = data; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Chainable setter for {@link #what} | 
|  | * | 
|  | * @hide | 
|  | */ | 
|  | public Message setWhat(int what) { | 
|  | this.what = what; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sends this Message to the Handler specified by {@link #getTarget}. | 
|  | * Throws a null pointer exception if this field has not been set. | 
|  | */ | 
|  | public void sendToTarget() { | 
|  | target.sendMessage(this); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns true if the message is asynchronous, meaning that it is not | 
|  | * subject to {@link Looper} synchronization barriers. | 
|  | * | 
|  | * @return True if the message is asynchronous. | 
|  | * | 
|  | * @see #setAsynchronous(boolean) | 
|  | */ | 
|  | public boolean isAsynchronous() { | 
|  | return (flags & FLAG_ASYNCHRONOUS) != 0; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets whether the message is asynchronous, meaning that it is not | 
|  | * subject to {@link Looper} synchronization barriers. | 
|  | * <p> | 
|  | * Certain operations, such as view invalidation, may introduce synchronization | 
|  | * barriers into the {@link Looper}'s message queue to prevent subsequent messages | 
|  | * from being delivered until some condition is met.  In the case of view invalidation, | 
|  | * messages which are posted after a call to {@link android.view.View#invalidate} | 
|  | * are suspended by means of a synchronization barrier until the next frame is | 
|  | * ready to be drawn.  The synchronization barrier ensures that the invalidation | 
|  | * request is completely handled before resuming. | 
|  | * </p><p> | 
|  | * Asynchronous messages are exempt from synchronization barriers.  They typically | 
|  | * represent interrupts, input events, and other signals that must be handled independently | 
|  | * even while other work has been suspended. | 
|  | * </p><p> | 
|  | * Note that asynchronous messages may be delivered out of order with respect to | 
|  | * synchronous messages although they are always delivered in order among themselves. | 
|  | * If the relative order of these messages matters then they probably should not be | 
|  | * asynchronous in the first place.  Use with caution. | 
|  | * </p> | 
|  | * | 
|  | * @param async True if the message is asynchronous. | 
|  | * | 
|  | * @see #isAsynchronous() | 
|  | */ | 
|  | public void setAsynchronous(boolean async) { | 
|  | if (async) { | 
|  | flags |= FLAG_ASYNCHRONOUS; | 
|  | } else { | 
|  | flags &= ~FLAG_ASYNCHRONOUS; | 
|  | } | 
|  | } | 
|  |  | 
|  | /*package*/ boolean isInUse() { | 
|  | return ((flags & FLAG_IN_USE) == FLAG_IN_USE); | 
|  | } | 
|  |  | 
|  | @UnsupportedAppUsage | 
|  | /*package*/ void markInUse() { | 
|  | flags |= FLAG_IN_USE; | 
|  | } | 
|  |  | 
|  | /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}). | 
|  | */ | 
|  | public Message() { | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public String toString() { | 
|  | return toString(SystemClock.uptimeMillis()); | 
|  | } | 
|  |  | 
|  | @UnsupportedAppUsage | 
|  | String toString(long now) { | 
|  | StringBuilder b = new StringBuilder(); | 
|  | b.append("{ when="); | 
|  | TimeUtils.formatDuration(when - now, b); | 
|  |  | 
|  | if (target != null) { | 
|  | if (callback != null) { | 
|  | b.append(" callback="); | 
|  | b.append(callback.getClass().getName()); | 
|  | } else { | 
|  | b.append(" what="); | 
|  | b.append(what); | 
|  | } | 
|  |  | 
|  | if (arg1 != 0) { | 
|  | b.append(" arg1="); | 
|  | b.append(arg1); | 
|  | } | 
|  |  | 
|  | if (arg2 != 0) { | 
|  | b.append(" arg2="); | 
|  | b.append(arg2); | 
|  | } | 
|  |  | 
|  | if (obj != null) { | 
|  | b.append(" obj="); | 
|  | b.append(obj); | 
|  | } | 
|  |  | 
|  | b.append(" target="); | 
|  | b.append(target.getClass().getName()); | 
|  | } else { | 
|  | b.append(" barrier="); | 
|  | b.append(arg1); | 
|  | } | 
|  |  | 
|  | b.append(" }"); | 
|  | return b.toString(); | 
|  | } | 
|  |  | 
|  | void dumpDebug(ProtoOutputStream proto, long fieldId) { | 
|  | final long messageToken = proto.start(fieldId); | 
|  | proto.write(MessageProto.WHEN, when); | 
|  |  | 
|  | if (target != null) { | 
|  | if (callback != null) { | 
|  | proto.write(MessageProto.CALLBACK, callback.getClass().getName()); | 
|  | } else { | 
|  | proto.write(MessageProto.WHAT, what); | 
|  | } | 
|  |  | 
|  | if (arg1 != 0) { | 
|  | proto.write(MessageProto.ARG1, arg1); | 
|  | } | 
|  |  | 
|  | if (arg2 != 0) { | 
|  | proto.write(MessageProto.ARG2, arg2); | 
|  | } | 
|  |  | 
|  | if (obj != null) { | 
|  | proto.write(MessageProto.OBJ, obj.toString()); | 
|  | } | 
|  |  | 
|  | proto.write(MessageProto.TARGET, target.getClass().getName()); | 
|  | } else { | 
|  | proto.write(MessageProto.BARRIER, arg1); | 
|  | } | 
|  |  | 
|  | proto.end(messageToken); | 
|  | } | 
|  |  | 
|  | public static final @android.annotation.NonNull Parcelable.Creator<Message> CREATOR | 
|  | = new Parcelable.Creator<Message>() { | 
|  | public Message createFromParcel(Parcel source) { | 
|  | Message msg = Message.obtain(); | 
|  | msg.readFromParcel(source); | 
|  | return msg; | 
|  | } | 
|  |  | 
|  | public Message[] newArray(int size) { | 
|  | return new Message[size]; | 
|  | } | 
|  | }; | 
|  |  | 
|  | public int describeContents() { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | public void writeToParcel(Parcel dest, int flags) { | 
|  | if (callback != null) { | 
|  | throw new RuntimeException( | 
|  | "Can't marshal callbacks across processes."); | 
|  | } | 
|  | dest.writeInt(what); | 
|  | dest.writeInt(arg1); | 
|  | dest.writeInt(arg2); | 
|  | if (obj != null) { | 
|  | try { | 
|  | Parcelable p = (Parcelable)obj; | 
|  | dest.writeInt(1); | 
|  | dest.writeParcelable(p, flags); | 
|  | } catch (ClassCastException e) { | 
|  | throw new RuntimeException( | 
|  | "Can't marshal non-Parcelable objects across processes."); | 
|  | } | 
|  | } else { | 
|  | dest.writeInt(0); | 
|  | } | 
|  | dest.writeLong(when); | 
|  | dest.writeBundle(data); | 
|  | Messenger.writeMessengerOrNullToParcel(replyTo, dest); | 
|  | dest.writeInt(sendingUid); | 
|  | dest.writeInt(workSourceUid); | 
|  | } | 
|  |  | 
|  | private void readFromParcel(Parcel source) { | 
|  | what = source.readInt(); | 
|  | arg1 = source.readInt(); | 
|  | arg2 = source.readInt(); | 
|  | if (source.readInt() != 0) { | 
|  | obj = source.readParcelable(getClass().getClassLoader()); | 
|  | } | 
|  | when = source.readLong(); | 
|  | data = source.readBundle(); | 
|  | replyTo = Messenger.readMessengerOrNullFromParcel(source); | 
|  | sendingUid = source.readInt(); | 
|  | workSourceUid = source.readInt(); | 
|  | } | 
|  | } |