1 /* 2 * Copyright (C) 2008 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.cts; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertArrayEquals; 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertFalse; 24 import static org.junit.Assert.assertNotNull; 25 import static org.junit.Assert.assertNotSame; 26 import static org.junit.Assert.assertNull; 27 import static org.junit.Assert.assertSame; 28 import static org.junit.Assert.assertThrows; 29 import static org.junit.Assert.assertTrue; 30 import static org.junit.Assert.fail; 31 32 import static java.util.Collections.singletonList; 33 34 import android.content.Intent; 35 import android.os.Bundle; 36 import android.os.Parcel; 37 import android.os.ParcelFileDescriptor; 38 import android.os.Parcelable; 39 import android.platform.test.annotations.AppModeSdkSandbox; 40 import android.platform.test.annotations.IgnoreUnderRavenwood; 41 import android.platform.test.ravenwood.RavenwoodRule; 42 import android.text.Spannable; 43 import android.text.SpannableString; 44 import android.text.style.ForegroundColorSpan; 45 import android.util.SparseArray; 46 47 import org.junit.After; 48 import org.junit.Before; 49 import org.junit.Rule; 50 import org.junit.Test; 51 52 import java.io.File; 53 import java.io.FileDescriptor; 54 import java.io.FileNotFoundException; 55 import java.io.IOException; 56 import java.io.ObjectInputStream; 57 import java.io.Serializable; 58 import java.util.ArrayList; 59 import java.util.Arrays; 60 import java.util.Objects; 61 import java.util.Set; 62 import java.util.concurrent.Callable; 63 64 @AppModeSdkSandbox(reason = "Allow test in the SDK sandbox (does not prevent other modes).") 65 public class BundleTest { 66 @Rule public RavenwoodRule mRavenwood = new RavenwoodRule(); 67 68 private static final boolean BOOLEANKEYVALUE = false; 69 private static final int INTKEYVALUE = 20; 70 private static final String INTKEY = "intkey"; 71 private static final String BOOLEANKEY = "booleankey"; 72 73 /** Keys should be in hash code order */ 74 private static final String KEY1 = "key1"; 75 private static final String KEY2 = "key2"; 76 77 private Bundle mBundle; 78 private Spannable mSpannable; 79 80 @Before setUp()81 public void setUp() throws Exception { 82 mBundle = new Bundle(); 83 mBundle.setClassLoader(getClass().getClassLoader()); 84 } 85 initSpannable()86 private void initSpannable() { 87 mSpannable = new SpannableString("foo bar"); 88 mSpannable.setSpan(new ForegroundColorSpan(0x123456), 0, 3, 0); 89 } 90 91 @After tearDown()92 public void tearDown() throws Exception { 93 CustomParcelable.sDeserialized = false; 94 CustomSerializable.sDeserialized = false; 95 } 96 97 @Test testBundle()98 public void testBundle() { 99 final Bundle b1 = new Bundle(); 100 assertTrue(b1.isEmpty()); 101 b1.putBoolean(KEY1, true); 102 assertFalse(b1.isEmpty()); 103 104 final Bundle b2 = new Bundle(b1); 105 assertTrue(b2.getBoolean(KEY1)); 106 107 new Bundle(1024); 108 new Bundle(getClass().getClassLoader()); 109 } 110 111 @Test testEmptyStream()112 public void testEmptyStream() { 113 Parcel p = Parcel.obtain(); 114 p.unmarshall(new byte[] {}, 0, 0); 115 Bundle b = p.readBundle(); 116 assertTrue(b.isEmpty()); 117 mBundle.putBoolean("android", true); 118 p.unmarshall(new byte[] {}, 0, 0); 119 mBundle.readFromParcel(p); 120 assertTrue(mBundle.isEmpty()); 121 } 122 123 // first put sth into tested Bundle, it shouldn't be empty, then clear it and it should be empty 124 @Test testClear()125 public void testClear() { 126 mBundle.putBoolean("android", true); 127 mBundle.putBoolean(KEY1, true); 128 assertFalse(mBundle.isEmpty()); 129 mBundle.clear(); 130 assertTrue(mBundle.isEmpty()); 131 } 132 133 // first clone the tested Bundle, then compare the original Bundle with the 134 // cloned Bundle, they should equal 135 @Test testClone()136 public void testClone() { 137 mBundle.putBoolean(BOOLEANKEY, BOOLEANKEYVALUE); 138 mBundle.putInt(INTKEY, INTKEYVALUE); 139 Bundle cloneBundle = (Bundle) mBundle.clone(); 140 assertEquals(mBundle.size(), cloneBundle.size()); 141 assertEquals(mBundle.getBoolean(BOOLEANKEY), cloneBundle.getBoolean(BOOLEANKEY)); 142 assertEquals(mBundle.getInt(INTKEY), cloneBundle.getInt(INTKEY)); 143 } 144 145 // containsKey would return false if nothing has been put into the Bundle, 146 // else containsKey would return true if any putXXX has been called before 147 @Test testContainsKey()148 public void testContainsKey() { 149 assertFalse(mBundle.containsKey(KEY1)); 150 mBundle.putBoolean(KEY1, true); 151 assertTrue(mBundle.containsKey(KEY1)); 152 roundtrip(); 153 assertTrue(mBundle.containsKey(KEY1)); 154 } 155 156 // get would return null if nothing has been put into the Bundle,else get 157 // would return the value set by putXXX 158 @Test testGet()159 public void testGet() { 160 assertNull(mBundle.get(KEY1)); 161 mBundle.putBoolean(KEY1, true); 162 assertNotNull(mBundle.get(KEY1)); 163 roundtrip(); 164 assertNotNull(mBundle.get(KEY1)); 165 } 166 167 @Test testGetBoolean1()168 public void testGetBoolean1() { 169 assertFalse(mBundle.getBoolean(KEY1)); 170 mBundle.putBoolean(KEY1, true); 171 assertTrue(mBundle.getBoolean(KEY1)); 172 roundtrip(); 173 assertTrue(mBundle.getBoolean(KEY1)); 174 } 175 176 @Test testGetBoolean2()177 public void testGetBoolean2() { 178 assertTrue(mBundle.getBoolean(KEY1, true)); 179 mBundle.putBoolean(KEY1, false); 180 assertFalse(mBundle.getBoolean(KEY1, true)); 181 roundtrip(); 182 assertFalse(mBundle.getBoolean(KEY1, true)); 183 } 184 185 @Test testGetBooleanArray()186 public void testGetBooleanArray() { 187 assertNull(mBundle.getBooleanArray(KEY1)); 188 mBundle.putBooleanArray(KEY1, new boolean[] { 189 true, false, true 190 }); 191 boolean[] booleanArray = mBundle.getBooleanArray(KEY1); 192 assertNotNull(booleanArray); 193 assertEquals(3, booleanArray.length); 194 assertEquals(true, booleanArray[0]); 195 assertEquals(false, booleanArray[1]); 196 assertEquals(true, booleanArray[2]); 197 roundtrip(); 198 booleanArray = mBundle.getBooleanArray(KEY1); 199 assertNotNull(booleanArray); 200 assertEquals(3, booleanArray.length); 201 assertEquals(true, booleanArray[0]); 202 assertEquals(false, booleanArray[1]); 203 assertEquals(true, booleanArray[2]); 204 } 205 206 @Test testGetBundle()207 public void testGetBundle() { 208 assertNull(mBundle.getBundle(KEY1)); 209 final Bundle bundle = new Bundle(); 210 mBundle.putBundle(KEY1, bundle); 211 assertTrue(bundle.equals(mBundle.getBundle(KEY1))); 212 roundtrip(); 213 assertBundleEquals(bundle, mBundle.getBundle(KEY1)); 214 } 215 216 @Test testGetByte1()217 public void testGetByte1() { 218 final byte b = 7; 219 220 assertEquals(0, mBundle.getByte(KEY1)); 221 mBundle.putByte(KEY1, b); 222 assertEquals(b, mBundle.getByte(KEY1)); 223 roundtrip(); 224 assertEquals(b, mBundle.getByte(KEY1)); 225 } 226 227 @Test testGetByte2()228 public void testGetByte2() { 229 final byte b1 = 6; 230 final byte b2 = 7; 231 232 assertEquals((Byte)b1, mBundle.getByte(KEY1, b1)); 233 mBundle.putByte(KEY1, b2); 234 assertEquals((Byte)b2, mBundle.getByte(KEY1, b1)); 235 roundtrip(); 236 assertEquals((Byte)b2, mBundle.getByte(KEY1, b1)); 237 } 238 239 @Test testGetByteArray()240 public void testGetByteArray() { 241 assertNull(mBundle.getByteArray(KEY1)); 242 mBundle.putByteArray(KEY1, new byte[] { 243 1, 2, 3 244 }); 245 byte[] byteArray = mBundle.getByteArray(KEY1); 246 assertNotNull(byteArray); 247 assertEquals(3, byteArray.length); 248 assertEquals(1, byteArray[0]); 249 assertEquals(2, byteArray[1]); 250 assertEquals(3, byteArray[2]); 251 roundtrip(); 252 byteArray = mBundle.getByteArray(KEY1); 253 assertNotNull(byteArray); 254 assertEquals(3, byteArray.length); 255 assertEquals(1, byteArray[0]); 256 assertEquals(2, byteArray[1]); 257 assertEquals(3, byteArray[2]); 258 } 259 260 @Test testGetChar1()261 public void testGetChar1() { 262 final char c = 'l'; 263 264 assertEquals((char)0, mBundle.getChar(KEY1)); 265 mBundle.putChar(KEY1, c); 266 assertEquals(c, mBundle.getChar(KEY1)); 267 roundtrip(); 268 assertEquals(c, mBundle.getChar(KEY1)); 269 } 270 271 @Test testGetChar2()272 public void testGetChar2() { 273 final char c1 = 'l'; 274 final char c2 = 'i'; 275 276 assertEquals(c1, mBundle.getChar(KEY1, c1)); 277 mBundle.putChar(KEY1, c2); 278 assertEquals(c2, mBundle.getChar(KEY1, c1)); 279 roundtrip(); 280 assertEquals(c2, mBundle.getChar(KEY1, c1)); 281 } 282 283 @Test testGetCharArray()284 public void testGetCharArray() { 285 assertNull(mBundle.getCharArray(KEY1)); 286 mBundle.putCharArray(KEY1, new char[] { 287 'h', 'i' 288 }); 289 char[] charArray = mBundle.getCharArray(KEY1); 290 assertEquals('h', charArray[0]); 291 assertEquals('i', charArray[1]); 292 roundtrip(); 293 charArray = mBundle.getCharArray(KEY1); 294 assertEquals('h', charArray[0]); 295 assertEquals('i', charArray[1]); 296 } 297 298 @Test 299 @IgnoreUnderRavenwood(blockedBy = SpannableString.class) testGetCharSequence()300 public void testGetCharSequence() { 301 initSpannable(); 302 final CharSequence cS = "Bruce Lee"; 303 304 assertNull(mBundle.getCharSequence(KEY1)); 305 assertNull(mBundle.getCharSequence(KEY2)); 306 mBundle.putCharSequence(KEY1, cS); 307 mBundle.putCharSequence(KEY2, mSpannable); 308 assertEquals(cS, mBundle.getCharSequence(KEY1)); 309 assertSpannableEquals(mSpannable, mBundle.getCharSequence(KEY2)); 310 roundtrip(); 311 assertEquals(cS, mBundle.getCharSequence(KEY1)); 312 assertSpannableEquals(mSpannable, mBundle.getCharSequence(KEY2)); 313 } 314 315 @Test 316 @IgnoreUnderRavenwood(blockedBy = SpannableString.class) testGetCharSequenceArray()317 public void testGetCharSequenceArray() { 318 initSpannable(); 319 assertNull(mBundle.getCharSequenceArray(KEY1)); 320 mBundle.putCharSequenceArray(KEY1, new CharSequence[] { 321 "one", "two", "three", mSpannable 322 }); 323 CharSequence[] ret = mBundle.getCharSequenceArray(KEY1); 324 assertEquals(4, ret.length); 325 assertEquals("one", ret[0]); 326 assertEquals("two", ret[1]); 327 assertEquals("three", ret[2]); 328 assertSpannableEquals(mSpannable, ret[3]); 329 roundtrip(); 330 ret = mBundle.getCharSequenceArray(KEY1); 331 assertEquals(4, ret.length); 332 assertEquals("one", ret[0]); 333 assertEquals("two", ret[1]); 334 assertEquals("three", ret[2]); 335 assertSpannableEquals(mSpannable, ret[3]); 336 } 337 338 @Test 339 @IgnoreUnderRavenwood(blockedBy = SpannableString.class) testGetCharSequenceArrayList()340 public void testGetCharSequenceArrayList() { 341 initSpannable(); 342 assertNull(mBundle.getCharSequenceArrayList(KEY1)); 343 final ArrayList<CharSequence> list = new ArrayList<CharSequence>(); 344 list.add("one"); 345 list.add("two"); 346 list.add("three"); 347 list.add(mSpannable); 348 mBundle.putCharSequenceArrayList(KEY1, list); 349 roundtrip(); 350 ArrayList<CharSequence> ret = mBundle.getCharSequenceArrayList(KEY1); 351 assertEquals(4, ret.size()); 352 assertEquals("one", ret.get(0)); 353 assertEquals("two", ret.get(1)); 354 assertEquals("three", ret.get(2)); 355 assertSpannableEquals(mSpannable, ret.get(3)); 356 roundtrip(); 357 ret = mBundle.getCharSequenceArrayList(KEY1); 358 assertEquals(4, ret.size()); 359 assertEquals("one", ret.get(0)); 360 assertEquals("two", ret.get(1)); 361 assertEquals("three", ret.get(2)); 362 assertSpannableEquals(mSpannable, ret.get(3)); 363 } 364 365 @Test testGetDouble1()366 public void testGetDouble1() { 367 final double d = 10.07; 368 369 assertEquals(0.0, mBundle.getDouble(KEY1), 0.0); 370 mBundle.putDouble(KEY1, d); 371 assertEquals(d, mBundle.getDouble(KEY1), 0.0); 372 roundtrip(); 373 assertEquals(d, mBundle.getDouble(KEY1), 0.0); 374 } 375 376 @Test testGetDouble2()377 public void testGetDouble2() { 378 final double d1 = 10.06; 379 final double d2 = 10.07; 380 381 assertEquals(d1, mBundle.getDouble(KEY1, d1), 0.0); 382 mBundle.putDouble(KEY1, d2); 383 assertEquals(d2, mBundle.getDouble(KEY1, d1), 0.0); 384 roundtrip(); 385 assertEquals(d2, mBundle.getDouble(KEY1, d1), 0.0); 386 } 387 388 @Test testGetDoubleArray()389 public void testGetDoubleArray() { 390 assertNull(mBundle.getDoubleArray(KEY1)); 391 mBundle.putDoubleArray(KEY1, new double[] { 392 10.06, 10.07 393 }); 394 double[] doubleArray = mBundle.getDoubleArray(KEY1); 395 assertEquals(10.06, doubleArray[0], 0.0); 396 assertEquals(10.07, doubleArray[1], 0.0); 397 roundtrip(); 398 doubleArray = mBundle.getDoubleArray(KEY1); 399 assertEquals(10.06, doubleArray[0], 0.0); 400 assertEquals(10.07, doubleArray[1], 0.0); 401 } 402 403 @Test testGetFloat1()404 public void testGetFloat1() { 405 final float f = 10.07f; 406 407 assertEquals(0.0f, mBundle.getFloat(KEY1), 0.0f); 408 mBundle.putFloat(KEY1, f); 409 assertEquals(f, mBundle.getFloat(KEY1), 0.0f); 410 roundtrip(); 411 assertEquals(f, mBundle.getFloat(KEY1), 0.0f); 412 } 413 414 @Test testGetFloat2()415 public void testGetFloat2() { 416 final float f1 = 10.06f; 417 final float f2 = 10.07f; 418 419 assertEquals(f1, mBundle.getFloat(KEY1, f1), 0.0f); 420 mBundle.putFloat(KEY1, f2); 421 assertEquals(f2, mBundle.getFloat(KEY1, f1), 0.0f); 422 roundtrip(); 423 assertEquals(f2, mBundle.getFloat(KEY1, f1), 0.0f); 424 } 425 426 @Test testGetFloatArray()427 public void testGetFloatArray() { 428 assertNull(mBundle.getFloatArray(KEY1)); 429 mBundle.putFloatArray(KEY1, new float[] { 430 10.06f, 10.07f 431 }); 432 float[] floatArray = mBundle.getFloatArray(KEY1); 433 assertEquals(10.06f, floatArray[0], 0.0f); 434 assertEquals(10.07f, floatArray[1], 0.0f); 435 roundtrip(); 436 floatArray = mBundle.getFloatArray(KEY1); 437 assertEquals(10.06f, floatArray[0], 0.0f); 438 assertEquals(10.07f, floatArray[1], 0.0f); 439 } 440 441 @Test testGetInt1()442 public void testGetInt1() { 443 final int i = 1007; 444 445 assertEquals(0, mBundle.getInt(KEY1)); 446 mBundle.putInt(KEY1, i); 447 assertEquals(i, mBundle.getInt(KEY1)); 448 roundtrip(); 449 assertEquals(i, mBundle.getInt(KEY1)); 450 } 451 452 @Test testGetInt2()453 public void testGetInt2() { 454 final int i1 = 1006; 455 final int i2 = 1007; 456 457 assertEquals(i1, mBundle.getInt(KEY1, i1)); 458 mBundle.putInt(KEY1, i2); 459 assertEquals(i2, mBundle.getInt(KEY1, i2)); 460 roundtrip(); 461 assertEquals(i2, mBundle.getInt(KEY1, i2)); 462 } 463 464 @Test testGetIntArray()465 public void testGetIntArray() { 466 assertNull(mBundle.getIntArray(KEY1)); 467 mBundle.putIntArray(KEY1, new int[] { 468 1006, 1007 469 }); 470 int[] intArray = mBundle.getIntArray(KEY1); 471 assertEquals(1006, intArray[0]); 472 assertEquals(1007, intArray[1]); 473 roundtrip(); 474 intArray = mBundle.getIntArray(KEY1); 475 assertEquals(1006, intArray[0]); 476 assertEquals(1007, intArray[1]); 477 } 478 479 // getIntegerArrayList should only return the IntegerArrayList set by putIntegerArrayLis 480 @Test testGetIntegerArrayList()481 public void testGetIntegerArrayList() { 482 final int i1 = 1006; 483 final int i2 = 1007; 484 485 assertNull(mBundle.getIntegerArrayList(KEY1)); 486 final ArrayList<Integer> arrayList = new ArrayList<Integer>(); 487 arrayList.add(i1); 488 arrayList.add(i2); 489 mBundle.putIntegerArrayList(KEY1, arrayList); 490 ArrayList<Integer> retArrayList = mBundle.getIntegerArrayList(KEY1); 491 assertNotNull(retArrayList); 492 assertEquals(2, retArrayList.size()); 493 assertEquals((Integer)i1, retArrayList.get(0)); 494 assertEquals((Integer)i2, retArrayList.get(1)); 495 roundtrip(); 496 retArrayList = mBundle.getIntegerArrayList(KEY1); 497 assertNotNull(retArrayList); 498 assertEquals(2, retArrayList.size()); 499 assertEquals((Integer)i1, retArrayList.get(0)); 500 assertEquals((Integer)i2, retArrayList.get(1)); 501 } 502 503 @Test testGetLong1()504 public void testGetLong1() { 505 final long l = 1007; 506 507 assertEquals(0, mBundle.getLong(KEY1)); 508 mBundle.putLong(KEY1, l); 509 assertEquals(l, mBundle.getLong(KEY1)); 510 roundtrip(); 511 assertEquals(l, mBundle.getLong(KEY1)); 512 } 513 514 @Test testGetLong2()515 public void testGetLong2() { 516 final long l1 = 1006; 517 final long l2 = 1007; 518 519 assertEquals(l1, mBundle.getLong(KEY1, l1)); 520 mBundle.putLong(KEY1, l2); 521 assertEquals(l2, mBundle.getLong(KEY1, l2)); 522 roundtrip(); 523 assertEquals(l2, mBundle.getLong(KEY1, l2)); 524 } 525 526 @Test testGetLongArray()527 public void testGetLongArray() { 528 assertNull(mBundle.getLongArray(KEY1)); 529 mBundle.putLongArray(KEY1, new long[] { 530 1006, 1007 531 }); 532 long[] longArray = mBundle.getLongArray(KEY1); 533 assertEquals(1006, longArray[0]); 534 assertEquals(1007, longArray[1]); 535 roundtrip(); 536 longArray = mBundle.getLongArray(KEY1); 537 assertEquals(1006, longArray[0]); 538 assertEquals(1007, longArray[1]); 539 } 540 541 @Test testGetParcelable()542 public void testGetParcelable() { 543 assertNull(mBundle.getParcelable(KEY1)); 544 final Bundle bundle = new Bundle(); 545 mBundle.putParcelable(KEY1, bundle); 546 assertTrue(bundle.equals(mBundle.getParcelable(KEY1))); 547 roundtrip(); 548 assertBundleEquals(bundle, (Bundle) mBundle.getParcelable(KEY1)); 549 } 550 551 @Test testGetParcelableTypeSafe_withMismatchingType_returnsNull()552 public void testGetParcelableTypeSafe_withMismatchingType_returnsNull() { 553 mBundle.putParcelable(KEY1, new CustomParcelable(42, "don't panic")); 554 roundtrip(); 555 assertNull(mBundle.getParcelable(KEY1, Intent.class)); 556 assertFalse(CustomParcelable.sDeserialized); 557 } 558 559 @Test testGetParcelableTypeSafe_withMatchingType_returnsObject()560 public void testGetParcelableTypeSafe_withMatchingType_returnsObject() { 561 final CustomParcelable original = new CustomParcelable(42, "don't panic"); 562 mBundle.putParcelable(KEY1, original); 563 roundtrip(); 564 assertEquals(original, mBundle.getParcelable(KEY1, CustomParcelable.class)); 565 } 566 567 @Test testGetParcelableTypeSafe_withBaseType_returnsObject()568 public void testGetParcelableTypeSafe_withBaseType_returnsObject() { 569 final CustomParcelable original = new CustomParcelable(42, "don't panic"); 570 mBundle.putParcelable(KEY1, original); 571 roundtrip(); 572 assertEquals(original, mBundle.getParcelable(KEY1, Parcelable.class)); 573 } 574 575 // getParcelableArray should only return the ParcelableArray set by putParcelableArray 576 @Test testGetParcelableArray()577 public void testGetParcelableArray() { 578 assertNull(mBundle.getParcelableArray(KEY1)); 579 final Bundle bundle1 = new Bundle(); 580 final Bundle bundle2 = new Bundle(); 581 mBundle.putParcelableArray(KEY1, new Bundle[] { 582 bundle1, bundle2 583 }); 584 Parcelable[] parcelableArray = mBundle.getParcelableArray(KEY1); 585 assertEquals(2, parcelableArray.length); 586 assertTrue(bundle1.equals(parcelableArray[0])); 587 assertTrue(bundle2.equals(parcelableArray[1])); 588 roundtrip(); 589 parcelableArray = mBundle.getParcelableArray(KEY1); 590 assertEquals(2, parcelableArray.length); 591 assertBundleEquals(bundle1, (Bundle) parcelableArray[0]); 592 assertBundleEquals(bundle2, (Bundle) parcelableArray[1]); 593 } 594 595 @Test testGetParcelableArrayTypeSafe_withMismatchingType_returnsNull()596 public void testGetParcelableArrayTypeSafe_withMismatchingType_returnsNull() { 597 mBundle.putParcelableArray(KEY1, new CustomParcelable[] { 598 new CustomParcelable(42, "don't panic") 599 }); 600 roundtrip(); 601 assertNull(mBundle.getParcelableArray(KEY1, Intent.class)); 602 assertFalse(CustomParcelable.sDeserialized); 603 } 604 605 @Test testGetParcelableArrayTypeSafe_withMatchingType_returnsObject()606 public void testGetParcelableArrayTypeSafe_withMatchingType_returnsObject() { 607 final CustomParcelable[] original = new CustomParcelable[] { 608 new CustomParcelable(42, "don't panic"), 609 new CustomParcelable(1961, "off we go") 610 }; 611 mBundle.putParcelableArray(KEY1, original); 612 roundtrip(); 613 assertArrayEquals(original, mBundle.getParcelableArray(KEY1, CustomParcelable.class)); 614 } 615 616 @Test testGetParcelableArrayTypeSafe_withBaseType_returnsObject()617 public void testGetParcelableArrayTypeSafe_withBaseType_returnsObject() { 618 final CustomParcelable[] original = new CustomParcelable[] { 619 new CustomParcelable(42, "don't panic"), 620 new CustomParcelable(1961, "off we go") 621 }; 622 mBundle.putParcelableArray(KEY1, original); 623 roundtrip(); 624 assertArrayEquals(original, mBundle.getParcelableArray(KEY1, Parcelable.class)); 625 } 626 627 // getParcelableArrayList should only return the parcelableArrayList set by putParcelableArrayList 628 @Test testGetParcelableArrayList()629 public void testGetParcelableArrayList() { 630 assertNull(mBundle.getParcelableArrayList(KEY1)); 631 final ArrayList<Parcelable> parcelableArrayList = new ArrayList<Parcelable>(); 632 final Bundle bundle1 = new Bundle(); 633 final Bundle bundle2 = new Bundle(); 634 parcelableArrayList.add(bundle1); 635 parcelableArrayList.add(bundle2); 636 mBundle.putParcelableArrayList(KEY1, parcelableArrayList); 637 ArrayList<Parcelable> ret = mBundle.getParcelableArrayList(KEY1); 638 assertEquals(2, ret.size()); 639 assertTrue(bundle1.equals(ret.get(0))); 640 assertTrue(bundle2.equals(ret.get(1))); 641 roundtrip(); 642 ret = mBundle.getParcelableArrayList(KEY1); 643 assertEquals(2, ret.size()); 644 assertBundleEquals(bundle1, (Bundle) ret.get(0)); 645 assertBundleEquals(bundle2, (Bundle) ret.get(1)); 646 } 647 648 @Test testGetParcelableArrayListTypeSafe_withMismatchingType_returnsNull()649 public void testGetParcelableArrayListTypeSafe_withMismatchingType_returnsNull() { 650 final ArrayList<CustomParcelable> originalObjects = new ArrayList<>(); 651 originalObjects.add(new CustomParcelable(42, "don't panic")); 652 mBundle.putParcelableArrayList(KEY1, originalObjects); 653 roundtrip(); 654 assertNull(mBundle.getParcelableArrayList(KEY1, Intent.class)); 655 assertFalse(CustomParcelable.sDeserialized); 656 } 657 658 @Test testGetParcelableArrayListTypeSafe_withMatchingType_returnsObject()659 public void testGetParcelableArrayListTypeSafe_withMatchingType_returnsObject() { 660 final ArrayList<CustomParcelable> original = new ArrayList<>(); 661 original.add(new CustomParcelable(42, "don't panic")); 662 original.add(new CustomParcelable(1961, "off we go")); 663 mBundle.putParcelableArrayList(KEY1, original); 664 roundtrip(); 665 assertEquals(original, mBundle.getParcelableArrayList(KEY1, CustomParcelable.class)); 666 } 667 668 @Test testGetParcelableArrayListTypeSafe_withMismatchingTypeAndDifferentReturnType_returnsNull()669 public void testGetParcelableArrayListTypeSafe_withMismatchingTypeAndDifferentReturnType_returnsNull() { 670 final ArrayList<CustomParcelable> originalObjects = new ArrayList<>(); 671 originalObjects.add(new CustomParcelable(42, "don't panic")); 672 mBundle.putParcelableArrayList(KEY1, originalObjects); 673 roundtrip(); 674 ArrayList<Parcelable> result = mBundle.getParcelableArrayList(KEY1, Intent.class); 675 assertNull(result); 676 assertFalse(CustomParcelable.sDeserialized); 677 } 678 679 @Test testGetParcelableArrayListTypeSafe_withMatchingTypeAndDifferentReturnType__returnsObject()680 public void testGetParcelableArrayListTypeSafe_withMatchingTypeAndDifferentReturnType__returnsObject() { 681 final ArrayList<CustomParcelable> original = new ArrayList<>(); 682 original.add(new CustomParcelable(42, "don't panic")); 683 original.add(new CustomParcelable(1961, "off we go")); 684 mBundle.putParcelableArrayList(KEY1, original); 685 roundtrip(); 686 ArrayList<Parcelable> result = mBundle.getParcelableArrayList(KEY1, CustomParcelable.class); 687 assertEquals(original, result); 688 } 689 690 @Test testGetParcelableArrayListTypeSafe_withBaseType_returnsObject()691 public void testGetParcelableArrayListTypeSafe_withBaseType_returnsObject() { 692 final ArrayList<CustomParcelable> original = new ArrayList<>(); 693 original.add(new CustomParcelable(42, "don't panic")); 694 original.add(new CustomParcelable(1961, "off we go")); 695 mBundle.putParcelableArrayList(KEY1, original); 696 roundtrip(); 697 assertEquals(original, mBundle.getParcelableArrayList(KEY1, Parcelable.class)); 698 } 699 700 @Test testGetSerializableTypeSafe_withMismatchingType_returnsNull()701 public void testGetSerializableTypeSafe_withMismatchingType_returnsNull() { 702 mBundle.putSerializable(KEY1, new CustomSerializable()); 703 roundtrip(); 704 assertNull(mBundle.getSerializable(KEY1, AnotherSerializable.class)); 705 assertFalse(CustomSerializable.sDeserialized); 706 } 707 708 @Test testGetSerializableTypeSafe_withMatchingType_returnsObject()709 public void testGetSerializableTypeSafe_withMatchingType_returnsObject() { 710 mBundle.putSerializable(KEY1, new CustomSerializable()); 711 roundtrip(); 712 assertNotNull(mBundle.getSerializable(KEY1, CustomSerializable.class)); 713 assertTrue(CustomSerializable.sDeserialized); 714 } 715 716 @Test testGetSerializableTypeSafe_withBaseType_returnsObject()717 public void testGetSerializableTypeSafe_withBaseType_returnsObject() { 718 mBundle.putSerializable(KEY1, new CustomSerializable()); 719 roundtrip(); 720 assertNotNull(mBundle.getSerializable(KEY1, Serializable.class)); 721 assertTrue(CustomSerializable.sDeserialized); 722 } 723 724 @Test testGetSerializableWithString()725 public void testGetSerializableWithString() { 726 assertNull(mBundle.getSerializable(KEY1)); 727 String s = "android"; 728 mBundle.putSerializable(KEY1, s); 729 assertEquals(s, mBundle.getSerializable(KEY1)); 730 roundtrip(); 731 assertEquals(s, mBundle.getSerializable(KEY1)); 732 } 733 734 @Test testGetSerializableWithStringArray()735 public void testGetSerializableWithStringArray() { 736 assertNull(mBundle.getSerializable(KEY1)); 737 String[] strings = new String[]{"first", "last"}; 738 mBundle.putSerializable(KEY1, strings); 739 assertEquals(Arrays.asList(strings), 740 Arrays.asList((String[]) mBundle.getSerializable(KEY1))); 741 roundtrip(); 742 assertEquals(Arrays.asList(strings), 743 Arrays.asList((String[]) mBundle.getSerializable(KEY1))); 744 } 745 746 @Test testGetSerializableWithMultiDimensionalObjectArray()747 public void testGetSerializableWithMultiDimensionalObjectArray() { 748 assertNull(mBundle.getSerializable(KEY1)); 749 Object[][] objects = new Object[][] { 750 {"string", 1L} 751 }; 752 mBundle.putSerializable(KEY1, objects); 753 assertEquals(Arrays.asList(objects[0]), 754 Arrays.asList(((Object[][]) mBundle.getSerializable(KEY1))[0])); 755 roundtrip(); 756 assertEquals(Arrays.asList(objects[0]), 757 Arrays.asList(((Object[][]) mBundle.getSerializable(KEY1))[0])); 758 } 759 760 @Test testGetShort1()761 public void testGetShort1() { 762 final short s = 1007; 763 764 assertEquals(0, mBundle.getShort(KEY1)); 765 mBundle.putShort(KEY1, s); 766 assertEquals(s, mBundle.getShort(KEY1)); 767 roundtrip(); 768 assertEquals(s, mBundle.getShort(KEY1)); 769 } 770 771 @Test testGetShort2()772 public void testGetShort2() { 773 final short s1 = 1006; 774 final short s2 = 1007; 775 776 assertEquals(s1, mBundle.getShort(KEY1, s1)); 777 mBundle.putShort(KEY1, s2); 778 assertEquals(s2, mBundle.getShort(KEY1, s1)); 779 roundtrip(); 780 assertEquals(s2, mBundle.getShort(KEY1, s1)); 781 } 782 783 @Test testGetShortArray()784 public void testGetShortArray() { 785 final short s1 = 1006; 786 final short s2 = 1007; 787 788 assertNull(mBundle.getShortArray(KEY1)); 789 mBundle.putShortArray(KEY1, new short[] { 790 s1, s2 791 }); 792 short[] shortArray = mBundle.getShortArray(KEY1); 793 assertEquals(s1, shortArray[0]); 794 assertEquals(s2, shortArray[1]); 795 roundtrip(); 796 shortArray = mBundle.getShortArray(KEY1); 797 assertEquals(s1, shortArray[0]); 798 assertEquals(s2, shortArray[1]); 799 } 800 801 // getSparseParcelableArray should only return the SparseArray<Parcelable> 802 // set by putSparseParcelableArray 803 @Test testGetSparseParcelableArray()804 public void testGetSparseParcelableArray() { 805 assertNull(mBundle.getSparseParcelableArray(KEY1)); 806 final SparseArray<Parcelable> sparseArray = new SparseArray<Parcelable>(); 807 final Bundle bundle = new Bundle(); 808 final CustomParcelable custom = new CustomParcelable(42, "example"); 809 sparseArray.put(1006, bundle); 810 sparseArray.put(1007, custom); 811 mBundle.putSparseParcelableArray(KEY1, sparseArray); 812 SparseArray<Parcelable> ret = mBundle.getSparseParcelableArray(KEY1); 813 assertEquals(2, ret.size()); 814 assertNull(ret.get(1008)); 815 assertTrue(bundle.equals(ret.get(1006))); 816 assertTrue(custom.equals(ret.get(1007))); 817 roundtrip(); 818 ret = mBundle.getSparseParcelableArray(KEY1); 819 assertEquals(2, ret.size()); 820 assertNull(ret.get(1008)); 821 assertBundleEquals(bundle, (Bundle) ret.get(1006)); 822 assertEquals(custom, (CustomParcelable) ret.get(1007)); 823 } 824 825 @Test testGetSparseParcelableArrayTypeSafe_withMismatchingType_returnsNull()826 public void testGetSparseParcelableArrayTypeSafe_withMismatchingType_returnsNull() { 827 final SparseArray<CustomParcelable> originalObjects = new SparseArray<>(); 828 originalObjects.put(42, new CustomParcelable(42, "don't panic")); 829 mBundle.putSparseParcelableArray(KEY1, originalObjects); 830 roundtrip(); 831 assertNull(mBundle.getSparseParcelableArray(KEY1, Intent.class)); 832 assertFalse(CustomParcelable.sDeserialized); 833 } 834 835 @Test testGetSparseParcelableArrayTypeSafe_withMatchingType_returnsObject()836 public void testGetSparseParcelableArrayTypeSafe_withMatchingType_returnsObject() { 837 final SparseArray<CustomParcelable> original = new SparseArray<>(); 838 original.put(42, new CustomParcelable(42, "don't panic")); 839 original.put(1961, new CustomParcelable(1961, "off we go")); 840 mBundle.putSparseParcelableArray(KEY1, original); 841 roundtrip(); 842 assertTrue(original.contentEquals(mBundle.getSparseParcelableArray(KEY1, CustomParcelable.class))); 843 } 844 845 @Test testGetSparseParcelableArrayTypeSafe_withMismatchingTypeAndDifferentReturnType_returnsNull()846 public void testGetSparseParcelableArrayTypeSafe_withMismatchingTypeAndDifferentReturnType_returnsNull() { 847 final SparseArray<CustomParcelable> originalObjects = new SparseArray<>(); 848 originalObjects.put(42, new CustomParcelable(42, "don't panic")); 849 mBundle.putSparseParcelableArray(KEY1, originalObjects); 850 roundtrip(); 851 SparseArray<Parcelable> result = mBundle.getSparseParcelableArray(KEY1, Intent.class); 852 assertNull(result); 853 assertFalse(CustomParcelable.sDeserialized); 854 } 855 856 @Test testGetSparseParcelableArrayTypeSafe_withMatchingTypeAndDifferentReturnType_returnsObject()857 public void testGetSparseParcelableArrayTypeSafe_withMatchingTypeAndDifferentReturnType_returnsObject() { 858 final SparseArray<CustomParcelable> original = new SparseArray<>(); 859 original.put(42, new CustomParcelable(42, "don't panic")); 860 original.put(1961, new CustomParcelable(1961, "off we go")); 861 mBundle.putSparseParcelableArray(KEY1, original); 862 roundtrip(); 863 SparseArray<Parcelable> result = mBundle.getSparseParcelableArray(KEY1, 864 CustomParcelable.class); 865 assertTrue(original.contentEquals(result)); 866 } 867 868 @Test testGetSparseParcelableArrayTypeSafe_withBaseType_returnsObject()869 public void testGetSparseParcelableArrayTypeSafe_withBaseType_returnsObject() { 870 final SparseArray<CustomParcelable> original = new SparseArray<>(); 871 original.put(42, new CustomParcelable(42, "don't panic")); 872 original.put(1961, new CustomParcelable(1961, "off we go")); 873 mBundle.putSparseParcelableArray(KEY1, original); 874 roundtrip(); 875 assertTrue(original.contentEquals(mBundle.getSparseParcelableArray(KEY1, Parcelable.class))); 876 } 877 878 @Test testGetSparseParcelableArrayTypeSafe_withMixedTypes_returnsObject()879 public void testGetSparseParcelableArrayTypeSafe_withMixedTypes_returnsObject() { 880 final SparseArray<Parcelable> original = new SparseArray<>(); 881 original.put(42, new CustomParcelable(42, "don't panic")); 882 original.put(1961, new ComposedParcelable(21, new CustomParcelable(21, "off we go"))); 883 mBundle.putSparseParcelableArray(KEY1, original); 884 roundtrip(); 885 final SparseArray<Parcelable> received = mBundle.getSparseParcelableArray(KEY1, Parcelable.class); 886 assertEquals(original.size(), received.size()); 887 assertEquals(original.get(42), received.get(42)); 888 assertEquals((ComposedParcelable) original.get(1961), 889 (ComposedParcelable) received.get(1961)); 890 } 891 892 @Test testGetString()893 public void testGetString() { 894 assertNull(mBundle.getString(KEY1)); 895 mBundle.putString(KEY1, "android"); 896 assertEquals("android", mBundle.getString(KEY1)); 897 roundtrip(); 898 assertEquals("android", mBundle.getString(KEY1)); 899 } 900 901 @Test testGetStringArray()902 public void testGetStringArray() { 903 assertNull(mBundle.getStringArray(KEY1)); 904 mBundle.putStringArray(KEY1, new String[] { 905 "one", "two", "three" 906 }); 907 String[] ret = mBundle.getStringArray(KEY1); 908 assertEquals("one", ret[0]); 909 assertEquals("two", ret[1]); 910 assertEquals("three", ret[2]); 911 roundtrip(); 912 ret = mBundle.getStringArray(KEY1); 913 assertEquals("one", ret[0]); 914 assertEquals("two", ret[1]); 915 assertEquals("three", ret[2]); 916 } 917 918 // getStringArrayList should only return the StringArrayList set by putStringArrayList 919 @Test testGetStringArrayList()920 public void testGetStringArrayList() { 921 assertNull(mBundle.getStringArrayList(KEY1)); 922 final ArrayList<String> stringArrayList = new ArrayList<String>(); 923 stringArrayList.add("one"); 924 stringArrayList.add("two"); 925 stringArrayList.add("three"); 926 mBundle.putStringArrayList(KEY1, stringArrayList); 927 ArrayList<String> ret = mBundle.getStringArrayList(KEY1); 928 assertEquals(3, ret.size()); 929 assertEquals("one", ret.get(0)); 930 assertEquals("two", ret.get(1)); 931 assertEquals("three", ret.get(2)); 932 roundtrip(); 933 ret = mBundle.getStringArrayList(KEY1); 934 assertEquals(3, ret.size()); 935 assertEquals("one", ret.get(0)); 936 assertEquals("two", ret.get(1)); 937 assertEquals("three", ret.get(2)); 938 } 939 940 @Test testKeySet()941 public void testKeySet() { 942 Set<String> setKey = mBundle.keySet(); 943 assertFalse(setKey.contains("one")); 944 assertFalse(setKey.contains("two")); 945 mBundle.putBoolean("one", true); 946 mBundle.putChar("two", 't'); 947 setKey = mBundle.keySet(); 948 assertEquals(2, setKey.size()); 949 assertTrue(setKey.contains("one")); 950 assertTrue(setKey.contains("two")); 951 assertFalse(setKey.contains("three")); 952 roundtrip(); 953 setKey = mBundle.keySet(); 954 assertEquals(2, setKey.size()); 955 assertTrue(setKey.contains("one")); 956 assertTrue(setKey.contains("two")); 957 assertFalse(setKey.contains("three")); 958 } 959 960 // same as hasFileDescriptors, the only difference is that describeContents 961 // return 0 if no fd and return 1 if has fd for the tested Bundle 962 963 @Test 964 @IgnoreUnderRavenwood(blockedBy = ParcelFileDescriptor.class) testDescribeContents()965 public void testDescribeContents() { 966 assertTrue((mBundle.describeContents() 967 & Parcelable.CONTENTS_FILE_DESCRIPTOR) == 0); 968 969 final Parcel parcel = Parcel.obtain(); 970 try { 971 mBundle.putParcelable("foo", ParcelFileDescriptor.open( 972 new File("/system"), ParcelFileDescriptor.MODE_READ_ONLY)); 973 } catch (FileNotFoundException e) { 974 throw new RuntimeException("can't open /system", e); 975 } 976 assertTrue((mBundle.describeContents() 977 & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0); 978 mBundle.writeToParcel(parcel, 0); 979 mBundle.clear(); 980 assertTrue((mBundle.describeContents() 981 & Parcelable.CONTENTS_FILE_DESCRIPTOR) == 0); 982 parcel.setDataPosition(0); 983 mBundle.readFromParcel(parcel); 984 assertTrue((mBundle.describeContents() 985 & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0); 986 ParcelFileDescriptor pfd = (ParcelFileDescriptor)mBundle.getParcelable("foo"); 987 assertTrue((mBundle.describeContents() 988 & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0); 989 } 990 991 // case 1: The default bundle doesn't has FileDescriptor. 992 // case 2: The tested Bundle should has FileDescriptor 993 // if it read data from a Parcel object, which is created with a FileDescriptor. 994 // case 3: The tested Bundle should has FileDescriptor 995 // if put a Parcelable object, which is created with a FileDescriptor, into it. 996 @Test 997 @IgnoreUnderRavenwood(blockedBy = ParcelFileDescriptor.class) testHasFileDescriptors_withParcelFdItem()998 public void testHasFileDescriptors_withParcelFdItem() { 999 assertFalse(mBundle.hasFileDescriptors()); 1000 1001 final Parcel parcel = Parcel.obtain(); 1002 assertFalse(parcel.hasFileDescriptors()); 1003 try { 1004 mBundle.putParcelable("foo", ParcelFileDescriptor.open( 1005 new File("/system"), ParcelFileDescriptor.MODE_READ_ONLY)); 1006 } catch (FileNotFoundException e) { 1007 throw new RuntimeException("can't open /system", e); 1008 } 1009 assertTrue(mBundle.hasFileDescriptors()); 1010 mBundle.writeToParcel(parcel, 0); 1011 assertTrue(parcel.hasFileDescriptors()); 1012 mBundle.clear(); 1013 assertFalse(mBundle.hasFileDescriptors()); 1014 parcel.setDataPosition(0); 1015 mBundle.readFromParcel(parcel); 1016 assertTrue(mBundle.hasFileDescriptors()); // Checks the parcel 1017 1018 // Remove item to trigger deserialization and remove flag FLAG_HAS_FDS_KNOWN such that next 1019 // query triggers flag computation from lazy value 1020 mBundle.remove("unexistent"); 1021 assertTrue(mBundle.hasFileDescriptors()); // Checks the lazy value 1022 1023 // Trigger flag computation 1024 mBundle.remove("unexistent"); 1025 ParcelFileDescriptor pfd = mBundle.getParcelable("foo"); // Extracts the lazy value 1026 assertTrue(mBundle.hasFileDescriptors()); // Checks the object 1027 1028 // Now, check the lazy value returns false 1029 mBundle.clear(); 1030 mBundle.putParcelable(KEY1, new CustomParcelable(13, "Tiramisu")); 1031 roundtrip(); 1032 // Trigger flag computation 1033 mBundle.putParcelable("random", new CustomParcelable(13, "Tiramisu")); 1034 assertFalse(mBundle.hasFileDescriptors()); // Checks the lazy value 1035 } 1036 1037 @Test 1038 @IgnoreUnderRavenwood(blockedBy = ParcelFileDescriptor.class) testHasFileDescriptors_withParcelable()1039 public void testHasFileDescriptors_withParcelable() throws Exception { 1040 assertTrue(mBundle.isEmpty()); 1041 assertFalse(mBundle.hasFileDescriptors()); 1042 1043 mBundle.putParcelable("key", ParcelFileDescriptor.dup(FileDescriptor.in)); 1044 assertTrue(mBundle.hasFileDescriptors()); 1045 1046 mBundle.putParcelable("key", new CustomParcelable(13, "Tiramisu")); 1047 assertFalse(mBundle.hasFileDescriptors()); 1048 } 1049 1050 @Test 1051 @IgnoreUnderRavenwood(blockedBy = ParcelFileDescriptor.class) testHasFileDescriptors_withStringArray()1052 public void testHasFileDescriptors_withStringArray() throws Exception { 1053 assertTrue(mBundle.isEmpty()); 1054 assertFalse(mBundle.hasFileDescriptors()); 1055 1056 mBundle.putStringArray("key", new String[] { "string" }); 1057 assertFalse(mBundle.hasFileDescriptors()); 1058 } 1059 1060 @Test 1061 @IgnoreUnderRavenwood(blockedBy = ParcelFileDescriptor.class) testHasFileDescriptors_withSparseArray()1062 public void testHasFileDescriptors_withSparseArray() throws Exception { 1063 assertTrue(mBundle.isEmpty()); 1064 assertFalse(mBundle.hasFileDescriptors()); 1065 1066 SparseArray<Parcelable> fdArray = new SparseArray<>(); 1067 fdArray.append(0, ParcelFileDescriptor.dup(FileDescriptor.in)); 1068 mBundle.putSparseParcelableArray("key", fdArray); 1069 assertTrue(mBundle.hasFileDescriptors()); 1070 1071 SparseArray<Parcelable> noFdArray = new SparseArray<>(); 1072 noFdArray.append(0, new CustomParcelable(13, "Tiramisu")); 1073 mBundle.putSparseParcelableArray("key", noFdArray); 1074 assertFalse(mBundle.hasFileDescriptors()); 1075 1076 SparseArray<Parcelable> emptyArray = new SparseArray<>(); 1077 mBundle.putSparseParcelableArray("key", emptyArray); 1078 assertFalse(mBundle.hasFileDescriptors()); 1079 } 1080 1081 @Test 1082 @IgnoreUnderRavenwood(blockedBy = ParcelFileDescriptor.class) testHasFileDescriptors_withParcelableArray()1083 public void testHasFileDescriptors_withParcelableArray() throws Exception { 1084 assertTrue(mBundle.isEmpty()); 1085 assertFalse(mBundle.hasFileDescriptors()); 1086 1087 mBundle.putParcelableArray("key", 1088 new Parcelable[] { ParcelFileDescriptor.dup(FileDescriptor.in) }); 1089 assertTrue(mBundle.hasFileDescriptors()); 1090 1091 mBundle.putParcelableArray("key", 1092 new Parcelable[] { new CustomParcelable(13, "Tiramisu") }); 1093 assertFalse(mBundle.hasFileDescriptors()); 1094 } 1095 1096 @Test 1097 @IgnoreUnderRavenwood(blockedBy = ParcelFileDescriptor.class) testHasFileDescriptorsOnNullValuedCollection()1098 public void testHasFileDescriptorsOnNullValuedCollection() { 1099 assertFalse(mBundle.hasFileDescriptors()); 1100 1101 mBundle.putParcelableArray("foo", new Parcelable[1]); 1102 assertFalse(mBundle.hasFileDescriptors()); 1103 mBundle.clear(); 1104 1105 SparseArray<Parcelable> sparseArray = new SparseArray<Parcelable>(); 1106 sparseArray.put(0, null); 1107 mBundle.putSparseParcelableArray("bar", sparseArray); 1108 assertFalse(mBundle.hasFileDescriptors()); 1109 mBundle.clear(); 1110 1111 ArrayList<Parcelable> arrayList = new ArrayList<Parcelable>(); 1112 arrayList.add(null); 1113 mBundle.putParcelableArrayList("baz", arrayList); 1114 assertFalse(mBundle.hasFileDescriptors()); 1115 mBundle.clear(); 1116 } 1117 1118 @SuppressWarnings("unchecked") 1119 @Test 1120 @IgnoreUnderRavenwood(blockedBy = ParcelFileDescriptor.class) testHasFileDescriptors_withNestedContainers()1121 public void testHasFileDescriptors_withNestedContainers() throws IOException { 1122 // Purposely omitting generic types here, this is still "valid" app code after all. 1123 ArrayList nested = new ArrayList( 1124 Arrays.asList(Arrays.asList(ParcelFileDescriptor.dup(FileDescriptor.in)))); 1125 mBundle.putParcelableArrayList("list", nested); 1126 assertTrue(mBundle.hasFileDescriptors()); 1127 1128 roundtrip(/* parcel */ false); 1129 assertTrue(mBundle.hasFileDescriptors()); 1130 1131 mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values) 1132 mBundle.remove("unexistent"); // Removes cached value (removes FLAG_HAS_FDS_KNOWN) 1133 assertTrue(mBundle.hasFileDescriptors()); // Checks lazy value 1134 } 1135 1136 @Test 1137 @IgnoreUnderRavenwood(blockedBy = ParcelFileDescriptor.class) testHasFileDescriptors_withOriginalParcelContainingFdButNotItems()1138 public void testHasFileDescriptors_withOriginalParcelContainingFdButNotItems() throws IOException { 1139 mBundle.putParcelable("fd", ParcelFileDescriptor.dup(FileDescriptor.in)); 1140 mBundle.putParcelable("parcelable", new CustomParcelable(13, "Tiramisu")); 1141 assertTrue(mBundle.hasFileDescriptors()); 1142 1143 roundtrip(/* parcel */ false); 1144 mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values) 1145 assertTrue(mBundle.hasFileDescriptors()); 1146 mBundle.remove("fd"); 1147 1148 // Will check the item's specific range in the original parcel 1149 assertFalse(mBundle.hasFileDescriptors()); 1150 } 1151 1152 @Test 1153 @IgnoreUnderRavenwood(blockedBy = ParcelFileDescriptor.class) testHasFileDescriptors_withOriginalParcelAndItemsContainingFd()1154 public void testHasFileDescriptors_withOriginalParcelAndItemsContainingFd() throws IOException { 1155 mBundle.putParcelable("fd", ParcelFileDescriptor.dup(FileDescriptor.in)); 1156 mBundle.putParcelable("parcelable", new CustomParcelable(13, "Tiramisu")); 1157 assertTrue(mBundle.hasFileDescriptors()); 1158 1159 roundtrip(/* parcel */ false); 1160 mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values) 1161 assertTrue(mBundle.hasFileDescriptors()); 1162 mBundle.remove("parcelable"); 1163 1164 // Will check the item's specific range in the original parcel 1165 assertTrue(mBundle.hasFileDescriptors()); 1166 } 1167 1168 @Test testSetClassLoader()1169 public void testSetClassLoader() { 1170 mBundle.setClassLoader(new MockClassLoader()); 1171 } 1172 1173 // Write the bundle(A) to a parcel(B), and then create a bundle(C) from B. 1174 // C should be same as A. 1175 @Test testWriteToParcel()1176 public void testWriteToParcel() { 1177 final String li = "Bruce Li"; 1178 1179 mBundle.putString(KEY1, li); 1180 final Parcel parcel = Parcel.obtain(); 1181 mBundle.writeToParcel(parcel, 0); 1182 parcel.setDataPosition(0); 1183 final Bundle bundle = Bundle.CREATOR.createFromParcel(parcel); 1184 assertEquals(li, bundle.getString(KEY1)); 1185 } 1186 1187 // test the size should be right after add/remove key-value pair of the Bundle. 1188 @Test testSize()1189 public void testSize() { 1190 assertEquals(0, mBundle.size()); 1191 mBundle.putBoolean("one", true); 1192 assertEquals(1, mBundle.size()); 1193 1194 mBundle.putBoolean("two", true); 1195 assertEquals(2, mBundle.size()); 1196 1197 mBundle.putBoolean("three", true); 1198 assertEquals(3, mBundle.size()); 1199 1200 mBundle.putBoolean("four", true); 1201 mBundle.putBoolean("five", true); 1202 assertEquals(5, mBundle.size()); 1203 mBundle.remove("six"); 1204 assertEquals(5, mBundle.size()); 1205 1206 mBundle.remove("one"); 1207 assertEquals(4, mBundle.size()); 1208 mBundle.remove("one"); 1209 assertEquals(4, mBundle.size()); 1210 1211 mBundle.remove("two"); 1212 assertEquals(3, mBundle.size()); 1213 1214 mBundle.remove("three"); 1215 mBundle.remove("four"); 1216 mBundle.remove("five"); 1217 assertEquals(0, mBundle.size()); 1218 } 1219 1220 // The return value of toString() should not be null. 1221 @Test testToString()1222 public void testToString() { 1223 assertNotNull(mBundle.toString()); 1224 mBundle.putString("foo", "this test is so stupid"); 1225 assertNotNull(mBundle.toString()); 1226 } 1227 1228 // The tested Bundle should hold mappings from the given after putAll be invoked. 1229 @Test testPutAll()1230 public void testPutAll() { 1231 assertEquals(0, mBundle.size()); 1232 1233 final Bundle map = new Bundle(); 1234 map.putBoolean(KEY1, true); 1235 assertEquals(1, map.size()); 1236 mBundle.putAll(map); 1237 assertEquals(1, mBundle.size()); 1238 } 1239 roundtrip()1240 private void roundtrip() { 1241 roundtrip(/* parcel */ true); 1242 } 1243 roundtrip(boolean parcel)1244 private void roundtrip(boolean parcel) { 1245 mBundle = roundtrip(mBundle, parcel); 1246 } 1247 roundtrip(Bundle bundle)1248 private Bundle roundtrip(Bundle bundle) { 1249 return roundtrip(bundle, /* parcel */ true); 1250 } 1251 roundtrip(Bundle bundle, boolean parcel)1252 private Bundle roundtrip(Bundle bundle, boolean parcel) { 1253 Parcel p = Parcel.obtain(); 1254 bundle.writeToParcel(p, 0); 1255 if (parcel) { 1256 p = roundtripParcel(p); 1257 } 1258 p.setDataPosition(0); 1259 return p.readBundle(bundle.getClassLoader()); 1260 } 1261 roundtripParcel(Parcel out)1262 private Parcel roundtripParcel(Parcel out) { 1263 byte[] buf = out.marshall(); 1264 Parcel in = Parcel.obtain(); 1265 in.unmarshall(buf, 0, buf.length); 1266 in.setDataPosition(0); 1267 return in; 1268 } 1269 assertBundleEquals(Bundle expected, Bundle observed)1270 private void assertBundleEquals(Bundle expected, Bundle observed) { 1271 assertEquals(expected.size(), observed.size()); 1272 for (String key : expected.keySet()) { 1273 assertEquals(expected.get(key), observed.get(key)); 1274 } 1275 } 1276 assertSpannableEquals(Spannable expected, CharSequence observed)1277 private void assertSpannableEquals(Spannable expected, CharSequence observed) { 1278 final Spannable observedSpan = (Spannable) observed; 1279 assertEquals(expected.toString(), observed.toString()); 1280 Object[] expectedSpans = expected.getSpans(0, expected.length(), Object.class); 1281 Object[] observedSpans = observedSpan.getSpans(0, observedSpan.length(), Object.class); 1282 assertEquals(expectedSpans.length, observedSpans.length); 1283 for (int i = 0; i < expectedSpans.length; i++) { 1284 // Can't compare values of arbitrary objects 1285 assertEquals(expectedSpans[i].getClass(), observedSpans[i].getClass()); 1286 } 1287 } 1288 1289 @Test 1290 @IgnoreUnderRavenwood testHasFileDescriptor()1291 public void testHasFileDescriptor() throws Exception { 1292 final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); 1293 try { 1294 final ParcelFileDescriptor fd = pipe[0]; 1295 1296 assertNotHaveFd(Bundle.EMPTY); 1297 assertNotHaveFd(new Bundle()); 1298 1299 assertNotHaveFd(buildBundle("a", 1)); 1300 1301 assertHasFd(buildBundle("a", 1, fd)); 1302 assertHasFd(buildBundle("a", 1, new Parcelable[]{fd})); 1303 assertHasFd(buildBundle("a", 1, buildBundle(new Parcelable[]{fd}))); 1304 assertNotHaveFd(buildBundle("a", 1, buildBundle(1))); 1305 1306 Bundle nested1 = buildBundle(fd, buildBundle(1)); 1307 assertHasFd(nested1); // Outer bundle has an FD. 1308 assertNotHaveFd(nested1.getParcelable("key-1")); // But inner bundle doesn't. 1309 1310 Bundle nested2 = buildBundle(1, buildBundle(fd)); 1311 assertHasFd(nested2); 1312 assertHasFd(nested2.getParcelable("key-1")); 1313 1314 // More tricky case. Create a parcel with mixed objects. 1315 Parcel p = Parcel.obtain(); 1316 p.writeParcelable(fd, 0); 1317 p.writeInt(123); 1318 p.writeParcelable(buildBundle(1), 0); 1319 1320 // Now the parcel has an FD. 1321 p.setDataPosition(0); 1322 assertTrue(p.hasFileDescriptors()); 1323 1324 // Note even though the entire parcel has an FD, the inner bundle doesn't. 1325 assertEquals(ParcelFileDescriptor.class, 1326 p.readParcelable(getClass().getClassLoader()).getClass()); 1327 assertEquals(123, p.readInt()); 1328 assertNotHaveFd(p.readParcelable(Bundle.class.getClassLoader())); 1329 } finally { 1330 pipe[0].close(); 1331 pipe[1].close(); 1332 } 1333 } 1334 1335 @Test testBundleLengthNotAlignedByFour()1336 public void testBundleLengthNotAlignedByFour() { 1337 mBundle.putBoolean(KEY1, true); 1338 assertEquals(1, mBundle.size()); 1339 Parcel p = Parcel.obtain(); 1340 final int lengthPos = p.dataPosition(); 1341 mBundle.writeToParcel(p, 0); 1342 p.setDataPosition(lengthPos); 1343 final int length = p.readInt(); 1344 assertTrue(length != 0); 1345 assertTrue(length % 4 == 0); 1346 // Corrupt the bundle length so it is not aligned by 4. 1347 p.setDataPosition(lengthPos); 1348 p.writeInt(length - 1); 1349 p.setDataPosition(0); 1350 final Bundle b = new Bundle(); 1351 try { 1352 b.readFromParcel(p); 1353 fail("Failed to get an IllegalStateException"); 1354 } catch (IllegalStateException e) { 1355 // Expect IllegalStateException here. 1356 } 1357 } 1358 1359 @Test testGetCustomParcelable()1360 public void testGetCustomParcelable() { 1361 Parcelable parcelable = new CustomParcelable(13, "Tiramisu"); 1362 mBundle.putParcelable(KEY1, parcelable); 1363 assertEquals(parcelable, mBundle.getParcelable(KEY1)); 1364 assertEquals(1, mBundle.size()); 1365 roundtrip(); 1366 assertNotSame(parcelable, mBundle.getParcelable(KEY1)); 1367 assertEquals(parcelable, mBundle.getParcelable(KEY1)); 1368 assertEquals(1, mBundle.size()); 1369 } 1370 1371 @Test testGetNestedParcelable()1372 public void testGetNestedParcelable() { 1373 Parcelable nested = new CustomParcelable(13, "Tiramisu"); 1374 ComposedParcelable parcelable = new ComposedParcelable(26, nested); 1375 mBundle.putParcelable(KEY1, parcelable); 1376 assertEquals(parcelable, mBundle.getParcelable(KEY1)); 1377 assertEquals(1, mBundle.size()); 1378 roundtrip(); 1379 ComposedParcelable reconstructed = mBundle.getParcelable(KEY1); 1380 assertNotSame(parcelable, reconstructed); 1381 assertEquals(parcelable, reconstructed); 1382 assertNotSame(nested, reconstructed.parcelable); 1383 assertEquals(nested, reconstructed.parcelable); 1384 assertEquals(1, mBundle.size()); 1385 } 1386 1387 @Test testItemDeserializationIndependence()1388 public void testItemDeserializationIndependence() { 1389 Parcelable parcelable = new CustomParcelable(13, "Tiramisu"); 1390 Parcelable bomb = new CustomParcelable(13, "Tiramisu").setThrowsDuringDeserialization(true); 1391 mBundle.putParcelable(KEY1, parcelable); 1392 mBundle.putParcelable(KEY2, bomb); 1393 assertEquals(parcelable, mBundle.getParcelable(KEY1)); 1394 assertEquals(bomb, mBundle.getParcelable(KEY2)); 1395 assertEquals(2, mBundle.size()); 1396 roundtrip(); 1397 assertEquals(2, mBundle.size()); 1398 Parcelable reParcelable = mBundle.getParcelable(KEY1); 1399 // Passed if it didn't throw 1400 assertNotSame(parcelable, reParcelable); 1401 assertEquals(parcelable, reParcelable); 1402 assertThrows(RuntimeException.class, () -> mBundle.getParcelable(KEY2)); 1403 assertEquals(2, mBundle.size()); 1404 } 1405 1406 @Test testLazyValueReserialization()1407 public void testLazyValueReserialization() { 1408 Parcelable parcelable = new CustomParcelable(13, "Tiramisu"); 1409 mBundle.putParcelable(KEY1, parcelable); 1410 mBundle.putString(KEY2, "value"); 1411 roundtrip(); 1412 assertEquals("value", mBundle.getString(KEY2)); 1413 // Since we haven't retrieved KEY1, its value is still a lazy value inside bundle 1414 roundtrip(); 1415 assertEquals(parcelable, mBundle.getParcelable(KEY1)); 1416 assertEquals("value", mBundle.getString(KEY2)); 1417 } 1418 1419 @Test testPutAll_withLazyValues()1420 public void testPutAll_withLazyValues() { 1421 Parcelable parcelable = new CustomParcelable(13, "Tiramisu"); 1422 mBundle.putParcelable(KEY1, parcelable); 1423 roundtrip(); 1424 mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values) 1425 Bundle copy = new Bundle(); 1426 copy.putAll(mBundle); 1427 assertEquals(parcelable, copy.getParcelable(KEY1)); 1428 // Here we're verifying that LazyValue caches the deserialized object, hence they are the 1429 // same instance 1430 assertSame(copy.getParcelable(KEY1), mBundle.getParcelable(KEY1)); 1431 assertEquals(1, copy.size()); 1432 } 1433 1434 @Test testDeepCopy_withLazyValues()1435 public void testDeepCopy_withLazyValues() { 1436 Parcelable parcelable = new CustomParcelable(13, "Tiramisu"); 1437 mBundle.putParcelable(KEY1, parcelable); 1438 roundtrip(); 1439 mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values) 1440 Bundle copy = mBundle.deepCopy(); 1441 assertEquals(parcelable, copy.getParcelable(KEY1)); 1442 // Here we're verifying that LazyValue caches the deserialized object, hence they are the 1443 // same instance 1444 assertSame(copy.getParcelable(KEY1), mBundle.getParcelable(KEY1)); 1445 assertEquals(1, copy.size()); 1446 } 1447 1448 @Test testDeepCopy_withNestedParcelable()1449 public void testDeepCopy_withNestedParcelable() { 1450 Parcelable nested = new CustomParcelable(13, "Tiramisu"); 1451 ComposedParcelable parcelable = new ComposedParcelable(26, nested); 1452 mBundle.putParcelable(KEY1, parcelable); 1453 roundtrip(); 1454 mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values) 1455 Bundle copy = mBundle.deepCopy(); 1456 ComposedParcelable reconstructed = copy.getParcelable(KEY1); 1457 assertEquals(parcelable, reconstructed); 1458 assertSame(copy.getParcelable(KEY1), mBundle.getParcelable(KEY1)); 1459 assertEquals(nested, reconstructed.parcelable); 1460 assertEquals(1, copy.size()); 1461 } 1462 1463 @Test testDeepCopy_withNestedBundleAndLazyValues()1464 public void testDeepCopy_withNestedBundleAndLazyValues() { 1465 Parcelable parcelable = new CustomParcelable(13, "Tiramisu"); 1466 Bundle inner = new Bundle(); 1467 inner.putParcelable(KEY1, parcelable); 1468 inner = roundtrip(inner); 1469 inner.setClassLoader(getClass().getClassLoader()); 1470 inner.isEmpty(); // Triggers partial deserialization (leaving lazy values) 1471 mBundle.putParcelable(KEY1, inner); 1472 Bundle copy = mBundle.deepCopy(); 1473 assertEquals(parcelable, copy.getBundle(KEY1).getParcelable(KEY1)); 1474 assertNotSame(mBundle.getBundle(KEY1), copy.getBundle(KEY1)); 1475 assertSame(mBundle.getBundle(KEY1).getParcelable(KEY1), 1476 copy.getBundle(KEY1).getParcelable(KEY1)); 1477 assertEquals(1, copy.getBundle(KEY1).size()); 1478 assertEquals(1, copy.size()); 1479 } 1480 1481 @Test testGetParcelable_isLazy()1482 public void testGetParcelable_isLazy() { 1483 mBundle.putParcelable(KEY1, new CustomParcelable(13, "Tiramisu")); 1484 roundtrip(); 1485 mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values) 1486 assertThat(CustomParcelable.sDeserialized).isFalse(); 1487 mBundle.getParcelable(KEY1); 1488 assertThat(CustomParcelable.sDeserialized).isTrue(); 1489 } 1490 1491 @Test testGetParcelableArray_isLazy()1492 public void testGetParcelableArray_isLazy() { 1493 mBundle.putParcelableArray(KEY1, new Parcelable[] {new CustomParcelable(13, "Tiramisu")}); 1494 roundtrip(); 1495 mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values) 1496 assertThat(CustomParcelable.sDeserialized).isFalse(); 1497 mBundle.getParcelableArray(KEY1); 1498 assertThat(CustomParcelable.sDeserialized).isTrue(); 1499 } 1500 1501 @Test testGetParcelableArrayList_isLazy()1502 public void testGetParcelableArrayList_isLazy() { 1503 mBundle.putParcelableArrayList(KEY1, 1504 new ArrayList<>(singletonList(new CustomParcelable(13, "Tiramisu")))); 1505 roundtrip(); 1506 mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values) 1507 assertThat(CustomParcelable.sDeserialized).isFalse(); 1508 mBundle.getParcelableArrayList(KEY1); 1509 assertThat(CustomParcelable.sDeserialized).isTrue(); 1510 } 1511 1512 @Test testGetSparseParcelableArray_isLazy()1513 public void testGetSparseParcelableArray_isLazy() { 1514 SparseArray<Parcelable> container = new SparseArray<>(); 1515 container.put(0, new CustomParcelable(13, "Tiramisu")); 1516 mBundle.putSparseParcelableArray(KEY1, container); 1517 roundtrip(); 1518 mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values) 1519 assertThat(CustomParcelable.sDeserialized).isFalse(); 1520 mBundle.getSparseParcelableArray(KEY1); 1521 assertThat(CustomParcelable.sDeserialized).isTrue(); 1522 } 1523 1524 @Test testGetSerializable_isLazy()1525 public void testGetSerializable_isLazy() { 1526 mBundle.putSerializable(KEY1, new CustomSerializable()); 1527 roundtrip(); 1528 mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values) 1529 assertThat(CustomSerializable.sDeserialized).isFalse(); 1530 mBundle.getSerializable(KEY1); 1531 assertThat(CustomSerializable.sDeserialized).isTrue(); 1532 } 1533 1534 public static class CustomSerializable implements Serializable { 1535 public static boolean sDeserialized = false; 1536 readObject(ObjectInputStream in)1537 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 1538 in.defaultReadObject(); 1539 sDeserialized = true; 1540 } 1541 } 1542 1543 public static class AnotherSerializable implements Serializable { 1544 } 1545 1546 public static class CustomParcelable implements Parcelable { 1547 public static boolean sDeserialized = false; 1548 1549 public final int integer; 1550 public final String string; 1551 public boolean throwsDuringDeserialization; 1552 CustomParcelable(int integer, String string)1553 public CustomParcelable(int integer, String string) { 1554 this.integer = integer; 1555 this.string = string; 1556 } 1557 CustomParcelable(Parcel in)1558 protected CustomParcelable(Parcel in) { 1559 integer = in.readInt(); 1560 string = in.readString(); 1561 throwsDuringDeserialization = in.readBoolean(); 1562 if (throwsDuringDeserialization) { 1563 throw new RuntimeException(); 1564 } 1565 sDeserialized = true; 1566 } 1567 setThrowsDuringDeserialization( boolean throwsDuringDeserialization)1568 public CustomParcelable setThrowsDuringDeserialization( 1569 boolean throwsDuringDeserialization) { 1570 this.throwsDuringDeserialization = throwsDuringDeserialization; 1571 return this; 1572 } 1573 1574 @Override describeContents()1575 public int describeContents() { 1576 return 0; 1577 } 1578 1579 @Override writeToParcel(Parcel out, int flags)1580 public void writeToParcel(Parcel out, int flags) { 1581 out.writeInt(integer); 1582 out.writeString(string); 1583 out.writeBoolean(throwsDuringDeserialization); 1584 } 1585 1586 @Override equals(Object other)1587 public boolean equals(Object other) { 1588 if (this == other) { 1589 return true; 1590 } 1591 if (!(other instanceof CustomParcelable)) { 1592 return false; 1593 } 1594 CustomParcelable that = (CustomParcelable) other; 1595 return integer == that.integer 1596 && throwsDuringDeserialization == that.throwsDuringDeserialization 1597 && string.equals(that.string); 1598 } 1599 1600 @Override hashCode()1601 public int hashCode() { 1602 return Objects.hash(integer, string, throwsDuringDeserialization); 1603 } 1604 1605 public static final Creator<CustomParcelable> CREATOR = new Creator<CustomParcelable>() { 1606 @Override 1607 public CustomParcelable createFromParcel(Parcel in) { 1608 return new CustomParcelable(in); 1609 } 1610 @Override 1611 public CustomParcelable[] newArray(int size) { 1612 return new CustomParcelable[size]; 1613 } 1614 }; 1615 } 1616 1617 public static class ComposedParcelable implements Parcelable { 1618 public final int integer; 1619 public final Parcelable parcelable; 1620 ComposedParcelable(int integer, Parcelable parcelable)1621 public ComposedParcelable(int integer, Parcelable parcelable) { 1622 this.integer = integer; 1623 this.parcelable = parcelable; 1624 } 1625 ComposedParcelable(Parcel in)1626 protected ComposedParcelable(Parcel in) { 1627 integer = in.readInt(); 1628 parcelable = in.readParcelable(getClass().getClassLoader()); 1629 } 1630 1631 @Override describeContents()1632 public int describeContents() { 1633 return 0; 1634 } 1635 1636 @Override writeToParcel(Parcel out, int flags)1637 public void writeToParcel(Parcel out, int flags) { 1638 out.writeInt(integer); 1639 out.writeParcelable(parcelable, flags); 1640 } 1641 1642 @Override equals(Object other)1643 public boolean equals(Object other) { 1644 if (this == other) { 1645 return true; 1646 } 1647 if (!(other instanceof ComposedParcelable)) { 1648 return false; 1649 } 1650 ComposedParcelable that = (ComposedParcelable) other; 1651 return integer == that.integer && Objects.equals(parcelable, that.parcelable); 1652 } 1653 1654 @Override hashCode()1655 public int hashCode() { 1656 return Objects.hash(integer, parcelable); 1657 } 1658 1659 public static final Creator<ComposedParcelable> CREATOR = 1660 new Creator<ComposedParcelable>() { 1661 @Override 1662 public ComposedParcelable createFromParcel(Parcel in) { 1663 return new ComposedParcelable(in); 1664 } 1665 @Override 1666 public ComposedParcelable[] newArray(int size) { 1667 return new ComposedParcelable[size]; 1668 } 1669 }; 1670 } 1671 1672 /** Create a Bundle with values, with autogenerated keys. */ buildBundle(Object... values)1673 private static Bundle buildBundle(Object... values) { 1674 final Bundle result = new Bundle(); 1675 1676 for (int i = 0; i < values.length; i++) { 1677 final String key = "key-" + i; 1678 1679 final Object value = values[i]; 1680 if (value == null) { 1681 result.putString(key, null); 1682 1683 } else if (value instanceof String) { 1684 result.putString(key, (String) value); 1685 1686 } else if (value instanceof Integer) { 1687 result.putInt(key, (Integer) value); 1688 1689 } else if (value instanceof Parcelable) { 1690 result.putParcelable(key, (Parcelable) value); 1691 1692 } else if (value instanceof Parcelable[]) { 1693 result.putParcelableArray(key, (Parcelable[]) value); 1694 1695 } else { 1696 fail("Unsupported value type: " + value.getClass()); 1697 } 1698 } 1699 return result; 1700 } 1701 cloneBundle(Bundle b)1702 private static Bundle cloneBundle(Bundle b) { 1703 return new Bundle(b); 1704 } 1705 cloneBundleViaParcel(Bundle b)1706 private static Bundle cloneBundleViaParcel(Bundle b) { 1707 final Parcel p = Parcel.obtain(); 1708 try { 1709 p.writeParcelable(b, 0); 1710 1711 p.setDataPosition(0); 1712 1713 return p.readParcelable(Bundle.class.getClassLoader()); 1714 } finally { 1715 p.recycle(); 1716 } 1717 } 1718 assertHasFd(Bundle b)1719 private static void assertHasFd(Bundle b) { 1720 assertTrue(b.hasFileDescriptors()); 1721 1722 // Make sure cloned ones have the same result. 1723 assertTrue(cloneBundle(b).hasFileDescriptors()); 1724 assertTrue(cloneBundleViaParcel(b).hasFileDescriptors()); 1725 } 1726 assertNotHaveFd(Bundle b)1727 private static void assertNotHaveFd(Bundle b) { 1728 assertFalse(b.hasFileDescriptors()); 1729 1730 // Make sure cloned ones have the same result. 1731 assertFalse(cloneBundle(b).hasFileDescriptors()); 1732 assertFalse(cloneBundleViaParcel(b).hasFileDescriptors()); 1733 } 1734 1735 class MockClassLoader extends ClassLoader { MockClassLoader()1736 MockClassLoader() { 1737 super(); 1738 } 1739 } 1740 uncheck(Callable<T> runnable)1741 private static <T> T uncheck(Callable<T> runnable) { 1742 try { 1743 return runnable.call(); 1744 } catch (Exception e) { 1745 throw new AssertionError(e); 1746 } 1747 } 1748 } 1749