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.text.TextUtils; 20 import android.util.Log; 21 import android.util.SparseArray; 22 import android.util.SparseBooleanArray; 23 24 import java.io.ByteArrayInputStream; 25 import java.io.ByteArrayOutputStream; 26 import java.io.FileDescriptor; 27 import java.io.FileNotFoundException; 28 import java.io.IOException; 29 import java.io.ObjectInputStream; 30 import java.io.ObjectOutputStream; 31 import java.io.Serializable; 32 import java.lang.reflect.Field; 33 import java.util.ArrayList; 34 import java.util.Arrays; 35 import java.util.HashMap; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.Set; 39 40 /** 41 * Container for a message (data and object references) that can 42 * be sent through an IBinder. A Parcel can contain both flattened data 43 * that will be unflattened on the other side of the IPC (using the various 44 * methods here for writing specific types, or the general 45 * {@link Parcelable} interface), and references to live {@link IBinder} 46 * objects that will result in the other side receiving a proxy IBinder 47 * connected with the original IBinder in the Parcel. 48 * 49 * <p class="note">Parcel is <strong>not</strong> a general-purpose 50 * serialization mechanism. This class (and the corresponding 51 * {@link Parcelable} API for placing arbitrary objects into a Parcel) is 52 * designed as a high-performance IPC transport. As such, it is not 53 * appropriate to place any Parcel data in to persistent storage: changes 54 * in the underlying implementation of any of the data in the Parcel can 55 * render older data unreadable.</p> 56 * 57 * <p>The bulk of the Parcel API revolves around reading and writing data 58 * of various types. There are six major classes of such functions available.</p> 59 * 60 * <h3>Primitives</h3> 61 * 62 * <p>The most basic data functions are for writing and reading primitive 63 * data types: {@link #writeByte}, {@link #readByte}, {@link #writeDouble}, 64 * {@link #readDouble}, {@link #writeFloat}, {@link #readFloat}, {@link #writeInt}, 65 * {@link #readInt}, {@link #writeLong}, {@link #readLong}, 66 * {@link #writeString}, {@link #readString}. Most other 67 * data operations are built on top of these. The given data is written and 68 * read using the endianess of the host CPU.</p> 69 * 70 * <h3>Primitive Arrays</h3> 71 * 72 * <p>There are a variety of methods for reading and writing raw arrays 73 * of primitive objects, which generally result in writing a 4-byte length 74 * followed by the primitive data items. The methods for reading can either 75 * read the data into an existing array, or create and return a new array. 76 * These available types are:</p> 77 * 78 * <ul> 79 * <li> {@link #writeBooleanArray(boolean[])}, 80 * {@link #readBooleanArray(boolean[])}, {@link #createBooleanArray()} 81 * <li> {@link #writeByteArray(byte[])}, 82 * {@link #writeByteArray(byte[], int, int)}, {@link #readByteArray(byte[])}, 83 * {@link #createByteArray()} 84 * <li> {@link #writeCharArray(char[])}, {@link #readCharArray(char[])}, 85 * {@link #createCharArray()} 86 * <li> {@link #writeDoubleArray(double[])}, {@link #readDoubleArray(double[])}, 87 * {@link #createDoubleArray()} 88 * <li> {@link #writeFloatArray(float[])}, {@link #readFloatArray(float[])}, 89 * {@link #createFloatArray()} 90 * <li> {@link #writeIntArray(int[])}, {@link #readIntArray(int[])}, 91 * {@link #createIntArray()} 92 * <li> {@link #writeLongArray(long[])}, {@link #readLongArray(long[])}, 93 * {@link #createLongArray()} 94 * <li> {@link #writeStringArray(String[])}, {@link #readStringArray(String[])}, 95 * {@link #createStringArray()}. 96 * <li> {@link #writeSparseBooleanArray(SparseBooleanArray)}, 97 * {@link #readSparseBooleanArray()}. 98 * </ul> 99 * 100 * <h3>Parcelables</h3> 101 * 102 * <p>The {@link Parcelable} protocol provides an extremely efficient (but 103 * low-level) protocol for objects to write and read themselves from Parcels. 104 * You can use the direct methods {@link #writeParcelable(Parcelable, int)} 105 * and {@link #readParcelable(ClassLoader)} or 106 * {@link #writeParcelableArray} and 107 * {@link #readParcelableArray(ClassLoader)} to write or read. These 108 * methods write both the class type and its data to the Parcel, allowing 109 * that class to be reconstructed from the appropriate class loader when 110 * later reading.</p> 111 * 112 * <p>There are also some methods that provide a more efficient way to work 113 * with Parcelables: {@link #writeTypedArray}, 114 * {@link #writeTypedList(List)}, 115 * {@link #readTypedArray} and {@link #readTypedList}. These methods 116 * do not write the class information of the original object: instead, the 117 * caller of the read function must know what type to expect and pass in the 118 * appropriate {@link Parcelable.Creator Parcelable.Creator} instead to 119 * properly construct the new object and read its data. (To more efficient 120 * write and read a single Parceable object, you can directly call 121 * {@link Parcelable#writeToParcel Parcelable.writeToParcel} and 122 * {@link Parcelable.Creator#createFromParcel Parcelable.Creator.createFromParcel} 123 * yourself.)</p> 124 * 125 * <h3>Bundles</h3> 126 * 127 * <p>A special type-safe container, called {@link Bundle}, is available 128 * for key/value maps of heterogeneous values. This has many optimizations 129 * for improved performance when reading and writing data, and its type-safe 130 * API avoids difficult to debug type errors when finally marshalling the 131 * data contents into a Parcel. The methods to use are 132 * {@link #writeBundle(Bundle)}, {@link #readBundle()}, and 133 * {@link #readBundle(ClassLoader)}. 134 * 135 * <h3>Active Objects</h3> 136 * 137 * <p>An unusual feature of Parcel is the ability to read and write active 138 * objects. For these objects the actual contents of the object is not 139 * written, rather a special token referencing the object is written. When 140 * reading the object back from the Parcel, you do not get a new instance of 141 * the object, but rather a handle that operates on the exact same object that 142 * was originally written. There are two forms of active objects available.</p> 143 * 144 * <p>{@link Binder} objects are a core facility of Android's general cross-process 145 * communication system. The {@link IBinder} interface describes an abstract 146 * protocol with a Binder object. Any such interface can be written in to 147 * a Parcel, and upon reading you will receive either the original object 148 * implementing that interface or a special proxy implementation 149 * that communicates calls back to the original object. The methods to use are 150 * {@link #writeStrongBinder(IBinder)}, 151 * {@link #writeStrongInterface(IInterface)}, {@link #readStrongBinder()}, 152 * {@link #writeBinderArray(IBinder[])}, {@link #readBinderArray(IBinder[])}, 153 * {@link #createBinderArray()}, 154 * {@link #writeBinderList(List)}, {@link #readBinderList(List)}, 155 * {@link #createBinderArrayList()}.</p> 156 * 157 * <p>FileDescriptor objects, representing raw Linux file descriptor identifiers, 158 * can be written and {@link ParcelFileDescriptor} objects returned to operate 159 * on the original file descriptor. The returned file descriptor is a dup 160 * of the original file descriptor: the object and fd is different, but 161 * operating on the same underlying file stream, with the same position, etc. 162 * The methods to use are {@link #writeFileDescriptor(FileDescriptor)}, 163 * {@link #readFileDescriptor()}. 164 * 165 * <h3>Untyped Containers</h3> 166 * 167 * <p>A final class of methods are for writing and reading standard Java 168 * containers of arbitrary types. These all revolve around the 169 * {@link #writeValue(Object)} and {@link #readValue(ClassLoader)} methods 170 * which define the types of objects allowed. The container methods are 171 * {@link #writeArray(Object[])}, {@link #readArray(ClassLoader)}, 172 * {@link #writeList(List)}, {@link #readList(List, ClassLoader)}, 173 * {@link #readArrayList(ClassLoader)}, 174 * {@link #writeMap(Map)}, {@link #readMap(Map, ClassLoader)}, 175 * {@link #writeSparseArray(SparseArray)}, 176 * {@link #readSparseArray(ClassLoader)}. 177 */ 178 public final class Parcel { 179 private static final boolean DEBUG_RECYCLE = false; 180 private static final String TAG = "Parcel"; 181 182 @SuppressWarnings({"UnusedDeclaration"}) 183 private int mObject; // used by native code 184 @SuppressWarnings({"UnusedDeclaration"}) 185 private int mOwnObject; // used by native code 186 private RuntimeException mStack; 187 188 private static final int POOL_SIZE = 6; 189 private static final Parcel[] sOwnedPool = new Parcel[POOL_SIZE]; 190 private static final Parcel[] sHolderPool = new Parcel[POOL_SIZE]; 191 192 private static final int VAL_NULL = -1; 193 private static final int VAL_STRING = 0; 194 private static final int VAL_INTEGER = 1; 195 private static final int VAL_MAP = 2; 196 private static final int VAL_BUNDLE = 3; 197 private static final int VAL_PARCELABLE = 4; 198 private static final int VAL_SHORT = 5; 199 private static final int VAL_LONG = 6; 200 private static final int VAL_FLOAT = 7; 201 private static final int VAL_DOUBLE = 8; 202 private static final int VAL_BOOLEAN = 9; 203 private static final int VAL_CHARSEQUENCE = 10; 204 private static final int VAL_LIST = 11; 205 private static final int VAL_SPARSEARRAY = 12; 206 private static final int VAL_BYTEARRAY = 13; 207 private static final int VAL_STRINGARRAY = 14; 208 private static final int VAL_IBINDER = 15; 209 private static final int VAL_PARCELABLEARRAY = 16; 210 private static final int VAL_OBJECTARRAY = 17; 211 private static final int VAL_INTARRAY = 18; 212 private static final int VAL_LONGARRAY = 19; 213 private static final int VAL_BYTE = 20; 214 private static final int VAL_SERIALIZABLE = 21; 215 private static final int VAL_SPARSEBOOLEANARRAY = 22; 216 private static final int VAL_BOOLEANARRAY = 23; 217 private static final int VAL_CHARSEQUENCEARRAY = 24; 218 219 // The initial int32 in a Binder call's reply Parcel header: 220 private static final int EX_SECURITY = -1; 221 private static final int EX_BAD_PARCELABLE = -2; 222 private static final int EX_ILLEGAL_ARGUMENT = -3; 223 private static final int EX_NULL_POINTER = -4; 224 private static final int EX_ILLEGAL_STATE = -5; 225 private static final int EX_HAS_REPLY_HEADER = -128; // special; see below 226 227 public final static Parcelable.Creator<String> STRING_CREATOR 228 = new Parcelable.Creator<String>() { 229 public String createFromParcel(Parcel source) { 230 return source.readString(); 231 } 232 public String[] newArray(int size) { 233 return new String[size]; 234 } 235 }; 236 237 /** 238 * Retrieve a new Parcel object from the pool. 239 */ obtain()240 public static Parcel obtain() { 241 final Parcel[] pool = sOwnedPool; 242 synchronized (pool) { 243 Parcel p; 244 for (int i=0; i<POOL_SIZE; i++) { 245 p = pool[i]; 246 if (p != null) { 247 pool[i] = null; 248 if (DEBUG_RECYCLE) { 249 p.mStack = new RuntimeException(); 250 } 251 return p; 252 } 253 } 254 } 255 return new Parcel(0); 256 } 257 258 /** 259 * Put a Parcel object back into the pool. You must not touch 260 * the object after this call. 261 */ recycle()262 public final void recycle() { 263 if (DEBUG_RECYCLE) mStack = null; 264 freeBuffer(); 265 final Parcel[] pool = mOwnObject != 0 ? sOwnedPool : sHolderPool; 266 synchronized (pool) { 267 for (int i=0; i<POOL_SIZE; i++) { 268 if (pool[i] == null) { 269 pool[i] = this; 270 return; 271 } 272 } 273 } 274 } 275 276 /** 277 * Returns the total amount of data contained in the parcel. 278 */ dataSize()279 public final native int dataSize(); 280 281 /** 282 * Returns the amount of data remaining to be read from the 283 * parcel. That is, {@link #dataSize}-{@link #dataPosition}. 284 */ dataAvail()285 public final native int dataAvail(); 286 287 /** 288 * Returns the current position in the parcel data. Never 289 * more than {@link #dataSize}. 290 */ dataPosition()291 public final native int dataPosition(); 292 293 /** 294 * Returns the total amount of space in the parcel. This is always 295 * >= {@link #dataSize}. The difference between it and dataSize() is the 296 * amount of room left until the parcel needs to re-allocate its 297 * data buffer. 298 */ dataCapacity()299 public final native int dataCapacity(); 300 301 /** 302 * Change the amount of data in the parcel. Can be either smaller or 303 * larger than the current size. If larger than the current capacity, 304 * more memory will be allocated. 305 * 306 * @param size The new number of bytes in the Parcel. 307 */ setDataSize(int size)308 public final native void setDataSize(int size); 309 310 /** 311 * Move the current read/write position in the parcel. 312 * @param pos New offset in the parcel; must be between 0 and 313 * {@link #dataSize}. 314 */ setDataPosition(int pos)315 public final native void setDataPosition(int pos); 316 317 /** 318 * Change the capacity (current available space) of the parcel. 319 * 320 * @param size The new capacity of the parcel, in bytes. Can not be 321 * less than {@link #dataSize} -- that is, you can not drop existing data 322 * with this method. 323 */ setDataCapacity(int size)324 public final native void setDataCapacity(int size); 325 326 /** @hide */ pushAllowFds(boolean allowFds)327 public final native boolean pushAllowFds(boolean allowFds); 328 329 /** @hide */ restoreAllowFds(boolean lastValue)330 public final native void restoreAllowFds(boolean lastValue); 331 332 /** 333 * Returns the raw bytes of the parcel. 334 * 335 * <p class="note">The data you retrieve here <strong>must not</strong> 336 * be placed in any kind of persistent storage (on local disk, across 337 * a network, etc). For that, you should use standard serialization 338 * or another kind of general serialization mechanism. The Parcel 339 * marshalled representation is highly optimized for local IPC, and as 340 * such does not attempt to maintain compatibility with data created 341 * in different versions of the platform. 342 */ marshall()343 public final native byte[] marshall(); 344 345 /** 346 * Set the bytes in data to be the raw bytes of this Parcel. 347 */ unmarshall(byte[] data, int offest, int length)348 public final native void unmarshall(byte[] data, int offest, int length); 349 appendFrom(Parcel parcel, int offset, int length)350 public final native void appendFrom(Parcel parcel, int offset, int length); 351 352 /** 353 * Report whether the parcel contains any marshalled file descriptors. 354 */ hasFileDescriptors()355 public final native boolean hasFileDescriptors(); 356 357 /** 358 * Store or read an IBinder interface token in the parcel at the current 359 * {@link #dataPosition}. This is used to validate that the marshalled 360 * transaction is intended for the target interface. 361 */ writeInterfaceToken(String interfaceName)362 public final native void writeInterfaceToken(String interfaceName); enforceInterface(String interfaceName)363 public final native void enforceInterface(String interfaceName); 364 365 /** 366 * Write a byte array into the parcel at the current {@link #dataPosition}, 367 * growing {@link #dataCapacity} if needed. 368 * @param b Bytes to place into the parcel. 369 */ writeByteArray(byte[] b)370 public final void writeByteArray(byte[] b) { 371 writeByteArray(b, 0, (b != null) ? b.length : 0); 372 } 373 374 /** 375 * Write an byte array into the parcel at the current {@link #dataPosition}, 376 * growing {@link #dataCapacity} if needed. 377 * @param b Bytes to place into the parcel. 378 * @param offset Index of first byte to be written. 379 * @param len Number of bytes to write. 380 */ writeByteArray(byte[] b, int offset, int len)381 public final void writeByteArray(byte[] b, int offset, int len) { 382 if (b == null) { 383 writeInt(-1); 384 return; 385 } 386 Arrays.checkOffsetAndCount(b.length, offset, len); 387 writeNative(b, offset, len); 388 } 389 writeNative(byte[] b, int offset, int len)390 private native void writeNative(byte[] b, int offset, int len); 391 392 /** 393 * Write an integer value into the parcel at the current dataPosition(), 394 * growing dataCapacity() if needed. 395 */ writeInt(int val)396 public final native void writeInt(int val); 397 398 /** 399 * Write a long integer value into the parcel at the current dataPosition(), 400 * growing dataCapacity() if needed. 401 */ writeLong(long val)402 public final native void writeLong(long val); 403 404 /** 405 * Write a floating point value into the parcel at the current 406 * dataPosition(), growing dataCapacity() if needed. 407 */ writeFloat(float val)408 public final native void writeFloat(float val); 409 410 /** 411 * Write a double precision floating point value into the parcel at the 412 * current dataPosition(), growing dataCapacity() if needed. 413 */ writeDouble(double val)414 public final native void writeDouble(double val); 415 416 /** 417 * Write a string value into the parcel at the current dataPosition(), 418 * growing dataCapacity() if needed. 419 */ writeString(String val)420 public final native void writeString(String val); 421 422 /** 423 * Write a CharSequence value into the parcel at the current dataPosition(), 424 * growing dataCapacity() if needed. 425 * @hide 426 */ writeCharSequence(CharSequence val)427 public final void writeCharSequence(CharSequence val) { 428 TextUtils.writeToParcel(val, this, 0); 429 } 430 431 /** 432 * Write an object into the parcel at the current dataPosition(), 433 * growing dataCapacity() if needed. 434 */ writeStrongBinder(IBinder val)435 public final native void writeStrongBinder(IBinder val); 436 437 /** 438 * Write an object into the parcel at the current dataPosition(), 439 * growing dataCapacity() if needed. 440 */ writeStrongInterface(IInterface val)441 public final void writeStrongInterface(IInterface val) { 442 writeStrongBinder(val == null ? null : val.asBinder()); 443 } 444 445 /** 446 * Write a FileDescriptor into the parcel at the current dataPosition(), 447 * growing dataCapacity() if needed. 448 * 449 * <p class="caution">The file descriptor will not be closed, which may 450 * result in file descriptor leaks when objects are returned from Binder 451 * calls. Use {@link ParcelFileDescriptor#writeToParcel} instead, which 452 * accepts contextual flags and will close the original file descriptor 453 * if {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE} is set.</p> 454 */ writeFileDescriptor(FileDescriptor val)455 public final native void writeFileDescriptor(FileDescriptor val); 456 457 /** 458 * Write an byte value into the parcel at the current dataPosition(), 459 * growing dataCapacity() if needed. 460 */ writeByte(byte val)461 public final void writeByte(byte val) { 462 writeInt(val); 463 } 464 465 /** 466 * Please use {@link #writeBundle} instead. Flattens a Map into the parcel 467 * at the current dataPosition(), 468 * growing dataCapacity() if needed. The Map keys must be String objects. 469 * The Map values are written using {@link #writeValue} and must follow 470 * the specification there. 471 * 472 * <p>It is strongly recommended to use {@link #writeBundle} instead of 473 * this method, since the Bundle class provides a type-safe API that 474 * allows you to avoid mysterious type errors at the point of marshalling. 475 */ writeMap(Map val)476 public final void writeMap(Map val) { 477 writeMapInternal((Map<String,Object>) val); 478 } 479 480 /** 481 * Flatten a Map into the parcel at the current dataPosition(), 482 * growing dataCapacity() if needed. The Map keys must be String objects. 483 */ writeMapInternal(Map<String,Object> val)484 /* package */ void writeMapInternal(Map<String,Object> val) { 485 if (val == null) { 486 writeInt(-1); 487 return; 488 } 489 Set<Map.Entry<String,Object>> entries = val.entrySet(); 490 writeInt(entries.size()); 491 for (Map.Entry<String,Object> e : entries) { 492 writeValue(e.getKey()); 493 writeValue(e.getValue()); 494 } 495 } 496 497 /** 498 * Flatten a Bundle into the parcel at the current dataPosition(), 499 * growing dataCapacity() if needed. 500 */ writeBundle(Bundle val)501 public final void writeBundle(Bundle val) { 502 if (val == null) { 503 writeInt(-1); 504 return; 505 } 506 507 val.writeToParcel(this, 0); 508 } 509 510 /** 511 * Flatten a List into the parcel at the current dataPosition(), growing 512 * dataCapacity() if needed. The List values are written using 513 * {@link #writeValue} and must follow the specification there. 514 */ writeList(List val)515 public final void writeList(List val) { 516 if (val == null) { 517 writeInt(-1); 518 return; 519 } 520 int N = val.size(); 521 int i=0; 522 writeInt(N); 523 while (i < N) { 524 writeValue(val.get(i)); 525 i++; 526 } 527 } 528 529 /** 530 * Flatten an Object array into the parcel at the current dataPosition(), 531 * growing dataCapacity() if needed. The array values are written using 532 * {@link #writeValue} and must follow the specification there. 533 */ writeArray(Object[] val)534 public final void writeArray(Object[] val) { 535 if (val == null) { 536 writeInt(-1); 537 return; 538 } 539 int N = val.length; 540 int i=0; 541 writeInt(N); 542 while (i < N) { 543 writeValue(val[i]); 544 i++; 545 } 546 } 547 548 /** 549 * Flatten a generic SparseArray into the parcel at the current 550 * dataPosition(), growing dataCapacity() if needed. The SparseArray 551 * values are written using {@link #writeValue} and must follow the 552 * specification there. 553 */ writeSparseArray(SparseArray<Object> val)554 public final void writeSparseArray(SparseArray<Object> val) { 555 if (val == null) { 556 writeInt(-1); 557 return; 558 } 559 int N = val.size(); 560 writeInt(N); 561 int i=0; 562 while (i < N) { 563 writeInt(val.keyAt(i)); 564 writeValue(val.valueAt(i)); 565 i++; 566 } 567 } 568 writeSparseBooleanArray(SparseBooleanArray val)569 public final void writeSparseBooleanArray(SparseBooleanArray val) { 570 if (val == null) { 571 writeInt(-1); 572 return; 573 } 574 int N = val.size(); 575 writeInt(N); 576 int i=0; 577 while (i < N) { 578 writeInt(val.keyAt(i)); 579 writeByte((byte)(val.valueAt(i) ? 1 : 0)); 580 i++; 581 } 582 } 583 writeBooleanArray(boolean[] val)584 public final void writeBooleanArray(boolean[] val) { 585 if (val != null) { 586 int N = val.length; 587 writeInt(N); 588 for (int i=0; i<N; i++) { 589 writeInt(val[i] ? 1 : 0); 590 } 591 } else { 592 writeInt(-1); 593 } 594 } 595 createBooleanArray()596 public final boolean[] createBooleanArray() { 597 int N = readInt(); 598 // >>2 as a fast divide-by-4 works in the create*Array() functions 599 // because dataAvail() will never return a negative number. 4 is 600 // the size of a stored boolean in the stream. 601 if (N >= 0 && N <= (dataAvail() >> 2)) { 602 boolean[] val = new boolean[N]; 603 for (int i=0; i<N; i++) { 604 val[i] = readInt() != 0; 605 } 606 return val; 607 } else { 608 return null; 609 } 610 } 611 readBooleanArray(boolean[] val)612 public final void readBooleanArray(boolean[] val) { 613 int N = readInt(); 614 if (N == val.length) { 615 for (int i=0; i<N; i++) { 616 val[i] = readInt() != 0; 617 } 618 } else { 619 throw new RuntimeException("bad array lengths"); 620 } 621 } 622 writeCharArray(char[] val)623 public final void writeCharArray(char[] val) { 624 if (val != null) { 625 int N = val.length; 626 writeInt(N); 627 for (int i=0; i<N; i++) { 628 writeInt((int)val[i]); 629 } 630 } else { 631 writeInt(-1); 632 } 633 } 634 createCharArray()635 public final char[] createCharArray() { 636 int N = readInt(); 637 if (N >= 0 && N <= (dataAvail() >> 2)) { 638 char[] val = new char[N]; 639 for (int i=0; i<N; i++) { 640 val[i] = (char)readInt(); 641 } 642 return val; 643 } else { 644 return null; 645 } 646 } 647 readCharArray(char[] val)648 public final void readCharArray(char[] val) { 649 int N = readInt(); 650 if (N == val.length) { 651 for (int i=0; i<N; i++) { 652 val[i] = (char)readInt(); 653 } 654 } else { 655 throw new RuntimeException("bad array lengths"); 656 } 657 } 658 writeIntArray(int[] val)659 public final void writeIntArray(int[] val) { 660 if (val != null) { 661 int N = val.length; 662 writeInt(N); 663 for (int i=0; i<N; i++) { 664 writeInt(val[i]); 665 } 666 } else { 667 writeInt(-1); 668 } 669 } 670 createIntArray()671 public final int[] createIntArray() { 672 int N = readInt(); 673 if (N >= 0 && N <= (dataAvail() >> 2)) { 674 int[] val = new int[N]; 675 for (int i=0; i<N; i++) { 676 val[i] = readInt(); 677 } 678 return val; 679 } else { 680 return null; 681 } 682 } 683 readIntArray(int[] val)684 public final void readIntArray(int[] val) { 685 int N = readInt(); 686 if (N == val.length) { 687 for (int i=0; i<N; i++) { 688 val[i] = readInt(); 689 } 690 } else { 691 throw new RuntimeException("bad array lengths"); 692 } 693 } 694 writeLongArray(long[] val)695 public final void writeLongArray(long[] val) { 696 if (val != null) { 697 int N = val.length; 698 writeInt(N); 699 for (int i=0; i<N; i++) { 700 writeLong(val[i]); 701 } 702 } else { 703 writeInt(-1); 704 } 705 } 706 createLongArray()707 public final long[] createLongArray() { 708 int N = readInt(); 709 // >>3 because stored longs are 64 bits 710 if (N >= 0 && N <= (dataAvail() >> 3)) { 711 long[] val = new long[N]; 712 for (int i=0; i<N; i++) { 713 val[i] = readLong(); 714 } 715 return val; 716 } else { 717 return null; 718 } 719 } 720 readLongArray(long[] val)721 public final void readLongArray(long[] val) { 722 int N = readInt(); 723 if (N == val.length) { 724 for (int i=0; i<N; i++) { 725 val[i] = readLong(); 726 } 727 } else { 728 throw new RuntimeException("bad array lengths"); 729 } 730 } 731 writeFloatArray(float[] val)732 public final void writeFloatArray(float[] val) { 733 if (val != null) { 734 int N = val.length; 735 writeInt(N); 736 for (int i=0; i<N; i++) { 737 writeFloat(val[i]); 738 } 739 } else { 740 writeInt(-1); 741 } 742 } 743 createFloatArray()744 public final float[] createFloatArray() { 745 int N = readInt(); 746 // >>2 because stored floats are 4 bytes 747 if (N >= 0 && N <= (dataAvail() >> 2)) { 748 float[] val = new float[N]; 749 for (int i=0; i<N; i++) { 750 val[i] = readFloat(); 751 } 752 return val; 753 } else { 754 return null; 755 } 756 } 757 readFloatArray(float[] val)758 public final void readFloatArray(float[] val) { 759 int N = readInt(); 760 if (N == val.length) { 761 for (int i=0; i<N; i++) { 762 val[i] = readFloat(); 763 } 764 } else { 765 throw new RuntimeException("bad array lengths"); 766 } 767 } 768 writeDoubleArray(double[] val)769 public final void writeDoubleArray(double[] val) { 770 if (val != null) { 771 int N = val.length; 772 writeInt(N); 773 for (int i=0; i<N; i++) { 774 writeDouble(val[i]); 775 } 776 } else { 777 writeInt(-1); 778 } 779 } 780 createDoubleArray()781 public final double[] createDoubleArray() { 782 int N = readInt(); 783 // >>3 because stored doubles are 8 bytes 784 if (N >= 0 && N <= (dataAvail() >> 3)) { 785 double[] val = new double[N]; 786 for (int i=0; i<N; i++) { 787 val[i] = readDouble(); 788 } 789 return val; 790 } else { 791 return null; 792 } 793 } 794 readDoubleArray(double[] val)795 public final void readDoubleArray(double[] val) { 796 int N = readInt(); 797 if (N == val.length) { 798 for (int i=0; i<N; i++) { 799 val[i] = readDouble(); 800 } 801 } else { 802 throw new RuntimeException("bad array lengths"); 803 } 804 } 805 writeStringArray(String[] val)806 public final void writeStringArray(String[] val) { 807 if (val != null) { 808 int N = val.length; 809 writeInt(N); 810 for (int i=0; i<N; i++) { 811 writeString(val[i]); 812 } 813 } else { 814 writeInt(-1); 815 } 816 } 817 createStringArray()818 public final String[] createStringArray() { 819 int N = readInt(); 820 if (N >= 0) { 821 String[] val = new String[N]; 822 for (int i=0; i<N; i++) { 823 val[i] = readString(); 824 } 825 return val; 826 } else { 827 return null; 828 } 829 } 830 readStringArray(String[] val)831 public final void readStringArray(String[] val) { 832 int N = readInt(); 833 if (N == val.length) { 834 for (int i=0; i<N; i++) { 835 val[i] = readString(); 836 } 837 } else { 838 throw new RuntimeException("bad array lengths"); 839 } 840 } 841 writeBinderArray(IBinder[] val)842 public final void writeBinderArray(IBinder[] val) { 843 if (val != null) { 844 int N = val.length; 845 writeInt(N); 846 for (int i=0; i<N; i++) { 847 writeStrongBinder(val[i]); 848 } 849 } else { 850 writeInt(-1); 851 } 852 } 853 854 /** 855 * @hide 856 */ writeCharSequenceArray(CharSequence[] val)857 public final void writeCharSequenceArray(CharSequence[] val) { 858 if (val != null) { 859 int N = val.length; 860 writeInt(N); 861 for (int i=0; i<N; i++) { 862 writeCharSequence(val[i]); 863 } 864 } else { 865 writeInt(-1); 866 } 867 } 868 createBinderArray()869 public final IBinder[] createBinderArray() { 870 int N = readInt(); 871 if (N >= 0) { 872 IBinder[] val = new IBinder[N]; 873 for (int i=0; i<N; i++) { 874 val[i] = readStrongBinder(); 875 } 876 return val; 877 } else { 878 return null; 879 } 880 } 881 readBinderArray(IBinder[] val)882 public final void readBinderArray(IBinder[] val) { 883 int N = readInt(); 884 if (N == val.length) { 885 for (int i=0; i<N; i++) { 886 val[i] = readStrongBinder(); 887 } 888 } else { 889 throw new RuntimeException("bad array lengths"); 890 } 891 } 892 893 /** 894 * Flatten a List containing a particular object type into the parcel, at 895 * the current dataPosition() and growing dataCapacity() if needed. The 896 * type of the objects in the list must be one that implements Parcelable. 897 * Unlike the generic writeList() method, however, only the raw data of the 898 * objects is written and not their type, so you must use the corresponding 899 * readTypedList() to unmarshall them. 900 * 901 * @param val The list of objects to be written. 902 * 903 * @see #createTypedArrayList 904 * @see #readTypedList 905 * @see Parcelable 906 */ writeTypedList(List<T> val)907 public final <T extends Parcelable> void writeTypedList(List<T> val) { 908 if (val == null) { 909 writeInt(-1); 910 return; 911 } 912 int N = val.size(); 913 int i=0; 914 writeInt(N); 915 while (i < N) { 916 T item = val.get(i); 917 if (item != null) { 918 writeInt(1); 919 item.writeToParcel(this, 0); 920 } else { 921 writeInt(0); 922 } 923 i++; 924 } 925 } 926 927 /** 928 * Flatten a List containing String objects into the parcel, at 929 * the current dataPosition() and growing dataCapacity() if needed. They 930 * can later be retrieved with {@link #createStringArrayList} or 931 * {@link #readStringList}. 932 * 933 * @param val The list of strings to be written. 934 * 935 * @see #createStringArrayList 936 * @see #readStringList 937 */ writeStringList(List<String> val)938 public final void writeStringList(List<String> val) { 939 if (val == null) { 940 writeInt(-1); 941 return; 942 } 943 int N = val.size(); 944 int i=0; 945 writeInt(N); 946 while (i < N) { 947 writeString(val.get(i)); 948 i++; 949 } 950 } 951 952 /** 953 * Flatten a List containing IBinder objects into the parcel, at 954 * the current dataPosition() and growing dataCapacity() if needed. They 955 * can later be retrieved with {@link #createBinderArrayList} or 956 * {@link #readBinderList}. 957 * 958 * @param val The list of strings to be written. 959 * 960 * @see #createBinderArrayList 961 * @see #readBinderList 962 */ writeBinderList(List<IBinder> val)963 public final void writeBinderList(List<IBinder> val) { 964 if (val == null) { 965 writeInt(-1); 966 return; 967 } 968 int N = val.size(); 969 int i=0; 970 writeInt(N); 971 while (i < N) { 972 writeStrongBinder(val.get(i)); 973 i++; 974 } 975 } 976 977 /** 978 * Flatten a heterogeneous array containing a particular object type into 979 * the parcel, at 980 * the current dataPosition() and growing dataCapacity() if needed. The 981 * type of the objects in the array must be one that implements Parcelable. 982 * Unlike the {@link #writeParcelableArray} method, however, only the 983 * raw data of the objects is written and not their type, so you must use 984 * {@link #readTypedArray} with the correct corresponding 985 * {@link Parcelable.Creator} implementation to unmarshall them. 986 * 987 * @param val The array of objects to be written. 988 * @param parcelableFlags Contextual flags as per 989 * {@link Parcelable#writeToParcel(Parcel, int) Parcelable.writeToParcel()}. 990 * 991 * @see #readTypedArray 992 * @see #writeParcelableArray 993 * @see Parcelable.Creator 994 */ writeTypedArray(T[] val, int parcelableFlags)995 public final <T extends Parcelable> void writeTypedArray(T[] val, 996 int parcelableFlags) { 997 if (val != null) { 998 int N = val.length; 999 writeInt(N); 1000 for (int i=0; i<N; i++) { 1001 T item = val[i]; 1002 if (item != null) { 1003 writeInt(1); 1004 item.writeToParcel(this, parcelableFlags); 1005 } else { 1006 writeInt(0); 1007 } 1008 } 1009 } else { 1010 writeInt(-1); 1011 } 1012 } 1013 1014 /** 1015 * Flatten a generic object in to a parcel. The given Object value may 1016 * currently be one of the following types: 1017 * 1018 * <ul> 1019 * <li> null 1020 * <li> String 1021 * <li> Byte 1022 * <li> Short 1023 * <li> Integer 1024 * <li> Long 1025 * <li> Float 1026 * <li> Double 1027 * <li> Boolean 1028 * <li> String[] 1029 * <li> boolean[] 1030 * <li> byte[] 1031 * <li> int[] 1032 * <li> long[] 1033 * <li> Object[] (supporting objects of the same type defined here). 1034 * <li> {@link Bundle} 1035 * <li> Map (as supported by {@link #writeMap}). 1036 * <li> Any object that implements the {@link Parcelable} protocol. 1037 * <li> Parcelable[] 1038 * <li> CharSequence (as supported by {@link TextUtils#writeToParcel}). 1039 * <li> List (as supported by {@link #writeList}). 1040 * <li> {@link SparseArray} (as supported by {@link #writeSparseArray(SparseArray)}). 1041 * <li> {@link IBinder} 1042 * <li> Any object that implements Serializable (but see 1043 * {@link #writeSerializable} for caveats). Note that all of the 1044 * previous types have relatively efficient implementations for 1045 * writing to a Parcel; having to rely on the generic serialization 1046 * approach is much less efficient and should be avoided whenever 1047 * possible. 1048 * </ul> 1049 * 1050 * <p class="caution">{@link Parcelable} objects are written with 1051 * {@link Parcelable#writeToParcel} using contextual flags of 0. When 1052 * serializing objects containing {@link ParcelFileDescriptor}s, 1053 * this may result in file descriptor leaks when they are returned from 1054 * Binder calls (where {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE} 1055 * should be used).</p> 1056 */ writeValue(Object v)1057 public final void writeValue(Object v) { 1058 if (v == null) { 1059 writeInt(VAL_NULL); 1060 } else if (v instanceof String) { 1061 writeInt(VAL_STRING); 1062 writeString((String) v); 1063 } else if (v instanceof Integer) { 1064 writeInt(VAL_INTEGER); 1065 writeInt((Integer) v); 1066 } else if (v instanceof Map) { 1067 writeInt(VAL_MAP); 1068 writeMap((Map) v); 1069 } else if (v instanceof Bundle) { 1070 // Must be before Parcelable 1071 writeInt(VAL_BUNDLE); 1072 writeBundle((Bundle) v); 1073 } else if (v instanceof Parcelable) { 1074 writeInt(VAL_PARCELABLE); 1075 writeParcelable((Parcelable) v, 0); 1076 } else if (v instanceof Short) { 1077 writeInt(VAL_SHORT); 1078 writeInt(((Short) v).intValue()); 1079 } else if (v instanceof Long) { 1080 writeInt(VAL_LONG); 1081 writeLong((Long) v); 1082 } else if (v instanceof Float) { 1083 writeInt(VAL_FLOAT); 1084 writeFloat((Float) v); 1085 } else if (v instanceof Double) { 1086 writeInt(VAL_DOUBLE); 1087 writeDouble((Double) v); 1088 } else if (v instanceof Boolean) { 1089 writeInt(VAL_BOOLEAN); 1090 writeInt((Boolean) v ? 1 : 0); 1091 } else if (v instanceof CharSequence) { 1092 // Must be after String 1093 writeInt(VAL_CHARSEQUENCE); 1094 writeCharSequence((CharSequence) v); 1095 } else if (v instanceof List) { 1096 writeInt(VAL_LIST); 1097 writeList((List) v); 1098 } else if (v instanceof SparseArray) { 1099 writeInt(VAL_SPARSEARRAY); 1100 writeSparseArray((SparseArray) v); 1101 } else if (v instanceof boolean[]) { 1102 writeInt(VAL_BOOLEANARRAY); 1103 writeBooleanArray((boolean[]) v); 1104 } else if (v instanceof byte[]) { 1105 writeInt(VAL_BYTEARRAY); 1106 writeByteArray((byte[]) v); 1107 } else if (v instanceof String[]) { 1108 writeInt(VAL_STRINGARRAY); 1109 writeStringArray((String[]) v); 1110 } else if (v instanceof CharSequence[]) { 1111 // Must be after String[] and before Object[] 1112 writeInt(VAL_CHARSEQUENCEARRAY); 1113 writeCharSequenceArray((CharSequence[]) v); 1114 } else if (v instanceof IBinder) { 1115 writeInt(VAL_IBINDER); 1116 writeStrongBinder((IBinder) v); 1117 } else if (v instanceof Parcelable[]) { 1118 writeInt(VAL_PARCELABLEARRAY); 1119 writeParcelableArray((Parcelable[]) v, 0); 1120 } else if (v instanceof Object[]) { 1121 writeInt(VAL_OBJECTARRAY); 1122 writeArray((Object[]) v); 1123 } else if (v instanceof int[]) { 1124 writeInt(VAL_INTARRAY); 1125 writeIntArray((int[]) v); 1126 } else if (v instanceof long[]) { 1127 writeInt(VAL_LONGARRAY); 1128 writeLongArray((long[]) v); 1129 } else if (v instanceof Byte) { 1130 writeInt(VAL_BYTE); 1131 writeInt((Byte) v); 1132 } else if (v instanceof Serializable) { 1133 // Must be last 1134 writeInt(VAL_SERIALIZABLE); 1135 writeSerializable((Serializable) v); 1136 } else { 1137 throw new RuntimeException("Parcel: unable to marshal value " + v); 1138 } 1139 } 1140 1141 /** 1142 * Flatten the name of the class of the Parcelable and its contents 1143 * into the parcel. 1144 * 1145 * @param p The Parcelable object to be written. 1146 * @param parcelableFlags Contextual flags as per 1147 * {@link Parcelable#writeToParcel(Parcel, int) Parcelable.writeToParcel()}. 1148 */ writeParcelable(Parcelable p, int parcelableFlags)1149 public final void writeParcelable(Parcelable p, int parcelableFlags) { 1150 if (p == null) { 1151 writeString(null); 1152 return; 1153 } 1154 String name = p.getClass().getName(); 1155 writeString(name); 1156 p.writeToParcel(this, parcelableFlags); 1157 } 1158 1159 /** 1160 * Write a generic serializable object in to a Parcel. It is strongly 1161 * recommended that this method be avoided, since the serialization 1162 * overhead is extremely large, and this approach will be much slower than 1163 * using the other approaches to writing data in to a Parcel. 1164 */ writeSerializable(Serializable s)1165 public final void writeSerializable(Serializable s) { 1166 if (s == null) { 1167 writeString(null); 1168 return; 1169 } 1170 String name = s.getClass().getName(); 1171 writeString(name); 1172 1173 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 1174 try { 1175 ObjectOutputStream oos = new ObjectOutputStream(baos); 1176 oos.writeObject(s); 1177 oos.close(); 1178 1179 writeByteArray(baos.toByteArray()); 1180 } catch (IOException ioe) { 1181 throw new RuntimeException("Parcelable encountered " + 1182 "IOException writing serializable object (name = " + name + 1183 ")", ioe); 1184 } 1185 } 1186 1187 /** 1188 * Special function for writing an exception result at the header of 1189 * a parcel, to be used when returning an exception from a transaction. 1190 * Note that this currently only supports a few exception types; any other 1191 * exception will be re-thrown by this function as a RuntimeException 1192 * (to be caught by the system's last-resort exception handling when 1193 * dispatching a transaction). 1194 * 1195 * <p>The supported exception types are: 1196 * <ul> 1197 * <li>{@link BadParcelableException} 1198 * <li>{@link IllegalArgumentException} 1199 * <li>{@link IllegalStateException} 1200 * <li>{@link NullPointerException} 1201 * <li>{@link SecurityException} 1202 * </ul> 1203 * 1204 * @param e The Exception to be written. 1205 * 1206 * @see #writeNoException 1207 * @see #readException 1208 */ writeException(Exception e)1209 public final void writeException(Exception e) { 1210 int code = 0; 1211 if (e instanceof SecurityException) { 1212 code = EX_SECURITY; 1213 } else if (e instanceof BadParcelableException) { 1214 code = EX_BAD_PARCELABLE; 1215 } else if (e instanceof IllegalArgumentException) { 1216 code = EX_ILLEGAL_ARGUMENT; 1217 } else if (e instanceof NullPointerException) { 1218 code = EX_NULL_POINTER; 1219 } else if (e instanceof IllegalStateException) { 1220 code = EX_ILLEGAL_STATE; 1221 } 1222 writeInt(code); 1223 StrictMode.clearGatheredViolations(); 1224 if (code == 0) { 1225 if (e instanceof RuntimeException) { 1226 throw (RuntimeException) e; 1227 } 1228 throw new RuntimeException(e); 1229 } 1230 writeString(e.getMessage()); 1231 } 1232 1233 /** 1234 * Special function for writing information at the front of the Parcel 1235 * indicating that no exception occurred. 1236 * 1237 * @see #writeException 1238 * @see #readException 1239 */ writeNoException()1240 public final void writeNoException() { 1241 // Despite the name of this function ("write no exception"), 1242 // it should instead be thought of as "write the RPC response 1243 // header", but because this function name is written out by 1244 // the AIDL compiler, we're not going to rename it. 1245 // 1246 // The response header, in the non-exception case (see also 1247 // writeException above, also called by the AIDL compiler), is 1248 // either a 0 (the default case), or EX_HAS_REPLY_HEADER if 1249 // StrictMode has gathered up violations that have occurred 1250 // during a Binder call, in which case we write out the number 1251 // of violations and their details, serialized, before the 1252 // actual RPC respons data. The receiving end of this is 1253 // readException(), below. 1254 if (StrictMode.hasGatheredViolations()) { 1255 writeInt(EX_HAS_REPLY_HEADER); 1256 final int sizePosition = dataPosition(); 1257 writeInt(0); // total size of fat header, to be filled in later 1258 StrictMode.writeGatheredViolationsToParcel(this); 1259 final int payloadPosition = dataPosition(); 1260 setDataPosition(sizePosition); 1261 writeInt(payloadPosition - sizePosition); // header size 1262 setDataPosition(payloadPosition); 1263 } else { 1264 writeInt(0); 1265 } 1266 } 1267 1268 /** 1269 * Special function for reading an exception result from the header of 1270 * a parcel, to be used after receiving the result of a transaction. This 1271 * will throw the exception for you if it had been written to the Parcel, 1272 * otherwise return and let you read the normal result data from the Parcel. 1273 * 1274 * @see #writeException 1275 * @see #writeNoException 1276 */ readException()1277 public final void readException() { 1278 int code = readExceptionCode(); 1279 if (code != 0) { 1280 String msg = readString(); 1281 readException(code, msg); 1282 } 1283 } 1284 1285 /** 1286 * Parses the header of a Binder call's response Parcel and 1287 * returns the exception code. Deals with lite or fat headers. 1288 * In the common successful case, this header is generally zero. 1289 * In less common cases, it's a small negative number and will be 1290 * followed by an error string. 1291 * 1292 * This exists purely for android.database.DatabaseUtils and 1293 * insulating it from having to handle fat headers as returned by 1294 * e.g. StrictMode-induced RPC responses. 1295 * 1296 * @hide 1297 */ readExceptionCode()1298 public final int readExceptionCode() { 1299 int code = readInt(); 1300 if (code == EX_HAS_REPLY_HEADER) { 1301 int headerSize = readInt(); 1302 if (headerSize == 0) { 1303 Log.e(TAG, "Unexpected zero-sized Parcel reply header."); 1304 } else { 1305 // Currently the only thing in the header is StrictMode stacks, 1306 // but discussions around event/RPC tracing suggest we might 1307 // put that here too. If so, switch on sub-header tags here. 1308 // But for now, just parse out the StrictMode stuff. 1309 StrictMode.readAndHandleBinderCallViolations(this); 1310 } 1311 // And fat response headers are currently only used when 1312 // there are no exceptions, so return no error: 1313 return 0; 1314 } 1315 return code; 1316 } 1317 1318 /** 1319 * Use this function for customized exception handling. 1320 * customized method call this method for all unknown case 1321 * @param code exception code 1322 * @param msg exception message 1323 */ readException(int code, String msg)1324 public final void readException(int code, String msg) { 1325 switch (code) { 1326 case EX_SECURITY: 1327 throw new SecurityException(msg); 1328 case EX_BAD_PARCELABLE: 1329 throw new BadParcelableException(msg); 1330 case EX_ILLEGAL_ARGUMENT: 1331 throw new IllegalArgumentException(msg); 1332 case EX_NULL_POINTER: 1333 throw new NullPointerException(msg); 1334 case EX_ILLEGAL_STATE: 1335 throw new IllegalStateException(msg); 1336 } 1337 throw new RuntimeException("Unknown exception code: " + code 1338 + " msg " + msg); 1339 } 1340 1341 /** 1342 * Read an integer value from the parcel at the current dataPosition(). 1343 */ readInt()1344 public final native int readInt(); 1345 1346 /** 1347 * Read a long integer value from the parcel at the current dataPosition(). 1348 */ readLong()1349 public final native long readLong(); 1350 1351 /** 1352 * Read a floating point value from the parcel at the current 1353 * dataPosition(). 1354 */ readFloat()1355 public final native float readFloat(); 1356 1357 /** 1358 * Read a double precision floating point value from the parcel at the 1359 * current dataPosition(). 1360 */ readDouble()1361 public final native double readDouble(); 1362 1363 /** 1364 * Read a string value from the parcel at the current dataPosition(). 1365 */ readString()1366 public final native String readString(); 1367 1368 /** 1369 * Read a CharSequence value from the parcel at the current dataPosition(). 1370 * @hide 1371 */ readCharSequence()1372 public final CharSequence readCharSequence() { 1373 return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(this); 1374 } 1375 1376 /** 1377 * Read an object from the parcel at the current dataPosition(). 1378 */ readStrongBinder()1379 public final native IBinder readStrongBinder(); 1380 1381 /** 1382 * Read a FileDescriptor from the parcel at the current dataPosition(). 1383 */ readFileDescriptor()1384 public final ParcelFileDescriptor readFileDescriptor() { 1385 FileDescriptor fd = internalReadFileDescriptor(); 1386 return fd != null ? new ParcelFileDescriptor(fd) : null; 1387 } 1388 internalReadFileDescriptor()1389 private native FileDescriptor internalReadFileDescriptor(); openFileDescriptor(String file, int mode)1390 /*package*/ static native FileDescriptor openFileDescriptor(String file, 1391 int mode) throws FileNotFoundException; dupFileDescriptor(FileDescriptor orig)1392 /*package*/ static native FileDescriptor dupFileDescriptor(FileDescriptor orig) 1393 throws IOException; closeFileDescriptor(FileDescriptor desc)1394 /*package*/ static native void closeFileDescriptor(FileDescriptor desc) 1395 throws IOException; clearFileDescriptor(FileDescriptor desc)1396 /*package*/ static native void clearFileDescriptor(FileDescriptor desc); 1397 1398 /** 1399 * Read a byte value from the parcel at the current dataPosition(). 1400 */ readByte()1401 public final byte readByte() { 1402 return (byte)(readInt() & 0xff); 1403 } 1404 1405 /** 1406 * Please use {@link #readBundle(ClassLoader)} instead (whose data must have 1407 * been written with {@link #writeBundle}. Read into an existing Map object 1408 * from the parcel at the current dataPosition(). 1409 */ readMap(Map outVal, ClassLoader loader)1410 public final void readMap(Map outVal, ClassLoader loader) { 1411 int N = readInt(); 1412 readMapInternal(outVal, N, loader); 1413 } 1414 1415 /** 1416 * Read into an existing List object from the parcel at the current 1417 * dataPosition(), using the given class loader to load any enclosed 1418 * Parcelables. If it is null, the default class loader is used. 1419 */ readList(List outVal, ClassLoader loader)1420 public final void readList(List outVal, ClassLoader loader) { 1421 int N = readInt(); 1422 readListInternal(outVal, N, loader); 1423 } 1424 1425 /** 1426 * Please use {@link #readBundle(ClassLoader)} instead (whose data must have 1427 * been written with {@link #writeBundle}. Read and return a new HashMap 1428 * object from the parcel at the current dataPosition(), using the given 1429 * class loader to load any enclosed Parcelables. Returns null if 1430 * the previously written map object was null. 1431 */ readHashMap(ClassLoader loader)1432 public final HashMap readHashMap(ClassLoader loader) 1433 { 1434 int N = readInt(); 1435 if (N < 0) { 1436 return null; 1437 } 1438 HashMap m = new HashMap(N); 1439 readMapInternal(m, N, loader); 1440 return m; 1441 } 1442 1443 /** 1444 * Read and return a new Bundle object from the parcel at the current 1445 * dataPosition(). Returns null if the previously written Bundle object was 1446 * null. 1447 */ readBundle()1448 public final Bundle readBundle() { 1449 return readBundle(null); 1450 } 1451 1452 /** 1453 * Read and return a new Bundle object from the parcel at the current 1454 * dataPosition(), using the given class loader to initialize the class 1455 * loader of the Bundle for later retrieval of Parcelable objects. 1456 * Returns null if the previously written Bundle object was null. 1457 */ readBundle(ClassLoader loader)1458 public final Bundle readBundle(ClassLoader loader) { 1459 int length = readInt(); 1460 if (length < 0) { 1461 return null; 1462 } 1463 1464 final Bundle bundle = new Bundle(this, length); 1465 if (loader != null) { 1466 bundle.setClassLoader(loader); 1467 } 1468 return bundle; 1469 } 1470 1471 /** 1472 * Read and return a byte[] object from the parcel. 1473 */ createByteArray()1474 public final native byte[] createByteArray(); 1475 1476 /** 1477 * Read a byte[] object from the parcel and copy it into the 1478 * given byte array. 1479 */ readByteArray(byte[] val)1480 public final void readByteArray(byte[] val) { 1481 // TODO: make this a native method to avoid the extra copy. 1482 byte[] ba = createByteArray(); 1483 if (ba.length == val.length) { 1484 System.arraycopy(ba, 0, val, 0, ba.length); 1485 } else { 1486 throw new RuntimeException("bad array lengths"); 1487 } 1488 } 1489 1490 /** 1491 * Read and return a String[] object from the parcel. 1492 * {@hide} 1493 */ readStringArray()1494 public final String[] readStringArray() { 1495 String[] array = null; 1496 1497 int length = readInt(); 1498 if (length >= 0) 1499 { 1500 array = new String[length]; 1501 1502 for (int i = 0 ; i < length ; i++) 1503 { 1504 array[i] = readString(); 1505 } 1506 } 1507 1508 return array; 1509 } 1510 1511 /** 1512 * Read and return a CharSequence[] object from the parcel. 1513 * {@hide} 1514 */ readCharSequenceArray()1515 public final CharSequence[] readCharSequenceArray() { 1516 CharSequence[] array = null; 1517 1518 int length = readInt(); 1519 if (length >= 0) 1520 { 1521 array = new CharSequence[length]; 1522 1523 for (int i = 0 ; i < length ; i++) 1524 { 1525 array[i] = readCharSequence(); 1526 } 1527 } 1528 1529 return array; 1530 } 1531 1532 /** 1533 * Read and return a new ArrayList object from the parcel at the current 1534 * dataPosition(). Returns null if the previously written list object was 1535 * null. The given class loader will be used to load any enclosed 1536 * Parcelables. 1537 */ readArrayList(ClassLoader loader)1538 public final ArrayList readArrayList(ClassLoader loader) { 1539 int N = readInt(); 1540 if (N < 0) { 1541 return null; 1542 } 1543 ArrayList l = new ArrayList(N); 1544 readListInternal(l, N, loader); 1545 return l; 1546 } 1547 1548 /** 1549 * Read and return a new Object array from the parcel at the current 1550 * dataPosition(). Returns null if the previously written array was 1551 * null. The given class loader will be used to load any enclosed 1552 * Parcelables. 1553 */ readArray(ClassLoader loader)1554 public final Object[] readArray(ClassLoader loader) { 1555 int N = readInt(); 1556 if (N < 0) { 1557 return null; 1558 } 1559 Object[] l = new Object[N]; 1560 readArrayInternal(l, N, loader); 1561 return l; 1562 } 1563 1564 /** 1565 * Read and return a new SparseArray object from the parcel at the current 1566 * dataPosition(). Returns null if the previously written list object was 1567 * null. The given class loader will be used to load any enclosed 1568 * Parcelables. 1569 */ readSparseArray(ClassLoader loader)1570 public final SparseArray readSparseArray(ClassLoader loader) { 1571 int N = readInt(); 1572 if (N < 0) { 1573 return null; 1574 } 1575 SparseArray sa = new SparseArray(N); 1576 readSparseArrayInternal(sa, N, loader); 1577 return sa; 1578 } 1579 1580 /** 1581 * Read and return a new SparseBooleanArray object from the parcel at the current 1582 * dataPosition(). Returns null if the previously written list object was 1583 * null. 1584 */ readSparseBooleanArray()1585 public final SparseBooleanArray readSparseBooleanArray() { 1586 int N = readInt(); 1587 if (N < 0) { 1588 return null; 1589 } 1590 SparseBooleanArray sa = new SparseBooleanArray(N); 1591 readSparseBooleanArrayInternal(sa, N); 1592 return sa; 1593 } 1594 1595 /** 1596 * Read and return a new ArrayList containing a particular object type from 1597 * the parcel that was written with {@link #writeTypedList} at the 1598 * current dataPosition(). Returns null if the 1599 * previously written list object was null. The list <em>must</em> have 1600 * previously been written via {@link #writeTypedList} with the same object 1601 * type. 1602 * 1603 * @return A newly created ArrayList containing objects with the same data 1604 * as those that were previously written. 1605 * 1606 * @see #writeTypedList 1607 */ createTypedArrayList(Parcelable.Creator<T> c)1608 public final <T> ArrayList<T> createTypedArrayList(Parcelable.Creator<T> c) { 1609 int N = readInt(); 1610 if (N < 0) { 1611 return null; 1612 } 1613 ArrayList<T> l = new ArrayList<T>(N); 1614 while (N > 0) { 1615 if (readInt() != 0) { 1616 l.add(c.createFromParcel(this)); 1617 } else { 1618 l.add(null); 1619 } 1620 N--; 1621 } 1622 return l; 1623 } 1624 1625 /** 1626 * Read into the given List items containing a particular object type 1627 * that were written with {@link #writeTypedList} at the 1628 * current dataPosition(). The list <em>must</em> have 1629 * previously been written via {@link #writeTypedList} with the same object 1630 * type. 1631 * 1632 * @return A newly created ArrayList containing objects with the same data 1633 * as those that were previously written. 1634 * 1635 * @see #writeTypedList 1636 */ readTypedList(List<T> list, Parcelable.Creator<T> c)1637 public final <T> void readTypedList(List<T> list, Parcelable.Creator<T> c) { 1638 int M = list.size(); 1639 int N = readInt(); 1640 int i = 0; 1641 for (; i < M && i < N; i++) { 1642 if (readInt() != 0) { 1643 list.set(i, c.createFromParcel(this)); 1644 } else { 1645 list.set(i, null); 1646 } 1647 } 1648 for (; i<N; i++) { 1649 if (readInt() != 0) { 1650 list.add(c.createFromParcel(this)); 1651 } else { 1652 list.add(null); 1653 } 1654 } 1655 for (; i<M; i++) { 1656 list.remove(N); 1657 } 1658 } 1659 1660 /** 1661 * Read and return a new ArrayList containing String objects from 1662 * the parcel that was written with {@link #writeStringList} at the 1663 * current dataPosition(). Returns null if the 1664 * previously written list object was null. 1665 * 1666 * @return A newly created ArrayList containing strings with the same data 1667 * as those that were previously written. 1668 * 1669 * @see #writeStringList 1670 */ createStringArrayList()1671 public final ArrayList<String> createStringArrayList() { 1672 int N = readInt(); 1673 if (N < 0) { 1674 return null; 1675 } 1676 ArrayList<String> l = new ArrayList<String>(N); 1677 while (N > 0) { 1678 l.add(readString()); 1679 N--; 1680 } 1681 return l; 1682 } 1683 1684 /** 1685 * Read and return a new ArrayList containing IBinder objects from 1686 * the parcel that was written with {@link #writeBinderList} at the 1687 * current dataPosition(). Returns null if the 1688 * previously written list object was null. 1689 * 1690 * @return A newly created ArrayList containing strings with the same data 1691 * as those that were previously written. 1692 * 1693 * @see #writeBinderList 1694 */ createBinderArrayList()1695 public final ArrayList<IBinder> createBinderArrayList() { 1696 int N = readInt(); 1697 if (N < 0) { 1698 return null; 1699 } 1700 ArrayList<IBinder> l = new ArrayList<IBinder>(N); 1701 while (N > 0) { 1702 l.add(readStrongBinder()); 1703 N--; 1704 } 1705 return l; 1706 } 1707 1708 /** 1709 * Read into the given List items String objects that were written with 1710 * {@link #writeStringList} at the current dataPosition(). 1711 * 1712 * @return A newly created ArrayList containing strings with the same data 1713 * as those that were previously written. 1714 * 1715 * @see #writeStringList 1716 */ readStringList(List<String> list)1717 public final void readStringList(List<String> list) { 1718 int M = list.size(); 1719 int N = readInt(); 1720 int i = 0; 1721 for (; i < M && i < N; i++) { 1722 list.set(i, readString()); 1723 } 1724 for (; i<N; i++) { 1725 list.add(readString()); 1726 } 1727 for (; i<M; i++) { 1728 list.remove(N); 1729 } 1730 } 1731 1732 /** 1733 * Read into the given List items IBinder objects that were written with 1734 * {@link #writeBinderList} at the current dataPosition(). 1735 * 1736 * @return A newly created ArrayList containing strings with the same data 1737 * as those that were previously written. 1738 * 1739 * @see #writeBinderList 1740 */ readBinderList(List<IBinder> list)1741 public final void readBinderList(List<IBinder> list) { 1742 int M = list.size(); 1743 int N = readInt(); 1744 int i = 0; 1745 for (; i < M && i < N; i++) { 1746 list.set(i, readStrongBinder()); 1747 } 1748 for (; i<N; i++) { 1749 list.add(readStrongBinder()); 1750 } 1751 for (; i<M; i++) { 1752 list.remove(N); 1753 } 1754 } 1755 1756 /** 1757 * Read and return a new array containing a particular object type from 1758 * the parcel at the current dataPosition(). Returns null if the 1759 * previously written array was null. The array <em>must</em> have 1760 * previously been written via {@link #writeTypedArray} with the same 1761 * object type. 1762 * 1763 * @return A newly created array containing objects with the same data 1764 * as those that were previously written. 1765 * 1766 * @see #writeTypedArray 1767 */ createTypedArray(Parcelable.Creator<T> c)1768 public final <T> T[] createTypedArray(Parcelable.Creator<T> c) { 1769 int N = readInt(); 1770 if (N < 0) { 1771 return null; 1772 } 1773 T[] l = c.newArray(N); 1774 for (int i=0; i<N; i++) { 1775 if (readInt() != 0) { 1776 l[i] = c.createFromParcel(this); 1777 } 1778 } 1779 return l; 1780 } 1781 readTypedArray(T[] val, Parcelable.Creator<T> c)1782 public final <T> void readTypedArray(T[] val, Parcelable.Creator<T> c) { 1783 int N = readInt(); 1784 if (N == val.length) { 1785 for (int i=0; i<N; i++) { 1786 if (readInt() != 0) { 1787 val[i] = c.createFromParcel(this); 1788 } else { 1789 val[i] = null; 1790 } 1791 } 1792 } else { 1793 throw new RuntimeException("bad array lengths"); 1794 } 1795 } 1796 1797 /** 1798 * @deprecated 1799 * @hide 1800 */ 1801 @Deprecated readTypedArray(Parcelable.Creator<T> c)1802 public final <T> T[] readTypedArray(Parcelable.Creator<T> c) { 1803 return createTypedArray(c); 1804 } 1805 1806 /** 1807 * Write a heterogeneous array of Parcelable objects into the Parcel. 1808 * Each object in the array is written along with its class name, so 1809 * that the correct class can later be instantiated. As a result, this 1810 * has significantly more overhead than {@link #writeTypedArray}, but will 1811 * correctly handle an array containing more than one type of object. 1812 * 1813 * @param value The array of objects to be written. 1814 * @param parcelableFlags Contextual flags as per 1815 * {@link Parcelable#writeToParcel(Parcel, int) Parcelable.writeToParcel()}. 1816 * 1817 * @see #writeTypedArray 1818 */ writeParcelableArray(T[] value, int parcelableFlags)1819 public final <T extends Parcelable> void writeParcelableArray(T[] value, 1820 int parcelableFlags) { 1821 if (value != null) { 1822 int N = value.length; 1823 writeInt(N); 1824 for (int i=0; i<N; i++) { 1825 writeParcelable(value[i], parcelableFlags); 1826 } 1827 } else { 1828 writeInt(-1); 1829 } 1830 } 1831 1832 /** 1833 * Read a typed object from a parcel. The given class loader will be 1834 * used to load any enclosed Parcelables. If it is null, the default class 1835 * loader will be used. 1836 */ readValue(ClassLoader loader)1837 public final Object readValue(ClassLoader loader) { 1838 int type = readInt(); 1839 1840 switch (type) { 1841 case VAL_NULL: 1842 return null; 1843 1844 case VAL_STRING: 1845 return readString(); 1846 1847 case VAL_INTEGER: 1848 return readInt(); 1849 1850 case VAL_MAP: 1851 return readHashMap(loader); 1852 1853 case VAL_PARCELABLE: 1854 return readParcelable(loader); 1855 1856 case VAL_SHORT: 1857 return (short) readInt(); 1858 1859 case VAL_LONG: 1860 return readLong(); 1861 1862 case VAL_FLOAT: 1863 return readFloat(); 1864 1865 case VAL_DOUBLE: 1866 return readDouble(); 1867 1868 case VAL_BOOLEAN: 1869 return readInt() == 1; 1870 1871 case VAL_CHARSEQUENCE: 1872 return readCharSequence(); 1873 1874 case VAL_LIST: 1875 return readArrayList(loader); 1876 1877 case VAL_BOOLEANARRAY: 1878 return createBooleanArray(); 1879 1880 case VAL_BYTEARRAY: 1881 return createByteArray(); 1882 1883 case VAL_STRINGARRAY: 1884 return readStringArray(); 1885 1886 case VAL_CHARSEQUENCEARRAY: 1887 return readCharSequenceArray(); 1888 1889 case VAL_IBINDER: 1890 return readStrongBinder(); 1891 1892 case VAL_OBJECTARRAY: 1893 return readArray(loader); 1894 1895 case VAL_INTARRAY: 1896 return createIntArray(); 1897 1898 case VAL_LONGARRAY: 1899 return createLongArray(); 1900 1901 case VAL_BYTE: 1902 return readByte(); 1903 1904 case VAL_SERIALIZABLE: 1905 return readSerializable(); 1906 1907 case VAL_PARCELABLEARRAY: 1908 return readParcelableArray(loader); 1909 1910 case VAL_SPARSEARRAY: 1911 return readSparseArray(loader); 1912 1913 case VAL_SPARSEBOOLEANARRAY: 1914 return readSparseBooleanArray(); 1915 1916 case VAL_BUNDLE: 1917 return readBundle(loader); // loading will be deferred 1918 1919 default: 1920 int off = dataPosition() - 4; 1921 throw new RuntimeException( 1922 "Parcel " + this + ": Unmarshalling unknown type code " + type + " at offset " + off); 1923 } 1924 } 1925 1926 /** 1927 * Read and return a new Parcelable from the parcel. The given class loader 1928 * will be used to load any enclosed Parcelables. If it is null, the default 1929 * class loader will be used. 1930 * @param loader A ClassLoader from which to instantiate the Parcelable 1931 * object, or null for the default class loader. 1932 * @return Returns the newly created Parcelable, or null if a null 1933 * object has been written. 1934 * @throws BadParcelableException Throws BadParcelableException if there 1935 * was an error trying to instantiate the Parcelable. 1936 */ readParcelable(ClassLoader loader)1937 public final <T extends Parcelable> T readParcelable(ClassLoader loader) { 1938 String name = readString(); 1939 if (name == null) { 1940 return null; 1941 } 1942 Parcelable.Creator<T> creator; 1943 synchronized (mCreators) { 1944 HashMap<String,Parcelable.Creator> map = mCreators.get(loader); 1945 if (map == null) { 1946 map = new HashMap<String,Parcelable.Creator>(); 1947 mCreators.put(loader, map); 1948 } 1949 creator = map.get(name); 1950 if (creator == null) { 1951 try { 1952 Class c = loader == null ? 1953 Class.forName(name) : Class.forName(name, true, loader); 1954 Field f = c.getField("CREATOR"); 1955 creator = (Parcelable.Creator)f.get(null); 1956 } 1957 catch (IllegalAccessException e) { 1958 Log.e(TAG, "Class not found when unmarshalling: " 1959 + name + ", e: " + e); 1960 throw new BadParcelableException( 1961 "IllegalAccessException when unmarshalling: " + name); 1962 } 1963 catch (ClassNotFoundException e) { 1964 Log.e(TAG, "Class not found when unmarshalling: " 1965 + name + ", e: " + e); 1966 throw new BadParcelableException( 1967 "ClassNotFoundException when unmarshalling: " + name); 1968 } 1969 catch (ClassCastException e) { 1970 throw new BadParcelableException("Parcelable protocol requires a " 1971 + "Parcelable.Creator object called " 1972 + " CREATOR on class " + name); 1973 } 1974 catch (NoSuchFieldException e) { 1975 throw new BadParcelableException("Parcelable protocol requires a " 1976 + "Parcelable.Creator object called " 1977 + " CREATOR on class " + name); 1978 } 1979 if (creator == null) { 1980 throw new BadParcelableException("Parcelable protocol requires a " 1981 + "Parcelable.Creator object called " 1982 + " CREATOR on class " + name); 1983 } 1984 1985 map.put(name, creator); 1986 } 1987 } 1988 1989 if (creator instanceof Parcelable.ClassLoaderCreator<?>) { 1990 return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader); 1991 } 1992 return creator.createFromParcel(this); 1993 } 1994 1995 /** 1996 * Read and return a new Parcelable array from the parcel. 1997 * The given class loader will be used to load any enclosed 1998 * Parcelables. 1999 * @return the Parcelable array, or null if the array is null 2000 */ readParcelableArray(ClassLoader loader)2001 public final Parcelable[] readParcelableArray(ClassLoader loader) { 2002 int N = readInt(); 2003 if (N < 0) { 2004 return null; 2005 } 2006 Parcelable[] p = new Parcelable[N]; 2007 for (int i = 0; i < N; i++) { 2008 p[i] = (Parcelable) readParcelable(loader); 2009 } 2010 return p; 2011 } 2012 2013 /** 2014 * Read and return a new Serializable object from the parcel. 2015 * @return the Serializable object, or null if the Serializable name 2016 * wasn't found in the parcel. 2017 */ readSerializable()2018 public final Serializable readSerializable() { 2019 String name = readString(); 2020 if (name == null) { 2021 // For some reason we were unable to read the name of the Serializable (either there 2022 // is nothing left in the Parcel to read, or the next value wasn't a String), so 2023 // return null, which indicates that the name wasn't found in the parcel. 2024 return null; 2025 } 2026 2027 byte[] serializedData = createByteArray(); 2028 ByteArrayInputStream bais = new ByteArrayInputStream(serializedData); 2029 try { 2030 ObjectInputStream ois = new ObjectInputStream(bais); 2031 return (Serializable) ois.readObject(); 2032 } catch (IOException ioe) { 2033 throw new RuntimeException("Parcelable encountered " + 2034 "IOException reading a Serializable object (name = " + name + 2035 ")", ioe); 2036 } catch (ClassNotFoundException cnfe) { 2037 throw new RuntimeException("Parcelable encountered" + 2038 "ClassNotFoundException reading a Serializable object (name = " 2039 + name + ")", cnfe); 2040 } 2041 } 2042 2043 // Cache of previously looked up CREATOR.createFromParcel() methods for 2044 // particular classes. Keys are the names of the classes, values are 2045 // Method objects. 2046 private static final HashMap<ClassLoader,HashMap<String,Parcelable.Creator>> 2047 mCreators = new HashMap<ClassLoader,HashMap<String,Parcelable.Creator>>(); 2048 obtain(int obj)2049 static protected final Parcel obtain(int obj) { 2050 final Parcel[] pool = sHolderPool; 2051 synchronized (pool) { 2052 Parcel p; 2053 for (int i=0; i<POOL_SIZE; i++) { 2054 p = pool[i]; 2055 if (p != null) { 2056 pool[i] = null; 2057 if (DEBUG_RECYCLE) { 2058 p.mStack = new RuntimeException(); 2059 } 2060 p.init(obj); 2061 return p; 2062 } 2063 } 2064 } 2065 return new Parcel(obj); 2066 } 2067 Parcel(int obj)2068 private Parcel(int obj) { 2069 if (DEBUG_RECYCLE) { 2070 mStack = new RuntimeException(); 2071 } 2072 //Log.i(TAG, "Initializing obj=0x" + Integer.toHexString(obj), mStack); 2073 init(obj); 2074 } 2075 2076 @Override finalize()2077 protected void finalize() throws Throwable { 2078 if (DEBUG_RECYCLE) { 2079 if (mStack != null) { 2080 Log.w(TAG, "Client did not call Parcel.recycle()", mStack); 2081 } 2082 } 2083 destroy(); 2084 } 2085 freeBuffer()2086 private native void freeBuffer(); init(int obj)2087 private native void init(int obj); destroy()2088 private native void destroy(); 2089 readMapInternal(Map outVal, int N, ClassLoader loader)2090 /* package */ void readMapInternal(Map outVal, int N, 2091 ClassLoader loader) { 2092 while (N > 0) { 2093 Object key = readValue(loader); 2094 Object value = readValue(loader); 2095 outVal.put(key, value); 2096 N--; 2097 } 2098 } 2099 readListInternal(List outVal, int N, ClassLoader loader)2100 private void readListInternal(List outVal, int N, 2101 ClassLoader loader) { 2102 while (N > 0) { 2103 Object value = readValue(loader); 2104 //Log.d(TAG, "Unmarshalling value=" + value); 2105 outVal.add(value); 2106 N--; 2107 } 2108 } 2109 readArrayInternal(Object[] outVal, int N, ClassLoader loader)2110 private void readArrayInternal(Object[] outVal, int N, 2111 ClassLoader loader) { 2112 for (int i = 0; i < N; i++) { 2113 Object value = readValue(loader); 2114 //Log.d(TAG, "Unmarshalling value=" + value); 2115 outVal[i] = value; 2116 } 2117 } 2118 readSparseArrayInternal(SparseArray outVal, int N, ClassLoader loader)2119 private void readSparseArrayInternal(SparseArray outVal, int N, 2120 ClassLoader loader) { 2121 while (N > 0) { 2122 int key = readInt(); 2123 Object value = readValue(loader); 2124 //Log.i(TAG, "Unmarshalling key=" + key + " value=" + value); 2125 outVal.append(key, value); 2126 N--; 2127 } 2128 } 2129 2130 readSparseBooleanArrayInternal(SparseBooleanArray outVal, int N)2131 private void readSparseBooleanArrayInternal(SparseBooleanArray outVal, int N) { 2132 while (N > 0) { 2133 int key = readInt(); 2134 boolean value = this.readByte() == 1; 2135 //Log.i(TAG, "Unmarshalling key=" + key + " value=" + value); 2136 outVal.append(key, value); 2137 N--; 2138 } 2139 } 2140 } 2141