1f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinskipackage android.content.pm;
2f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
3f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinskiimport android.os.Parcel;
4f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinskiimport android.os.Parcelable;
5bdbde55592792efe350acd6a46733f439f6a3f3dAurimas Liutikasimport android.support.test.filters.LargeTest;
62682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru
7f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinskiimport junit.framework.TestCase;
8f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
9f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinskiimport java.util.ArrayList;
102682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaruimport java.util.Collections;
11f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinskiimport java.util.List;
12f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
13bdbde55592792efe350acd6a46733f439f6a3f3dAurimas Liutikas@LargeTest
14f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinskipublic class ParceledListSliceTest extends TestCase {
15f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
16f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    public void testSmallList() throws Exception {
17f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        final int objectCount = 100;
1848c95c4370533bf27e537cbca1e64d060a016c5fJon Larimer        List<SmallObject> list = new ArrayList<SmallObject>();
19f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        for (int i = 0; i < objectCount; i++) {
20f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            list.add(new SmallObject(i * 2, (i * 2) + 1));
21f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
22f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
23f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        ParceledListSlice<SmallObject> slice;
24f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
25f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        Parcel parcel = Parcel.obtain();
26f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        try {
2748c95c4370533bf27e537cbca1e64d060a016c5fJon Larimer            parcel.writeParcelable(new ParceledListSlice<SmallObject>(list), 0);
28f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            parcel.setDataPosition(0);
29f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            slice = parcel.readParcelable(getClass().getClassLoader());
30f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        } finally {
31f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            parcel.recycle();
32f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
33f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
34f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        assertNotNull(slice);
35f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        assertNotNull(slice.getList());
36f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        assertEquals(objectCount, slice.getList().size());
37f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
38f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        for (int i = 0; i < objectCount; i++) {
39f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            assertEquals(i * 2, slice.getList().get(i).mFieldA);
40f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            assertEquals((i * 2) + 1, slice.getList().get(i).mFieldB);
41f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
42f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    }
43f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
44f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    private static int measureLargeObject() {
45f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        Parcel p = Parcel.obtain();
46f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        try {
47f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            new LargeObject(0, 0, 0, 0, 0).writeToParcel(p, 0);
48f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            return p.dataPosition();
49f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        } finally {
50f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            p.recycle();
51f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
52f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    }
53f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
54f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    /**
55f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski     * Test that when the list is large, the data is successfully parceled
56f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski     * and unparceled (the implementation will send pieces of the list in
57f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski     * separate round-trips to avoid the IPC limit).
58f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski     */
59f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    public void testLargeList() throws Exception {
60f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        final int thresholdBytes = 256 * 1024;
61f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        final int objectCount = thresholdBytes / measureLargeObject();
62f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
6348c95c4370533bf27e537cbca1e64d060a016c5fJon Larimer        List<LargeObject> list = new ArrayList<LargeObject>();
64f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        for (int i = 0; i < objectCount; i++) {
65f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            list.add(new LargeObject(
66f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    i * 5,
67f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    (i * 5) + 1,
68f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    (i * 5) + 2,
69f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    (i * 5) + 3,
70f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    (i * 5) + 4
71f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            ));
72f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
73f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
74f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        ParceledListSlice<LargeObject> slice;
75f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
76f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        Parcel parcel = Parcel.obtain();
77f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        try {
7848c95c4370533bf27e537cbca1e64d060a016c5fJon Larimer            parcel.writeParcelable(new ParceledListSlice<LargeObject>(list), 0);
79f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            parcel.setDataPosition(0);
80f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            slice = parcel.readParcelable(getClass().getClassLoader());
81f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        } finally {
82f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            parcel.recycle();
83f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
84f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
85f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        assertNotNull(slice);
86f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        assertNotNull(slice.getList());
87f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        assertEquals(objectCount, slice.getList().size());
88f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
89f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        for (int i = 0; i < objectCount; i++) {
90f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            assertEquals(i * 5, slice.getList().get(i).mFieldA);
91f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            assertEquals((i * 5) + 1, slice.getList().get(i).mFieldB);
92f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            assertEquals((i * 5) + 2, slice.getList().get(i).mFieldC);
93f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            assertEquals((i * 5) + 3, slice.getList().get(i).mFieldD);
94f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            assertEquals((i * 5) + 4, slice.getList().get(i).mFieldE);
95f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
96f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    }
97f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
982682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru    private void sendParcelStringList(List<String> list) {
99abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee        StringParceledListSlice slice;
100abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee        Parcel parcel = Parcel.obtain();
1012682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru
102abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee        try {
103abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee            parcel.writeParcelable(new StringParceledListSlice(list), 0);
104abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee            parcel.setDataPosition(0);
105abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee            slice = parcel.readParcelable(getClass().getClassLoader());
106abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee        } finally {
107abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee            parcel.recycle();
108abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee        }
109abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee
110abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee        assertNotNull(slice);
111abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee        assertNotNull(slice.getList());
112abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee        assertEquals(list, slice.getList());
113abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee    }
114abaa0695c5361b36a7a2cdbe87c77bf60be20af7Robin Lee
1152682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru    public void testStringList() throws Exception {
1162682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru        final int objectCount = 400;
1172682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru        List<String> list = new ArrayList<String>();
1182682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru        for (long i = 0; i < objectCount; i++) {
1192682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru            list.add(Long.toString(i * (6 - i)));
1202682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru        }
1212682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru
1222682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru        sendParcelStringList(list);
1232682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru    }
1242682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru
1252682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru    public void testLargeStringList() throws Exception {
1262682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru        final int thresholdBytes = 256 * 1024;
1272682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru        final String value = Long.toString(Long.MAX_VALUE);
1282682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru        final int objectCount = 2 * thresholdBytes / value.length();
1292682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru        final List<String> list = Collections.nCopies(objectCount, value);
1302682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru
1312682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru        sendParcelStringList(list);
1322682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru    }
1332682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru
1342682fa70678ec79131329a6071d70c3d84c23d41Alexandru-Andrei Rotaru
135f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    /**
136f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski     * Test that only homogeneous elements may be unparceled.
137f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski     */
138f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    public void testHomogeneousElements() throws Exception {
13948c95c4370533bf27e537cbca1e64d060a016c5fJon Larimer        List<BaseObject> list = new ArrayList<BaseObject>();
140f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        list.add(new LargeObject(0, 1, 2, 3, 4));
141f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        list.add(new SmallObject(5, 6));
142f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        list.add(new SmallObject(7, 8));
143f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
144f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        Parcel parcel = Parcel.obtain();
145f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        try {
146f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            writeEvilParceledListSlice(parcel, list);
147f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            parcel.setDataPosition(0);
148f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            try {
149f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                ParceledListSlice.CREATOR.createFromParcel(parcel, getClass().getClassLoader());
150f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                assertTrue("Unparceled heterogeneous ParceledListSlice", false);
151f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            } catch (IllegalArgumentException e) {
152f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                // Success, we're not allowed to process heterogeneous
153f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                // elements in a ParceledListSlice.
154f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            }
155f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        } finally {
156f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            parcel.recycle();
157f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
158f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    }
159f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
160f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    /**
161f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski     * Write a ParcelableListSlice that uses the BaseObject base class as the Creator.
162f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski     * This is dangerous, as it may affect how the data is unparceled, then later parceled
163f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski     * by the system, leading to a self-modifying data security vulnerability.
164f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski     */
165f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    private static <T extends BaseObject> void writeEvilParceledListSlice(Parcel dest, List<T> list) {
166f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        final int listCount = list.size();
167f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
168f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        // Number of items.
169f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        dest.writeInt(listCount);
170f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
171f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        // The type/creator to use when unparceling. Here we use the base class
172f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        // to simulate an attack on ParceledListSlice.
173f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        dest.writeString(BaseObject.class.getName());
174f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
175f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        for (int i = 0; i < listCount; i++) {
176f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            // 1 means the item is present.
177f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            dest.writeInt(1);
178f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            list.get(i).writeToParcel(dest, 0);
179f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
180f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    }
181f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
182f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    public abstract static class BaseObject implements Parcelable {
183f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        protected static final int TYPE_SMALL = 0;
184f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        protected static final int TYPE_LARGE = 1;
185f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
186f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        protected void writeToParcel(Parcel dest, int flags, int type) {
187f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            dest.writeInt(type);
188f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
189f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
190f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        @Override
191f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public int describeContents() {
192f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            return 0;
193f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
194f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
195f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        /**
196f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski         * This is *REALLY* bad, but we're doing it in the test to ensure that we handle
197f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski         * the possible exploit when unparceling an object with the BaseObject written as
198f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski         * Creator.
199f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski         */
200f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public static final Creator<BaseObject> CREATOR = new Creator<BaseObject>() {
201f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            @Override
202f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            public BaseObject createFromParcel(Parcel source) {
203f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                switch (source.readInt()) {
204f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    case TYPE_SMALL:
205f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                        return SmallObject.createFromParcelBody(source);
206f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    case TYPE_LARGE:
207f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                        return LargeObject.createFromParcelBody(source);
208f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    default:
209f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                        throw new IllegalArgumentException("Unknown type");
210f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                }
211f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            }
212f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
213f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            @Override
214f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            public BaseObject[] newArray(int size) {
215f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                return new BaseObject[size];
216f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            }
217f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        };
218f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    }
219f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
220f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    public static class SmallObject extends BaseObject {
221f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public int mFieldA;
222f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public int mFieldB;
223f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
224f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public SmallObject(int a, int b) {
225f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            mFieldA = a;
226f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            mFieldB = b;
227f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
228f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
229f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        @Override
230f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public void writeToParcel(Parcel dest, int flags) {
231f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            super.writeToParcel(dest, flags, TYPE_SMALL);
232f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            dest.writeInt(mFieldA);
233f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            dest.writeInt(mFieldB);
234f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
235f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
236f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public static SmallObject createFromParcelBody(Parcel source) {
237f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            return new SmallObject(source.readInt(), source.readInt());
238f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
239f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
240f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public static final Creator<SmallObject> CREATOR = new Creator<SmallObject>() {
241f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            @Override
242f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            public SmallObject createFromParcel(Parcel source) {
243f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                // Consume the type (as it is always written out).
244f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                source.readInt();
245f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                return createFromParcelBody(source);
246f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            }
247f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
248f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            @Override
249f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            public SmallObject[] newArray(int size) {
250f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                return new SmallObject[size];
251f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            }
252f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        };
253f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    }
254f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
255f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    public static class LargeObject extends BaseObject {
256f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public int mFieldA;
257f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public int mFieldB;
258f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public int mFieldC;
259f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public int mFieldD;
260f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public int mFieldE;
261f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
262f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public LargeObject(int a, int b, int c, int d, int e) {
263f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            mFieldA = a;
264f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            mFieldB = b;
265f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            mFieldC = c;
266f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            mFieldD = d;
267f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            mFieldE = e;
268f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
269f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
270f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        @Override
271f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public void writeToParcel(Parcel dest, int flags) {
272f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            super.writeToParcel(dest, flags, TYPE_LARGE);
273f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            dest.writeInt(mFieldA);
274f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            dest.writeInt(mFieldB);
275f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            dest.writeInt(mFieldC);
276f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            dest.writeInt(mFieldD);
277f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            dest.writeInt(mFieldE);
278f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
279f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
280f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public static LargeObject createFromParcelBody(Parcel source) {
281f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            return new LargeObject(
282f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    source.readInt(),
283f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    source.readInt(),
284f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    source.readInt(),
285f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    source.readInt(),
286f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                    source.readInt()
287f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            );
288f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        }
289f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
290f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        public static final Creator<LargeObject> CREATOR = new Creator<LargeObject>() {
291f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            @Override
292f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            public LargeObject createFromParcel(Parcel source) {
293f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                // Consume the type (as it is always written out).
294f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                source.readInt();
295f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                return createFromParcelBody(source);
296f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            }
297f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski
298f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            @Override
299f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            public LargeObject[] newArray(int size) {
300f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski                return new LargeObject[size];
301f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski            }
302f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski        };
303f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski    }
304f741c3727383008b131cd3877cbdb3857e07fc9bAdam Lesinski}
305