• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.DisabledOnRavenwood;
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     @DisabledOnRavenwood(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     @DisabledOnRavenwood(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     @DisabledOnRavenwood(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
testDescribeContents()964     public void testDescribeContents() {
965         assertTrue((mBundle.describeContents()
966                 & Parcelable.CONTENTS_FILE_DESCRIPTOR) == 0);
967 
968         final Parcel parcel = Parcel.obtain();
969         try {
970             mBundle.putParcelable("foo", ParcelFileDescriptor.open(
971                     new File("/dev/zero"), ParcelFileDescriptor.MODE_READ_ONLY));
972         } catch (FileNotFoundException e) {
973             throw new RuntimeException("can't open /dev/zero", e);
974         }
975         assertTrue((mBundle.describeContents()
976                 & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0);
977         mBundle.writeToParcel(parcel, 0);
978         mBundle.clear();
979         assertTrue((mBundle.describeContents()
980                 & Parcelable.CONTENTS_FILE_DESCRIPTOR) == 0);
981         parcel.setDataPosition(0);
982         mBundle.readFromParcel(parcel);
983         assertTrue((mBundle.describeContents()
984                 & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0);
985         ParcelFileDescriptor pfd = (ParcelFileDescriptor)mBundle.getParcelable("foo");
986         assertTrue((mBundle.describeContents()
987                 & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0);
988     }
989 
990     // case 1: The default bundle doesn't has FileDescriptor.
991     // case 2: The tested Bundle should has FileDescriptor
992     //  if it read data from a Parcel object, which is created with a FileDescriptor.
993     // case 3: The tested Bundle should has FileDescriptor
994     //  if put a Parcelable object, which is created with a FileDescriptor, into it.
995     @Test
testHasFileDescriptors_withParcelFdItem()996     public void testHasFileDescriptors_withParcelFdItem() {
997         assertFalse(mBundle.hasFileDescriptors());
998 
999         final Parcel parcel = Parcel.obtain();
1000         assertFalse(parcel.hasFileDescriptors());
1001         try {
1002             mBundle.putParcelable("foo", ParcelFileDescriptor.open(
1003                     new File("/dev/zero"), ParcelFileDescriptor.MODE_READ_ONLY));
1004         } catch (FileNotFoundException e) {
1005             throw new RuntimeException("can't open /dev/zero", e);
1006         }
1007         assertTrue(mBundle.hasFileDescriptors());
1008         mBundle.writeToParcel(parcel, 0);
1009         assertTrue(parcel.hasFileDescriptors());
1010         mBundle.clear();
1011         assertFalse(mBundle.hasFileDescriptors());
1012         parcel.setDataPosition(0);
1013         mBundle.readFromParcel(parcel);
1014         assertTrue(mBundle.hasFileDescriptors()); // Checks the parcel
1015 
1016         // Remove item to trigger deserialization and remove flag FLAG_HAS_FDS_KNOWN such that next
1017         // query triggers flag computation from lazy value
1018         mBundle.remove("unexistent");
1019         assertTrue(mBundle.hasFileDescriptors()); // Checks the lazy value
1020 
1021         // Trigger flag computation
1022         mBundle.remove("unexistent");
1023         ParcelFileDescriptor pfd = mBundle.getParcelable("foo"); // Extracts the lazy value
1024         assertTrue(mBundle.hasFileDescriptors()); // Checks the object
1025 
1026         // Now, check the lazy value returns false
1027         mBundle.clear();
1028         mBundle.putParcelable(KEY1, new CustomParcelable(13, "Tiramisu"));
1029         roundtrip();
1030         // Trigger flag computation
1031         mBundle.putParcelable("random", new CustomParcelable(13, "Tiramisu"));
1032         assertFalse(mBundle.hasFileDescriptors()); // Checks the lazy value
1033     }
1034 
1035     @Test
testHasFileDescriptors_withParcelable()1036     public void testHasFileDescriptors_withParcelable() throws Exception {
1037         assertTrue(mBundle.isEmpty());
1038         assertFalse(mBundle.hasFileDescriptors());
1039 
1040         mBundle.putParcelable("key", ParcelFileDescriptor.dup(FileDescriptor.in));
1041         assertTrue(mBundle.hasFileDescriptors());
1042 
1043         mBundle.putParcelable("key", new CustomParcelable(13, "Tiramisu"));
1044         assertFalse(mBundle.hasFileDescriptors());
1045     }
1046 
1047     @Test
testHasFileDescriptors_withStringArray()1048     public void testHasFileDescriptors_withStringArray() throws Exception {
1049         assertTrue(mBundle.isEmpty());
1050         assertFalse(mBundle.hasFileDescriptors());
1051 
1052         mBundle.putStringArray("key", new String[] { "string" });
1053         assertFalse(mBundle.hasFileDescriptors());
1054     }
1055 
1056     @Test
testHasFileDescriptors_withSparseArray()1057     public void testHasFileDescriptors_withSparseArray() throws Exception {
1058         assertTrue(mBundle.isEmpty());
1059         assertFalse(mBundle.hasFileDescriptors());
1060 
1061         SparseArray<Parcelable> fdArray = new SparseArray<>();
1062         fdArray.append(0, ParcelFileDescriptor.dup(FileDescriptor.in));
1063         mBundle.putSparseParcelableArray("key", fdArray);
1064         assertTrue(mBundle.hasFileDescriptors());
1065 
1066         SparseArray<Parcelable> noFdArray = new SparseArray<>();
1067         noFdArray.append(0, new CustomParcelable(13, "Tiramisu"));
1068         mBundle.putSparseParcelableArray("key", noFdArray);
1069         assertFalse(mBundle.hasFileDescriptors());
1070 
1071         SparseArray<Parcelable> emptyArray = new SparseArray<>();
1072         mBundle.putSparseParcelableArray("key", emptyArray);
1073         assertFalse(mBundle.hasFileDescriptors());
1074     }
1075 
1076     @Test
testHasFileDescriptors_withParcelableArray()1077     public void testHasFileDescriptors_withParcelableArray() throws Exception {
1078         assertTrue(mBundle.isEmpty());
1079         assertFalse(mBundle.hasFileDescriptors());
1080 
1081         mBundle.putParcelableArray("key",
1082                 new Parcelable[] { ParcelFileDescriptor.dup(FileDescriptor.in) });
1083         assertTrue(mBundle.hasFileDescriptors());
1084 
1085         mBundle.putParcelableArray("key",
1086                 new Parcelable[] { new CustomParcelable(13, "Tiramisu") });
1087         assertFalse(mBundle.hasFileDescriptors());
1088     }
1089 
1090     @Test
testHasFileDescriptorsOnNullValuedCollection()1091     public void testHasFileDescriptorsOnNullValuedCollection() {
1092         assertFalse(mBundle.hasFileDescriptors());
1093 
1094         mBundle.putParcelableArray("foo", new Parcelable[1]);
1095         assertFalse(mBundle.hasFileDescriptors());
1096         mBundle.clear();
1097 
1098         SparseArray<Parcelable> sparseArray = new SparseArray<Parcelable>();
1099         sparseArray.put(0, null);
1100         mBundle.putSparseParcelableArray("bar", sparseArray);
1101         assertFalse(mBundle.hasFileDescriptors());
1102         mBundle.clear();
1103 
1104         ArrayList<Parcelable> arrayList = new ArrayList<Parcelable>();
1105         arrayList.add(null);
1106         mBundle.putParcelableArrayList("baz", arrayList);
1107         assertFalse(mBundle.hasFileDescriptors());
1108         mBundle.clear();
1109     }
1110 
1111     @SuppressWarnings("unchecked")
1112     @Test
testHasFileDescriptors_withNestedContainers()1113     public void testHasFileDescriptors_withNestedContainers() throws IOException {
1114         // Purposely omitting generic types here, this is still "valid" app code after all.
1115         ArrayList nested = new ArrayList(
1116                 Arrays.asList(Arrays.asList(ParcelFileDescriptor.dup(FileDescriptor.in))));
1117         mBundle.putParcelableArrayList("list", nested);
1118         assertTrue(mBundle.hasFileDescriptors());
1119 
1120         roundtrip(/* parcel */ false);
1121         assertTrue(mBundle.hasFileDescriptors());
1122 
1123         mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values)
1124         mBundle.remove("unexistent"); // Removes cached value (removes FLAG_HAS_FDS_KNOWN)
1125         assertTrue(mBundle.hasFileDescriptors()); // Checks lazy value
1126     }
1127 
1128     @Test
testHasFileDescriptors_withOriginalParcelContainingFdButNotItems()1129     public void testHasFileDescriptors_withOriginalParcelContainingFdButNotItems() throws IOException {
1130         mBundle.putParcelable("fd", ParcelFileDescriptor.dup(FileDescriptor.in));
1131         mBundle.putParcelable("parcelable", new CustomParcelable(13, "Tiramisu"));
1132         assertTrue(mBundle.hasFileDescriptors());
1133 
1134         roundtrip(/* parcel */ false);
1135         mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values)
1136         assertTrue(mBundle.hasFileDescriptors());
1137         mBundle.remove("fd");
1138 
1139         // Will check the item's specific range in the original parcel
1140         assertFalse(mBundle.hasFileDescriptors());
1141     }
1142 
1143     @Test
testHasFileDescriptors_withOriginalParcelAndItemsContainingFd()1144     public void testHasFileDescriptors_withOriginalParcelAndItemsContainingFd() throws IOException {
1145         mBundle.putParcelable("fd", ParcelFileDescriptor.dup(FileDescriptor.in));
1146         mBundle.putParcelable("parcelable", new CustomParcelable(13, "Tiramisu"));
1147         assertTrue(mBundle.hasFileDescriptors());
1148 
1149         roundtrip(/* parcel */ false);
1150         mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values)
1151         assertTrue(mBundle.hasFileDescriptors());
1152         mBundle.remove("parcelable");
1153 
1154         // Will check the item's specific range in the original parcel
1155         assertTrue(mBundle.hasFileDescriptors());
1156     }
1157 
1158     @Test
testSetClassLoader()1159     public void testSetClassLoader() {
1160         mBundle.setClassLoader(new MockClassLoader());
1161     }
1162 
1163     // Write the bundle(A) to a parcel(B), and then create a bundle(C) from B.
1164     // C should be same as A.
1165     @Test
testWriteToParcel()1166     public void testWriteToParcel() {
1167         final String li = "Bruce Li";
1168 
1169         mBundle.putString(KEY1, li);
1170         final Parcel parcel = Parcel.obtain();
1171         mBundle.writeToParcel(parcel, 0);
1172         parcel.setDataPosition(0);
1173         final Bundle bundle = Bundle.CREATOR.createFromParcel(parcel);
1174         assertEquals(li, bundle.getString(KEY1));
1175     }
1176 
1177     // test the size should be right after add/remove key-value pair of the Bundle.
1178     @Test
testSize()1179     public void testSize() {
1180         assertEquals(0, mBundle.size());
1181         mBundle.putBoolean("one", true);
1182         assertEquals(1, mBundle.size());
1183 
1184         mBundle.putBoolean("two", true);
1185         assertEquals(2, mBundle.size());
1186 
1187         mBundle.putBoolean("three", true);
1188         assertEquals(3, mBundle.size());
1189 
1190         mBundle.putBoolean("four", true);
1191         mBundle.putBoolean("five", true);
1192         assertEquals(5, mBundle.size());
1193         mBundle.remove("six");
1194         assertEquals(5, mBundle.size());
1195 
1196         mBundle.remove("one");
1197         assertEquals(4, mBundle.size());
1198         mBundle.remove("one");
1199         assertEquals(4, mBundle.size());
1200 
1201         mBundle.remove("two");
1202         assertEquals(3, mBundle.size());
1203 
1204         mBundle.remove("three");
1205         mBundle.remove("four");
1206         mBundle.remove("five");
1207         assertEquals(0, mBundle.size());
1208     }
1209 
1210     // The return value of toString() should not be null.
1211     @Test
testToString()1212     public void testToString() {
1213         assertNotNull(mBundle.toString());
1214         mBundle.putString("foo", "this test is so stupid");
1215         assertNotNull(mBundle.toString());
1216     }
1217 
1218     // The tested Bundle should hold mappings from the given after putAll be invoked.
1219     @Test
testPutAll()1220     public void testPutAll() {
1221         assertEquals(0, mBundle.size());
1222 
1223         final Bundle map = new Bundle();
1224         map.putBoolean(KEY1, true);
1225         assertEquals(1, map.size());
1226         mBundle.putAll(map);
1227         assertEquals(1, mBundle.size());
1228     }
1229 
roundtrip()1230     private void roundtrip() {
1231         roundtrip(/* parcel */ true);
1232     }
1233 
roundtrip(boolean parcel)1234     private void roundtrip(boolean parcel) {
1235         mBundle = roundtrip(mBundle, parcel);
1236     }
1237 
roundtrip(Bundle bundle)1238     private Bundle roundtrip(Bundle bundle) {
1239         return roundtrip(bundle, /* parcel */ true);
1240     }
1241 
roundtrip(Bundle bundle, boolean parcel)1242     private Bundle roundtrip(Bundle bundle, boolean parcel) {
1243         Parcel p = Parcel.obtain();
1244         bundle.writeToParcel(p, 0);
1245         if (parcel) {
1246             p = roundtripParcel(p);
1247         }
1248         p.setDataPosition(0);
1249         return p.readBundle(bundle.getClassLoader());
1250     }
1251 
roundtripParcel(Parcel out)1252     private Parcel roundtripParcel(Parcel out) {
1253         byte[] buf = out.marshall();
1254         Parcel in = Parcel.obtain();
1255         in.unmarshall(buf, 0, buf.length);
1256         in.setDataPosition(0);
1257         return in;
1258     }
1259 
assertBundleEquals(Bundle expected, Bundle observed)1260     private void assertBundleEquals(Bundle expected, Bundle observed) {
1261         assertEquals(expected.size(), observed.size());
1262         for (String key : expected.keySet()) {
1263             assertEquals(expected.get(key), observed.get(key));
1264         }
1265     }
1266 
assertSpannableEquals(Spannable expected, CharSequence observed)1267     private void assertSpannableEquals(Spannable expected, CharSequence observed) {
1268         final Spannable observedSpan = (Spannable) observed;
1269         assertEquals(expected.toString(), observed.toString());
1270         Object[] expectedSpans = expected.getSpans(0, expected.length(), Object.class);
1271         Object[] observedSpans = observedSpan.getSpans(0, observedSpan.length(), Object.class);
1272         assertEquals(expectedSpans.length, observedSpans.length);
1273         for (int i = 0; i < expectedSpans.length; i++) {
1274             // Can't compare values of arbitrary objects
1275             assertEquals(expectedSpans[i].getClass(), observedSpans[i].getClass());
1276         }
1277     }
1278 
1279     @Test
testHasFileDescriptor()1280     public void testHasFileDescriptor() throws Exception {
1281         final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
1282         try {
1283             final ParcelFileDescriptor fd = pipe[0];
1284 
1285             assertNotHaveFd(Bundle.EMPTY);
1286             assertNotHaveFd(new Bundle());
1287 
1288             assertNotHaveFd(buildBundle("a", 1));
1289 
1290             assertHasFd(buildBundle("a", 1, fd));
1291             assertHasFd(buildBundle("a", 1, new Parcelable[]{fd}));
1292             assertHasFd(buildBundle("a", 1, buildBundle(new Parcelable[]{fd})));
1293             assertNotHaveFd(buildBundle("a", 1, buildBundle(1)));
1294 
1295             Bundle nested1 = buildBundle(fd, buildBundle(1));
1296             assertHasFd(nested1); // Outer bundle has an FD.
1297             assertNotHaveFd(nested1.getParcelable("key-1")); // But inner bundle doesn't.
1298 
1299             Bundle nested2 = buildBundle(1, buildBundle(fd));
1300             assertHasFd(nested2);
1301             assertHasFd(nested2.getParcelable("key-1"));
1302 
1303             // More tricky case.  Create a parcel with mixed objects.
1304             Parcel p = Parcel.obtain();
1305             p.writeParcelable(fd, 0);
1306             p.writeInt(123);
1307             p.writeParcelable(buildBundle(1), 0);
1308 
1309             // Now the parcel has an FD.
1310             p.setDataPosition(0);
1311             assertTrue(p.hasFileDescriptors());
1312 
1313             // Note even though the entire parcel has an FD, the inner bundle doesn't.
1314             assertEquals(ParcelFileDescriptor.class,
1315                     p.readParcelable(getClass().getClassLoader()).getClass());
1316             assertEquals(123, p.readInt());
1317             assertNotHaveFd(p.readParcelable(Bundle.class.getClassLoader()));
1318         } finally {
1319             pipe[0].close();
1320             pipe[1].close();
1321         }
1322     }
1323 
1324     @Test
testBundleLengthNotAlignedByFour()1325     public void testBundleLengthNotAlignedByFour() {
1326         mBundle.putBoolean(KEY1, true);
1327         assertEquals(1, mBundle.size());
1328         Parcel p = Parcel.obtain();
1329         final int lengthPos = p.dataPosition();
1330         mBundle.writeToParcel(p, 0);
1331         p.setDataPosition(lengthPos);
1332         final int length = p.readInt();
1333         assertTrue(length != 0);
1334         assertTrue(length % 4 == 0);
1335         // Corrupt the bundle length so it is not aligned by 4.
1336         p.setDataPosition(lengthPos);
1337         p.writeInt(length - 1);
1338         p.setDataPosition(0);
1339         final Bundle b = new Bundle();
1340         try {
1341             b.readFromParcel(p);
1342             fail("Failed to get an IllegalStateException");
1343         } catch (IllegalStateException e) {
1344             // Expect IllegalStateException here.
1345         }
1346     }
1347 
1348     @Test
testGetCustomParcelable()1349     public void testGetCustomParcelable() {
1350         Parcelable parcelable = new CustomParcelable(13, "Tiramisu");
1351         mBundle.putParcelable(KEY1, parcelable);
1352         assertEquals(parcelable, mBundle.getParcelable(KEY1));
1353         assertEquals(1, mBundle.size());
1354         roundtrip();
1355         assertNotSame(parcelable, mBundle.getParcelable(KEY1));
1356         assertEquals(parcelable, mBundle.getParcelable(KEY1));
1357         assertEquals(1, mBundle.size());
1358     }
1359 
1360     @Test
testGetNestedParcelable()1361     public void testGetNestedParcelable() {
1362         Parcelable nested = new CustomParcelable(13, "Tiramisu");
1363         ComposedParcelable parcelable = new ComposedParcelable(26, nested);
1364         mBundle.putParcelable(KEY1, parcelable);
1365         assertEquals(parcelable, mBundle.getParcelable(KEY1));
1366         assertEquals(1, mBundle.size());
1367         roundtrip();
1368         ComposedParcelable reconstructed = mBundle.getParcelable(KEY1);
1369         assertNotSame(parcelable, reconstructed);
1370         assertEquals(parcelable, reconstructed);
1371         assertNotSame(nested, reconstructed.parcelable);
1372         assertEquals(nested, reconstructed.parcelable);
1373         assertEquals(1, mBundle.size());
1374     }
1375 
1376     @Test
testItemDeserializationIndependence()1377     public void testItemDeserializationIndependence() {
1378         Parcelable parcelable = new CustomParcelable(13, "Tiramisu");
1379         Parcelable bomb = new CustomParcelable(13, "Tiramisu").setThrowsDuringDeserialization(true);
1380         mBundle.putParcelable(KEY1, parcelable);
1381         mBundle.putParcelable(KEY2, bomb);
1382         assertEquals(parcelable, mBundle.getParcelable(KEY1));
1383         assertEquals(bomb, mBundle.getParcelable(KEY2));
1384         assertEquals(2, mBundle.size());
1385         roundtrip();
1386         assertEquals(2, mBundle.size());
1387         Parcelable reParcelable = mBundle.getParcelable(KEY1);
1388         // Passed if it didn't throw
1389         assertNotSame(parcelable, reParcelable);
1390         assertEquals(parcelable, reParcelable);
1391         assertThrows(RuntimeException.class, () -> mBundle.getParcelable(KEY2));
1392         assertEquals(2, mBundle.size());
1393     }
1394 
1395     @Test
testLazyValueReserialization()1396     public void testLazyValueReserialization() {
1397         Parcelable parcelable = new CustomParcelable(13, "Tiramisu");
1398         mBundle.putParcelable(KEY1, parcelable);
1399         mBundle.putString(KEY2, "value");
1400         roundtrip();
1401         assertEquals("value", mBundle.getString(KEY2));
1402         // Since we haven't retrieved KEY1, its value is still a lazy value inside bundle
1403         roundtrip();
1404         assertEquals(parcelable, mBundle.getParcelable(KEY1));
1405         assertEquals("value", mBundle.getString(KEY2));
1406     }
1407 
1408     @Test
testPutAll_withLazyValues()1409     public void testPutAll_withLazyValues() {
1410         Parcelable parcelable = new CustomParcelable(13, "Tiramisu");
1411         mBundle.putParcelable(KEY1, parcelable);
1412         roundtrip();
1413         mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values)
1414         Bundle copy = new Bundle();
1415         copy.putAll(mBundle);
1416         assertEquals(parcelable, copy.getParcelable(KEY1));
1417         // Here we're verifying that LazyValue caches the deserialized object, hence they are the
1418         // same instance
1419         assertSame(copy.getParcelable(KEY1), mBundle.getParcelable(KEY1));
1420         assertEquals(1, copy.size());
1421     }
1422 
1423     @Test
testDeepCopy_withLazyValues()1424     public void testDeepCopy_withLazyValues() {
1425         Parcelable parcelable = new CustomParcelable(13, "Tiramisu");
1426         mBundle.putParcelable(KEY1, parcelable);
1427         roundtrip();
1428         mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values)
1429         Bundle copy = mBundle.deepCopy();
1430         assertEquals(parcelable, copy.getParcelable(KEY1));
1431         // Here we're verifying that LazyValue caches the deserialized object, hence they are the
1432         // same instance
1433         assertSame(copy.getParcelable(KEY1), mBundle.getParcelable(KEY1));
1434         assertEquals(1, copy.size());
1435     }
1436 
1437     @Test
testDeepCopy_withNestedParcelable()1438     public void testDeepCopy_withNestedParcelable() {
1439         Parcelable nested = new CustomParcelable(13, "Tiramisu");
1440         ComposedParcelable parcelable = new ComposedParcelable(26, nested);
1441         mBundle.putParcelable(KEY1, parcelable);
1442         roundtrip();
1443         mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values)
1444         Bundle copy = mBundle.deepCopy();
1445         ComposedParcelable reconstructed = copy.getParcelable(KEY1);
1446         assertEquals(parcelable, reconstructed);
1447         assertSame(copy.getParcelable(KEY1), mBundle.getParcelable(KEY1));
1448         assertEquals(nested, reconstructed.parcelable);
1449         assertEquals(1, copy.size());
1450     }
1451 
1452     @Test
testDeepCopy_withNestedBundleAndLazyValues()1453     public void testDeepCopy_withNestedBundleAndLazyValues() {
1454         Parcelable parcelable = new CustomParcelable(13, "Tiramisu");
1455         Bundle inner = new Bundle();
1456         inner.putParcelable(KEY1, parcelable);
1457         inner = roundtrip(inner);
1458         inner.setClassLoader(getClass().getClassLoader());
1459         inner.isEmpty(); // Triggers partial deserialization (leaving lazy values)
1460         mBundle.putParcelable(KEY1, inner);
1461         Bundle copy = mBundle.deepCopy();
1462         assertEquals(parcelable, copy.getBundle(KEY1).getParcelable(KEY1));
1463         assertNotSame(mBundle.getBundle(KEY1), copy.getBundle(KEY1));
1464         assertSame(mBundle.getBundle(KEY1).getParcelable(KEY1),
1465                 copy.getBundle(KEY1).getParcelable(KEY1));
1466         assertEquals(1, copy.getBundle(KEY1).size());
1467         assertEquals(1, copy.size());
1468     }
1469 
1470     @Test
testGetParcelable_isLazy()1471     public void testGetParcelable_isLazy() {
1472         mBundle.putParcelable(KEY1, new CustomParcelable(13, "Tiramisu"));
1473         roundtrip();
1474         mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values)
1475         assertThat(CustomParcelable.sDeserialized).isFalse();
1476         mBundle.getParcelable(KEY1);
1477         assertThat(CustomParcelable.sDeserialized).isTrue();
1478     }
1479 
1480     @Test
testGetParcelableArray_isLazy()1481     public void testGetParcelableArray_isLazy() {
1482         mBundle.putParcelableArray(KEY1, new Parcelable[] {new CustomParcelable(13, "Tiramisu")});
1483         roundtrip();
1484         mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values)
1485         assertThat(CustomParcelable.sDeserialized).isFalse();
1486         mBundle.getParcelableArray(KEY1);
1487         assertThat(CustomParcelable.sDeserialized).isTrue();
1488     }
1489 
1490     @Test
testGetParcelableArrayList_isLazy()1491     public void testGetParcelableArrayList_isLazy() {
1492         mBundle.putParcelableArrayList(KEY1,
1493                 new ArrayList<>(singletonList(new CustomParcelable(13, "Tiramisu"))));
1494         roundtrip();
1495         mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values)
1496         assertThat(CustomParcelable.sDeserialized).isFalse();
1497         mBundle.getParcelableArrayList(KEY1);
1498         assertThat(CustomParcelable.sDeserialized).isTrue();
1499     }
1500 
1501     @Test
testGetSparseParcelableArray_isLazy()1502     public void testGetSparseParcelableArray_isLazy() {
1503         SparseArray<Parcelable> container = new SparseArray<>();
1504         container.put(0, new CustomParcelable(13, "Tiramisu"));
1505         mBundle.putSparseParcelableArray(KEY1, container);
1506         roundtrip();
1507         mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values)
1508         assertThat(CustomParcelable.sDeserialized).isFalse();
1509         mBundle.getSparseParcelableArray(KEY1);
1510         assertThat(CustomParcelable.sDeserialized).isTrue();
1511     }
1512 
1513     @Test
testGetSerializable_isLazy()1514     public void testGetSerializable_isLazy() {
1515         mBundle.putSerializable(KEY1, new CustomSerializable());
1516         roundtrip();
1517         mBundle.isEmpty(); // Triggers partial deserialization (leaving lazy values)
1518         assertThat(CustomSerializable.sDeserialized).isFalse();
1519         mBundle.getSerializable(KEY1);
1520         assertThat(CustomSerializable.sDeserialized).isTrue();
1521     }
1522 
1523     public static class CustomSerializable implements Serializable {
1524         public static boolean sDeserialized = false;
1525 
readObject(ObjectInputStream in)1526         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
1527             in.defaultReadObject();
1528             sDeserialized = true;
1529         }
1530     }
1531 
1532     public static class AnotherSerializable implements Serializable {
1533     }
1534 
1535     public static class CustomParcelable implements Parcelable {
1536         public static boolean sDeserialized = false;
1537 
1538         public final int integer;
1539         public final String string;
1540         public boolean throwsDuringDeserialization;
1541 
CustomParcelable(int integer, String string)1542         public CustomParcelable(int integer, String string) {
1543             this.integer = integer;
1544             this.string = string;
1545         }
1546 
CustomParcelable(Parcel in)1547         protected CustomParcelable(Parcel in) {
1548             integer = in.readInt();
1549             string = in.readString();
1550             throwsDuringDeserialization = in.readBoolean();
1551             if (throwsDuringDeserialization) {
1552                 throw new RuntimeException();
1553             }
1554             sDeserialized = true;
1555         }
1556 
setThrowsDuringDeserialization( boolean throwsDuringDeserialization)1557         public CustomParcelable setThrowsDuringDeserialization(
1558                 boolean throwsDuringDeserialization) {
1559             this.throwsDuringDeserialization = throwsDuringDeserialization;
1560             return this;
1561         }
1562 
1563         @Override
describeContents()1564         public int describeContents() {
1565             return 0;
1566         }
1567 
1568         @Override
writeToParcel(Parcel out, int flags)1569         public void writeToParcel(Parcel out, int flags) {
1570             out.writeInt(integer);
1571             out.writeString(string);
1572             out.writeBoolean(throwsDuringDeserialization);
1573         }
1574 
1575         @Override
equals(Object other)1576         public boolean equals(Object other) {
1577             if (this == other) {
1578                 return true;
1579             }
1580             if (!(other instanceof CustomParcelable)) {
1581                 return false;
1582             }
1583             CustomParcelable that = (CustomParcelable) other;
1584             return integer == that.integer
1585                     && throwsDuringDeserialization == that.throwsDuringDeserialization
1586                     && string.equals(that.string);
1587         }
1588 
1589         @Override
hashCode()1590         public int hashCode() {
1591             return Objects.hash(integer, string, throwsDuringDeserialization);
1592         }
1593 
1594         public static final Creator<CustomParcelable> CREATOR = new Creator<CustomParcelable>() {
1595             @Override
1596             public CustomParcelable createFromParcel(Parcel in) {
1597                 return new CustomParcelable(in);
1598             }
1599             @Override
1600             public CustomParcelable[] newArray(int size) {
1601                 return new CustomParcelable[size];
1602             }
1603         };
1604     }
1605 
1606     public static class ComposedParcelable implements Parcelable {
1607         public final int integer;
1608         public final Parcelable parcelable;
1609 
ComposedParcelable(int integer, Parcelable parcelable)1610         public ComposedParcelable(int integer, Parcelable parcelable) {
1611             this.integer = integer;
1612             this.parcelable = parcelable;
1613         }
1614 
ComposedParcelable(Parcel in)1615         protected ComposedParcelable(Parcel in) {
1616             integer = in.readInt();
1617             parcelable = in.readParcelable(getClass().getClassLoader());
1618         }
1619 
1620         @Override
describeContents()1621         public int describeContents() {
1622             return 0;
1623         }
1624 
1625         @Override
writeToParcel(Parcel out, int flags)1626         public void writeToParcel(Parcel out, int flags) {
1627             out.writeInt(integer);
1628             out.writeParcelable(parcelable, flags);
1629         }
1630 
1631         @Override
equals(Object other)1632         public boolean equals(Object other) {
1633             if (this == other) {
1634                 return true;
1635             }
1636             if (!(other instanceof ComposedParcelable)) {
1637                 return false;
1638             }
1639             ComposedParcelable that = (ComposedParcelable) other;
1640             return integer == that.integer && Objects.equals(parcelable, that.parcelable);
1641         }
1642 
1643         @Override
hashCode()1644         public int hashCode() {
1645             return Objects.hash(integer, parcelable);
1646         }
1647 
1648         public static final Creator<ComposedParcelable> CREATOR =
1649                 new Creator<ComposedParcelable>() {
1650                     @Override
1651                     public ComposedParcelable createFromParcel(Parcel in) {
1652                         return new ComposedParcelable(in);
1653                     }
1654                     @Override
1655                     public ComposedParcelable[] newArray(int size) {
1656                         return new ComposedParcelable[size];
1657                     }
1658                 };
1659     }
1660 
1661     /** Create a Bundle with values, with autogenerated keys. */
buildBundle(Object... values)1662     private static Bundle buildBundle(Object... values) {
1663         final Bundle result = new Bundle();
1664 
1665         for (int i = 0; i < values.length; i++) {
1666             final String key = "key-" + i;
1667 
1668             final Object value = values[i];
1669             if (value == null) {
1670                 result.putString(key, null);
1671 
1672             } else if (value instanceof String) {
1673                 result.putString(key, (String) value);
1674 
1675             } else if (value instanceof Integer) {
1676                 result.putInt(key, (Integer) value);
1677 
1678             } else if (value instanceof Parcelable) {
1679                 result.putParcelable(key, (Parcelable) value);
1680 
1681             } else if (value instanceof Parcelable[]) {
1682                 result.putParcelableArray(key, (Parcelable[]) value);
1683 
1684             } else {
1685                 fail("Unsupported value type: " + value.getClass());
1686             }
1687         }
1688         return result;
1689     }
1690 
cloneBundle(Bundle b)1691     private static Bundle cloneBundle(Bundle b) {
1692         return new Bundle(b);
1693     }
1694 
cloneBundleViaParcel(Bundle b)1695     private static Bundle cloneBundleViaParcel(Bundle b) {
1696         final Parcel p = Parcel.obtain();
1697         try {
1698             p.writeParcelable(b, 0);
1699 
1700             p.setDataPosition(0);
1701 
1702             return p.readParcelable(Bundle.class.getClassLoader());
1703         } finally {
1704             p.recycle();
1705         }
1706     }
1707 
assertHasFd(Bundle b)1708     private static void assertHasFd(Bundle b) {
1709         assertTrue(b.hasFileDescriptors());
1710 
1711         // Make sure cloned ones have the same result.
1712         assertTrue(cloneBundle(b).hasFileDescriptors());
1713         assertTrue(cloneBundleViaParcel(b).hasFileDescriptors());
1714     }
1715 
assertNotHaveFd(Bundle b)1716     private static void assertNotHaveFd(Bundle b) {
1717         assertFalse(b.hasFileDescriptors());
1718 
1719         // Make sure cloned ones have the same result.
1720         assertFalse(cloneBundle(b).hasFileDescriptors());
1721         assertFalse(cloneBundleViaParcel(b).hasFileDescriptors());
1722     }
1723 
1724     class MockClassLoader extends ClassLoader {
MockClassLoader()1725         MockClassLoader() {
1726             super();
1727         }
1728     }
1729 
uncheck(Callable<T> runnable)1730     private static <T> T uncheck(Callable<T> runnable) {
1731         try {
1732             return runnable.call();
1733         } catch (Exception e) {
1734             throw new AssertionError(e);
1735         }
1736     }
1737 }
1738