1 package com.xtremelabs.robolectric.shadows; 2 3 import static com.xtremelabs.robolectric.Robolectric.shadowOf; 4 5 import android.os.Bundle; 6 import android.os.Parcel; 7 import android.os.Parcelable; 8 import android.text.TextUtils; 9 import android.util.Log; 10 import android.util.Pair; 11 12 import com.xtremelabs.robolectric.Robolectric; 13 import com.xtremelabs.robolectric.bytecode.ShadowWrangler; 14 import com.xtremelabs.robolectric.internal.Implementation; 15 import com.xtremelabs.robolectric.internal.Implements; 16 import com.xtremelabs.robolectric.internal.RealObject; 17 18 import java.lang.reflect.Field; 19 import java.util.ArrayList; 20 import java.util.HashMap; 21 import java.util.List; 22 import java.util.Map; 23 import java.util.Set; 24 25 @Implements(Parcel.class) 26 @SuppressWarnings("unchecked") 27 public class ShadowParcel { 28 29 private static final int VAL_NULL = -1; 30 private static final int VAL_STRING = 0; 31 private static final int VAL_INTEGER = 1; 32 private static final int VAL_MAP = 2; 33 private static final int VAL_BUNDLE = 3; 34 private static final int VAL_PARCELABLE = 4; 35 private static final int VAL_SHORT = 5; 36 private static final int VAL_LONG = 6; 37 private static final int VAL_FLOAT = 7; 38 private static final int VAL_DOUBLE = 8; 39 private static final int VAL_BOOLEAN = 9; 40 private static final int VAL_CHARSEQUENCE = 10; 41 private static final int VAL_LIST = 11; 42 private static final int VAL_BYTEARRAY = 13; 43 private static final int VAL_STRINGARRAY = 14; 44 private static final int VAL_PARCELABLEARRAY = 16; 45 private static final int VAL_OBJECTARRAY = 17; 46 private static final int VAL_INTARRAY = 18; 47 private static final int VAL_LONGARRAY = 19; 48 private static final int VAL_BYTE = 20; 49 private static final int VAL_BOOLEANARRAY = 23; 50 private static final int VAL_CHARSEQUENCEARRAY = 24; 51 52 private final ArrayList<Pair<Integer, ?>> parcelData = new ArrayList<Pair<Integer, ?>>(); 53 private int index = 0; 54 55 @RealObject 56 private Parcel realParcel; 57 58 @Implementation obtain()59 public static Parcel obtain() { 60 return Robolectric.newInstanceOf(Parcel.class); 61 } 62 63 @Implementation dataAvail()64 public int dataAvail() { 65 return dataSize() - dataPosition(); 66 } 67 68 @Implementation dataPosition()69 public int dataPosition() { 70 return calculateSizeToIndex(index); 71 } 72 73 @Implementation dataSize()74 public int dataSize() { 75 return calculateSizeToIndex(parcelData.size()); 76 } 77 78 @Implementation dataCapacity()79 public int dataCapacity() { 80 return dataSize(); 81 } 82 83 @Implementation setDataPosition(int pos)84 public void setDataPosition(int pos) { 85 index = calculateIndexFromSizePosition(pos); 86 } 87 calculateSizeToIndex(int index)88 private int calculateSizeToIndex(int index) { 89 int size = 0; 90 for (int i = 0; i < index; i++) { 91 size += parcelData.get(i).first; 92 } 93 return size; 94 } 95 calculateIndexFromSizePosition(int pos)96 private int calculateIndexFromSizePosition(int pos) { 97 int size = 0; 98 for (int i = 0; i < parcelData.size(); i++) { 99 if (size >= pos) { 100 return i; 101 } 102 size += parcelData.get(i).first; 103 } 104 return parcelData.size(); 105 } 106 107 @Implementation writeString(String str)108 public void writeString(String str) { 109 if (str == null) { 110 writeInt(-1); 111 } else { 112 writeInt(str.length()); 113 addValueToList(Pair.create(str.length(), str)); 114 } 115 } 116 117 @Implementation readString()118 public String readString() { 119 int N = readInt(); 120 if (N < 0) { 121 return null; 122 } else { 123 return readValueFromList(null); 124 } 125 } 126 127 @Implementation readCharSequence()128 public CharSequence readCharSequence() { 129 return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(realParcel); 130 } 131 132 @Implementation writeCharSequence(CharSequence val)133 public void writeCharSequence(CharSequence val) { 134 TextUtils.writeToParcel(val, realParcel, 0); 135 } 136 137 @Implementation writeInt(int i)138 public void writeInt(int i) { 139 addValueToList(Pair.create(Integer.SIZE / 8, i)); 140 } 141 142 @Implementation readInt()143 public int readInt() { 144 return readValueFromList(0); 145 } 146 147 @Implementation writeLong(long i)148 public void writeLong(long i) { 149 addValueToList(Pair.create(Long.SIZE / 8, i)); 150 } 151 152 @Implementation readLong()153 public long readLong() { 154 return readValueFromList((long) 0); 155 } 156 157 @Implementation writeFloat(float f)158 public void writeFloat(float f) { 159 addValueToList(Pair.create(Float.SIZE / 8, f)); 160 } 161 162 @Implementation readFloat()163 public float readFloat() { 164 return readValueFromList((float) 0); 165 } 166 167 @Implementation writeDouble(double f)168 public void writeDouble(double f) { 169 addValueToList(Pair.create(Double.SIZE / 8, f)); 170 } 171 172 @Implementation readDouble()173 public double readDouble() { 174 return readValueFromList((double) 0); 175 } 176 writeBoolean(boolean b)177 public void writeBoolean(boolean b) { 178 addValueToList(Pair.create(1, b)); 179 } 180 readBoolean()181 public boolean readBoolean() { 182 return readValueFromList(false); 183 } 184 writeChar(char c)185 public void writeChar(char c) { 186 addValueToList(Pair.create(Character.SIZE / 8, c)); 187 } 188 readChar()189 public char readChar() { 190 return readValueFromList((char) 0); 191 } 192 193 @Implementation 194 @SuppressWarnings("unchecked") writeByte(byte b)195 public void writeByte(byte b) { 196 addValueToList(Pair.create(Byte.SIZE / 8, b)); 197 } 198 199 @Implementation readByte()200 public byte readByte() { 201 return readValueFromList((byte) 0); 202 } 203 204 @Implementation readBooleanArray(boolean[] val)205 public void readBooleanArray(boolean[] val) { 206 int N = readInt(); 207 if (val.length != N) 208 throw new RuntimeException("bad array lengths"); 209 for (int i = 0; i < val.length; i++) { 210 val[i] = readBoolean(); 211 } 212 } 213 214 @Implementation writeBooleanArray(boolean[] val)215 public void writeBooleanArray(boolean[] val) { 216 if (val == null) { 217 writeInt(-1); 218 return; 219 } 220 writeInt(val.length); 221 for (boolean b : val) 222 writeBoolean(b); 223 } 224 225 @Implementation createBooleanArray()226 public boolean[] createBooleanArray() { 227 int N = readInt(); 228 if (N < 0) { 229 return null; 230 } 231 boolean[] val = new boolean[N]; 232 for (int i = 0; i < val.length; i++) { 233 val[i] = readBoolean(); 234 } 235 return val; 236 } 237 238 @Implementation readCharArray(char[] val)239 public void readCharArray(char[] val) { 240 int N = readInt(); 241 if (val.length != N) 242 throw new RuntimeException("bad array lengths"); 243 for (int i = 0; i < val.length; i++) { 244 val[i] = readChar(); 245 } 246 } 247 248 @Implementation writeCharArray(char[] val)249 public void writeCharArray(char[] val) { 250 if (val == null) { 251 writeInt(-1); 252 return; 253 } 254 writeInt(val.length); 255 for (char b : val) 256 writeChar(b); 257 } 258 259 @Implementation createCharArray()260 public char[] createCharArray() { 261 int N = readInt(); 262 if (N < 0) { 263 return null; 264 } 265 char[] val = new char[N]; 266 for (int i = 0; i < val.length; i++) { 267 val[i] = readChar(); 268 } 269 return val; 270 } 271 272 @Implementation readFloatArray(float[] val)273 public void readFloatArray(float[] val) { 274 int N = readInt(); 275 if (val.length != N) 276 throw new RuntimeException("bad array lengths"); 277 for (int i = 0; i < val.length; i++) { 278 val[i] = readFloat(); 279 } 280 } 281 282 @Implementation writeFloatArray(float[] val)283 public void writeFloatArray(float[] val) { 284 if (val == null) { 285 writeInt(-1); 286 return; 287 } 288 writeInt(val.length); 289 for (float f : val) 290 writeFloat(f); 291 } 292 293 @Implementation createFloatArray()294 public float[] createFloatArray() { 295 int N = readInt(); 296 if (N < 0) { 297 return null; 298 } 299 float[] val = new float[N]; 300 for (int i = 0; i < val.length; i++) { 301 val[i] = readFloat(); 302 } 303 return val; 304 } 305 306 @Implementation writeDoubleArray(double[] val)307 public void writeDoubleArray(double[] val) { 308 if (val == null) { 309 writeInt(-1); 310 return; 311 } 312 writeInt(val.length); 313 for (double f : val) 314 writeDouble(f); 315 } 316 317 @Implementation readDoubleArray(double[] val)318 public void readDoubleArray(double[] val) { 319 int N = readInt(); 320 if (val.length != N) 321 throw new RuntimeException("bad array lengths"); 322 for (int i = 0; i < val.length; i++) { 323 val[i] = readDouble(); 324 } 325 } 326 327 @Implementation createDoubleArray()328 public double[] createDoubleArray() { 329 int N = readInt(); 330 if (N < 0) { 331 return null; 332 } 333 double[] val = new double[N]; 334 for (int i = 0; i < val.length; i++) { 335 val[i] = readDouble(); 336 } 337 return val; 338 } 339 340 @Implementation writeIntArray(int[] val)341 public void writeIntArray(int[] val) { 342 if (val == null) { 343 writeInt(-1); 344 return; 345 } 346 writeInt(val.length); 347 for (int f : val) 348 writeInt(f); 349 } 350 351 @Implementation readIntArray(int[] val)352 public void readIntArray(int[] val) { 353 int N = readInt(); 354 if (val.length != N) 355 throw new RuntimeException("bad array lengths"); 356 for (int i = 0; i < val.length; i++) { 357 val[i] = readInt(); 358 } 359 } 360 361 @Implementation createIntArray()362 public int[] createIntArray() { 363 int N = readInt(); 364 if (N < 0) { 365 return null; 366 } 367 int[] val = new int[N]; 368 for (int i = 0; i < val.length; i++) { 369 val[i] = readInt(); 370 } 371 return val; 372 } 373 374 @Implementation writeByteArray(byte[] val)375 public void writeByteArray(byte[] val) { 376 if (val == null) { 377 writeInt(-1); 378 return; 379 } 380 writeInt(val.length); 381 for (byte f : val) 382 writeByte(f); 383 } 384 385 @Implementation readByteArray(byte[] val)386 public void readByteArray(byte[] val) { 387 int N = readInt(); 388 if (val.length != N) 389 throw new RuntimeException("bad array lengths"); 390 for (int i = 0; i < val.length; i++) { 391 val[i] = readByte(); 392 } 393 } 394 395 @Implementation createByteArray()396 public byte[] createByteArray() { 397 int N = readInt(); 398 if (N < 0) { 399 return null; 400 } 401 byte[] val = new byte[N]; 402 for (int i = 0; i < val.length; i++) { 403 val[i] = readByte(); 404 } 405 return val; 406 } 407 408 @Implementation writeLongArray(long[] val)409 public void writeLongArray(long[] val) { 410 if (val == null) { 411 writeInt(-1); 412 return; 413 } 414 writeInt(val.length); 415 for (long f : val) 416 writeLong(f); 417 } 418 419 @Implementation readLongArray(long[] val)420 public void readLongArray(long[] val) { 421 int N = readInt(); 422 if (val.length != N) 423 throw new RuntimeException("bad array lengths"); 424 for (int i = 0; i < val.length; i++) { 425 val[i] = readLong(); 426 } 427 } 428 429 @Implementation createLongArray()430 public long[] createLongArray() { 431 int N = readInt(); 432 if (N < 0) { 433 return null; 434 } 435 long[] val = new long[N]; 436 for (int i = 0; i < val.length; i++) { 437 val[i] = readLong(); 438 } 439 return val; 440 } 441 442 @Implementation writeStringArray(String[] val)443 public void writeStringArray(String[] val) { 444 if (val == null) { 445 writeInt(-1); 446 return; 447 } 448 writeInt(val.length); 449 for (String f : val) 450 writeString(f); 451 } 452 453 @Implementation createStringArray()454 public String[] createStringArray() { 455 String[] array = null; 456 457 int N = readInt(); 458 if (N >= 0) { 459 array = new String[N]; 460 for (int i = 0; i < N; i++) { 461 array[i] = readString(); 462 } 463 } 464 return array; 465 } 466 467 @Implementation readStringArray(String[] dest)468 public void readStringArray(String[] dest) { 469 int N = readInt(); 470 if (dest.length != N) 471 throw new RuntimeException("bad array lengths"); 472 for (int i = 0; i < dest.length; i++) { 473 dest[i] = readString(); 474 } 475 } 476 477 @Implementation writeStringList(List<String> strings)478 public void writeStringList(List<String> strings) { 479 if (strings == null) { 480 writeInt(-1); 481 return; 482 } 483 int count = strings.size(); 484 int i = 0; 485 writeInt(count); 486 while (i < count) { 487 writeString(strings.get(i)); 488 i++; 489 } 490 } 491 492 @Implementation readStringList(List<String> list)493 public void readStringList(List<String> list) { 494 int listSizeBeforeChange = list.size(); 495 int addCount = readInt(); 496 int i = 0; 497 for (; i < listSizeBeforeChange && i < addCount; i++) { 498 list.set(i, readString()); 499 } 500 for (; i < addCount; i++) { 501 list.add(readString()); 502 } 503 for (; i < listSizeBeforeChange; i++) { 504 list.remove(addCount); 505 } 506 } 507 508 @Implementation createStringArrayList()509 public ArrayList<String> createStringArrayList() { 510 int N = readInt(); 511 if (N < 0) { 512 return null; 513 } 514 515 ArrayList<String> l = new ArrayList<String>(N); 516 while (N > 0) { 517 l.add(readString()); 518 N--; 519 } 520 return l; 521 } 522 523 @Implementation writeCharSequenceArray(CharSequence[] val)524 public void writeCharSequenceArray(CharSequence[] val) { 525 if (val != null) { 526 int N = val.length; 527 writeInt(N); 528 for (int i=0; i<N; i++) { 529 writeCharSequence(val[i]); 530 } 531 } else { 532 writeInt(-1); 533 } 534 } 535 536 @Implementation readCharSequenceArray()537 public CharSequence[] readCharSequenceArray() { 538 CharSequence[] array = null; 539 540 int length = readInt(); 541 if (length >= 0) 542 { 543 array = new CharSequence[length]; 544 545 for (int i = 0 ; i < length ; i++) 546 { 547 array[i] = readCharSequence(); 548 } 549 } 550 551 return array; 552 } 553 554 @Implementation writeList(List val)555 public void writeList(List val) { 556 if (val == null) { 557 writeInt(-1); 558 return; 559 } 560 int N = val.size(); 561 int i = 0; 562 writeInt(N); 563 while (i < N) { 564 writeValue(val.get(i)); 565 i++; 566 } 567 } 568 569 @Implementation readList(List outVal, ClassLoader loader)570 public void readList(List outVal, ClassLoader loader) { 571 int N = readInt(); 572 readListInternal(outVal, N, loader); 573 } 574 575 @Implementation readArrayList(ClassLoader loader)576 public ArrayList readArrayList(ClassLoader loader) { 577 int N = readInt(); 578 if (N < 0) { 579 return null; 580 } 581 ArrayList l = new ArrayList(N); 582 readListInternal(l, N, loader); 583 return l; 584 } 585 586 @Implementation writeArray(Object[] values)587 public void writeArray(Object[] values) { 588 if (values == null) { 589 writeInt(-1); 590 return; 591 } 592 int N = values.length; 593 writeInt(N); 594 for (Object value : values) { 595 writeValue(value); 596 } 597 } 598 599 @Implementation readArray(ClassLoader loader)600 public Object[] readArray(ClassLoader loader) { 601 int N = readInt(); 602 if (N < 0) { 603 return null; 604 } 605 Object[] l = new Object[N]; 606 readArrayInternal(l, N, loader); 607 return l; 608 } 609 610 @Implementation writeValue(Object v)611 public void writeValue(Object v) { 612 if (v == null) { 613 writeInt(VAL_NULL); 614 } else if (v instanceof String) { 615 writeInt(VAL_STRING); 616 writeString((String) v); 617 } else if (v instanceof Integer) { 618 writeInt(VAL_INTEGER); 619 writeInt((Integer) v); 620 } else if (v instanceof Map) { 621 writeInt(VAL_MAP); 622 writeMap((Map) v); 623 } else if (v instanceof Bundle) { 624 // Must be before Parcelable 625 writeInt(VAL_BUNDLE); 626 writeBundle((Bundle) v); 627 } else if (v instanceof Parcelable) { 628 writeInt(VAL_PARCELABLE); 629 writeParcelable((Parcelable) v, 0); 630 } else if (v instanceof Short) { 631 writeInt(VAL_SHORT); 632 writeInt(((Short) v).intValue()); 633 } else if (v instanceof Long) { 634 writeInt(VAL_LONG); 635 writeLong((Long) v); 636 } else if (v instanceof Float) { 637 writeInt(VAL_FLOAT); 638 writeFloat((Float) v); 639 } else if (v instanceof Double) { 640 writeInt(VAL_DOUBLE); 641 writeDouble((Double) v); 642 } else if (v instanceof Boolean) { 643 writeInt(VAL_BOOLEAN); 644 writeInt((Boolean) v ? 1 : 0); 645 } else if (v instanceof CharSequence) { 646 // Must be after String 647 writeInt(VAL_CHARSEQUENCE); 648 writeCharSequence((CharSequence) v); 649 } else if (v instanceof List) { 650 writeInt(VAL_LIST); 651 writeList((List) v); 652 } else if (v instanceof boolean[]) { 653 writeInt(VAL_BOOLEANARRAY); 654 writeBooleanArray((boolean[]) v); 655 } else if (v instanceof byte[]) { 656 writeInt(VAL_BYTEARRAY); 657 writeByteArray((byte[]) v); 658 } else if (v instanceof String[]) { 659 writeInt(VAL_STRINGARRAY); 660 writeStringArray((String[]) v); 661 } else if (v instanceof CharSequence[]) { 662 // Must be after String[] and before Object[] 663 writeInt(VAL_CHARSEQUENCEARRAY); 664 writeCharSequenceArray((CharSequence[]) v); 665 } else if (v instanceof Parcelable[]) { 666 writeInt(VAL_PARCELABLEARRAY); 667 writeParcelableArray((Parcelable[]) v, 0); 668 } else if (v instanceof Object[]) { 669 writeInt(VAL_OBJECTARRAY); 670 writeArray((Object[]) v); 671 } else if (v instanceof int[]) { 672 writeInt(VAL_INTARRAY); 673 writeIntArray((int[]) v); 674 } else if (v instanceof long[]) { 675 writeInt(VAL_LONGARRAY); 676 writeLongArray((long[]) v); 677 } else if (v instanceof Byte) { 678 writeInt(VAL_BYTE); 679 writeByte((Byte) v); 680 } else { 681 throw new RuntimeException( 682 "Parcel: unable to marshal value with type" + v.getClass().getName()); 683 } 684 } 685 686 @Implementation readValue(ClassLoader loader)687 public Object readValue(ClassLoader loader) { 688 int type = readInt(); 689 690 switch (type) { 691 case VAL_NULL: 692 return null; 693 694 case VAL_STRING: 695 return readString(); 696 697 case VAL_INTEGER: 698 return readInt(); 699 700 case VAL_MAP: 701 return readHashMap(loader); 702 703 case VAL_PARCELABLE: 704 return readParcelable(loader); 705 706 case VAL_SHORT: 707 return (short) readInt(); 708 709 case VAL_LONG: 710 return readLong(); 711 712 case VAL_FLOAT: 713 return readFloat(); 714 715 case VAL_DOUBLE: 716 return readDouble(); 717 718 case VAL_BOOLEAN: 719 return readInt() == 1; 720 721 case VAL_CHARSEQUENCE: 722 return readCharSequence(); 723 724 case VAL_LIST: 725 return readArrayList(loader); 726 727 case VAL_BOOLEANARRAY: 728 return createBooleanArray(); 729 730 case VAL_BYTEARRAY: 731 return createByteArray(); 732 733 case VAL_STRINGARRAY: 734 return createStringArray(); 735 736 case VAL_CHARSEQUENCEARRAY: 737 return readCharSequenceArray(); 738 739 case VAL_OBJECTARRAY: 740 return readArray(loader); 741 742 case VAL_INTARRAY: 743 return createIntArray(); 744 745 case VAL_LONGARRAY: 746 return createLongArray(); 747 748 case VAL_BYTE: 749 return readByte(); 750 751 case VAL_PARCELABLEARRAY: 752 return readParcelableArray(loader); 753 754 case VAL_BUNDLE: 755 return readBundle(loader); // loading will be deferred 756 757 default: 758 int off = dataPosition() - 4; 759 throw new RuntimeException( 760 "Parcel " + this + ": Unmarshalling unknown type code " + type 761 + " at offset " + off); 762 } 763 } 764 765 @Implementation readBundle()766 public Bundle readBundle() { 767 return readBundle(null); 768 } 769 770 @Implementation readBundle(ClassLoader loader)771 public Bundle readBundle(ClassLoader loader) { 772 int offset = dataPosition(); 773 int N = readInt(); 774 if (N < 0) { 775 return null; 776 } 777 int magic = readInt(); 778 if (magic != 0x4C444E42) { 779 throw new RuntimeException("Magic number missing from bundle stream"); 780 } 781 782 Bundle bundle = new Bundle(); 783 784 // Read map 785 HashMap m = new HashMap(); 786 readMap(m, null); 787 788 shadowOf(bundle).map.putAll(m); 789 790 return bundle; 791 } 792 793 @Implementation writeBundle(Bundle val)794 public void writeBundle(Bundle val) { 795 if (val == null) { 796 writeInt(-1); 797 return; 798 } 799 800 writeInt(-1); // dummy, will hold length 801 int oldPos = dataPosition(); 802 writeInt(0x4C444E42); // 'B' 'N' 'D' 'L' 803 804 writeMapInternal(shadowOf(val).map); 805 int newPos = dataPosition(); 806 807 // Backpatch length 808 setDataPosition(oldPos - 4); 809 int N = newPos - oldPos; 810 writeInt(N); 811 setDataPosition(newPos); 812 } 813 814 @Implementation writeParcelable(Parcelable p, int flags)815 public void writeParcelable(Parcelable p, int flags) { 816 if (p == null) { 817 writeString(null); 818 return; 819 } 820 String name = p.getClass().getName(); 821 writeString(name); 822 p.writeToParcel(realParcel, flags); 823 } 824 825 @Implementation readParcelable(ClassLoader loader)826 public <T extends Parcelable> T readParcelable(ClassLoader loader) { 827 String name = readString(); 828 if (name == null) { 829 return null; 830 } 831 Parcelable.Creator<T> creator; 832 try { 833 Class c = loader == null ? Class.forName(name) : Class.forName(name, true, loader); 834 Field f = c.getField("CREATOR"); 835 creator = (Parcelable.Creator) f.get(null); 836 } catch (IllegalAccessException e) { 837 Log.e("Parcel", "Class not found when unmarshalling: " + name + ", e: " + e); 838 throw new RuntimeException("IllegalAccessException when unmarshalling: " + name); 839 } catch (ClassNotFoundException e) { 840 Log.e("Parcel", "Class not found when unmarshalling: " + name + ", e: " + e); 841 throw new RuntimeException("ClassNotFoundException when unmarshalling: " + name); 842 } catch (ClassCastException e) { 843 throw new RuntimeException("Parcelable protocol requires a " 844 + "Parcelable.Creator object called " + " CREATOR on class " + name); 845 } catch (NoSuchFieldException e) { 846 throw new RuntimeException("Parcelable protocol requires a " 847 + "Parcelable.Creator object called " + " CREATOR on class " + name); 848 } 849 if (creator == null) { 850 throw new RuntimeException("Parcelable protocol requires a " 851 + "Parcelable.Creator object called " + " CREATOR on class " + name); 852 } 853 854 return creator.createFromParcel(realParcel); 855 } 856 857 @Implementation createTypedArrayList(Parcelable.Creator c)858 public ArrayList createTypedArrayList(Parcelable.Creator c) { 859 int N = readInt(); 860 if (N < 0) { 861 return null; 862 } 863 864 ArrayList l = new ArrayList(N); 865 866 while (N > 0) { 867 if (readInt() != 0) { 868 l.add(c.createFromParcel(realParcel)); 869 } else { 870 l.add(null); 871 } 872 N--; 873 } 874 return l; 875 } 876 877 @Implementation writeTypedList(List val)878 public void writeTypedList(List val) { 879 if (val == null) { 880 writeInt(-1); 881 return; 882 } 883 884 int N = val.size(); 885 int i = 0; 886 writeInt(N); 887 while (i < N) { 888 Object item = val.get(i); 889 if (item != null) { 890 writeInt(1); 891 ((Parcelable) item).writeToParcel(realParcel, 0); 892 } else { 893 writeInt(0); 894 } 895 i++; 896 } 897 } 898 899 @Implementation writeParcelableArray(T[] value, int parcelableFlags)900 public <T extends Parcelable> void writeParcelableArray(T[] value, 901 int parcelableFlags) { 902 if (value != null) { 903 int N = value.length; 904 writeInt(N); 905 for (int i=0; i<N; i++) { 906 writeParcelable(value[i], parcelableFlags); 907 } 908 } else { 909 writeInt(-1); 910 } 911 } 912 913 @Implementation readParcelableArray(ClassLoader loader)914 public Parcelable[] readParcelableArray(ClassLoader loader) { 915 int N = readInt(); 916 if (N < 0) { 917 return null; 918 } 919 Parcelable[] p = new Parcelable[N]; 920 for (int i = 0; i < N; i++) { 921 p[i] = readParcelable(loader); 922 } 923 return p; 924 } 925 926 @Implementation writeMap(Map val)927 public void writeMap(Map val) { 928 writeMapInternal(val); 929 } 930 931 @Implementation readMap(Map outVal, ClassLoader loader)932 public void readMap(Map outVal, ClassLoader loader) { 933 int N = readInt(); 934 readMapInternal(outVal, N, loader); 935 } 936 937 @Implementation readHashMap(ClassLoader loader)938 public HashMap readHashMap(ClassLoader loader) { 939 int N = readInt(); 940 if (N < 0) { 941 return null; 942 } 943 HashMap m = new HashMap(N); 944 readMapInternal(m, N, loader); 945 return m; 946 } 947 writeMapInternal(Map<String, Object> val)948 private void writeMapInternal(Map<String, Object> val) { 949 if (val == null) { 950 writeInt(-1); 951 return; 952 } 953 954 Set<Map.Entry<String, Object>> entries = val.entrySet(); 955 writeInt(entries.size()); 956 for (Map.Entry<String, Object> e : entries) { 957 writeValue(e.getKey()); 958 writeValue(e.getValue()); 959 } 960 } 961 readMapInternal(Map outVal, int N, ClassLoader loader)962 private void readMapInternal(Map outVal, int N, ClassLoader loader) { 963 for (int i = 0; i < N; i++) { 964 Object key = readValue(loader); 965 Object value = readValue(loader); 966 outVal.put(key, value); 967 } 968 } 969 readListInternal(List outVal, int N, ClassLoader loader)970 private void readListInternal(List outVal, int N, ClassLoader loader) { 971 while (N > 0) { 972 Object value = readValue(loader); 973 outVal.add(value); 974 N--; 975 } 976 } 977 readArrayInternal(Object[] outVal, int N, ClassLoader loader)978 private void readArrayInternal(Object[] outVal, int N, ClassLoader loader) { 979 for (int i = 0; i < N; i++) { 980 Object value = readValue(loader); 981 outVal[i] = value; 982 } 983 } 984 addValueToList(Pair<Integer, ?> value)985 private void addValueToList(Pair<Integer, ?> value) { 986 if (index < parcelData.size()) { 987 parcelData.set(index, value); 988 } else { 989 parcelData.add(value); 990 } 991 index++; 992 } 993 readValueFromList(T defaultValue)994 private <T extends Object> T readValueFromList(T defaultValue) { 995 if (index < parcelData.size()) { 996 return (T) parcelData.get(index++).second; 997 } else { 998 return defaultValue; 999 } 1000 } 1001 getIndex()1002 public int getIndex() { 1003 return index; 1004 } 1005 getParcelData()1006 public List getParcelData() { 1007 return parcelData; 1008 } 1009 } 1010