blob: ee7bd9acec77d2cbf3391461b53bc6b11fe8ee1c [file] [log] [blame]
Craig Mautner719e6b12014-04-04 20:29:41 -07001/*
2 * Copyright (C) 2014 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
17package android.os;
18
Scott Kennedyc6a65dff2015-03-01 17:10:10 -080019import android.annotation.Nullable;
Craig Mautner719e6b12014-04-04 20:29:41 -070020import android.util.ArrayMap;
21import android.util.Log;
Adam Lesinski1619ed42015-09-22 13:02:09 -070022import android.util.MathUtils;
Craig Mautner719e6b12014-04-04 20:29:41 -070023
24import java.io.Serializable;
25import java.util.ArrayList;
Craig Mautner719e6b12014-04-04 20:29:41 -070026import java.util.Set;
27
28/**
29 * A mapping from String values to various types.
30 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -070031public class BaseBundle {
Craig Mautner719e6b12014-04-04 20:29:41 -070032 private static final String TAG = "Bundle";
33 static final boolean DEBUG = false;
34
Samuel Tan3cefe6a2015-12-14 13:29:17 -080035 // Keep in sync with frameworks/native/libs/binder/PersistableBundle.cpp.
Craig Mautner719e6b12014-04-04 20:29:41 -070036 static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
Samuel Tan3cefe6a2015-12-14 13:29:17 -080037
Craig Mautner719e6b12014-04-04 20:29:41 -070038 static final Parcel EMPTY_PARCEL;
39
40 static {
41 EMPTY_PARCEL = Parcel.obtain();
42 }
43
44 // Invariant - exactly one of mMap / mParcelledData will be null
45 // (except inside a call to unparcel)
46
47 ArrayMap<String, Object> mMap = null;
48
49 /*
50 * If mParcelledData is non-null, then mMap will be null and the
51 * data are stored as a Parcel containing a Bundle. When the data
52 * are unparcelled, mParcelledData willbe set to null.
53 */
54 Parcel mParcelledData = null;
55
56 /**
57 * The ClassLoader used when unparcelling data from mParcelledData.
58 */
59 private ClassLoader mClassLoader;
60
61 /**
62 * Constructs a new, empty Bundle that uses a specific ClassLoader for
63 * instantiating Parcelable and Serializable objects.
64 *
65 * @param loader An explicit ClassLoader to use when instantiating objects
66 * inside of the Bundle.
67 * @param capacity Initial size of the ArrayMap.
68 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -080069 BaseBundle(@Nullable ClassLoader loader, int capacity) {
Craig Mautner719e6b12014-04-04 20:29:41 -070070 mMap = capacity > 0 ?
71 new ArrayMap<String, Object>(capacity) : new ArrayMap<String, Object>();
72 mClassLoader = loader == null ? getClass().getClassLoader() : loader;
73 }
74
75 /**
76 * Constructs a new, empty Bundle.
77 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -070078 BaseBundle() {
Craig Mautner719e6b12014-04-04 20:29:41 -070079 this((ClassLoader) null, 0);
80 }
81
82 /**
83 * Constructs a Bundle whose data is stored as a Parcel. The data
84 * will be unparcelled on first contact, using the assigned ClassLoader.
85 *
86 * @param parcelledData a Parcel containing a Bundle
87 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -070088 BaseBundle(Parcel parcelledData) {
Craig Mautner719e6b12014-04-04 20:29:41 -070089 readFromParcelInner(parcelledData);
90 }
91
Craig Mautner0a8e160e2014-05-29 10:27:32 -070092 BaseBundle(Parcel parcelledData, int length) {
Craig Mautner719e6b12014-04-04 20:29:41 -070093 readFromParcelInner(parcelledData, length);
94 }
95
96 /**
97 * Constructs a new, empty Bundle that uses a specific ClassLoader for
98 * instantiating Parcelable and Serializable objects.
99 *
100 * @param loader An explicit ClassLoader to use when instantiating objects
101 * inside of the Bundle.
102 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700103 BaseBundle(ClassLoader loader) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700104 this(loader, 0);
105 }
106
107 /**
108 * Constructs a new, empty Bundle sized to hold the given number of
109 * elements. The Bundle will grow as needed.
110 *
111 * @param capacity the initial capacity of the Bundle
112 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700113 BaseBundle(int capacity) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700114 this((ClassLoader) null, capacity);
115 }
116
117 /**
118 * Constructs a Bundle containing a copy of the mappings from the given
119 * Bundle.
120 *
121 * @param b a Bundle to be copied.
122 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700123 BaseBundle(BaseBundle b) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700124 if (b.mParcelledData != null) {
125 if (b.mParcelledData == EMPTY_PARCEL) {
126 mParcelledData = EMPTY_PARCEL;
127 } else {
128 mParcelledData = Parcel.obtain();
129 mParcelledData.appendFrom(b.mParcelledData, 0, b.mParcelledData.dataSize());
130 mParcelledData.setDataPosition(0);
131 }
132 } else {
133 mParcelledData = null;
134 }
135
136 if (b.mMap != null) {
137 mMap = new ArrayMap<String, Object>(b.mMap);
138 } else {
139 mMap = null;
140 }
141
142 mClassLoader = b.mClassLoader;
143 }
144
145 /**
146 * TODO: optimize this later (getting just the value part of a Bundle
147 * with a single pair) once Bundle.forPair() above is implemented
148 * with a special single-value Map implementation/serialization.
149 *
150 * Note: value in single-pair Bundle may be null.
151 *
152 * @hide
153 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700154 public String getPairValue() {
Craig Mautner719e6b12014-04-04 20:29:41 -0700155 unparcel();
156 int size = mMap.size();
157 if (size > 1) {
158 Log.w(TAG, "getPairValue() used on Bundle with multiple pairs.");
159 }
160 if (size == 0) {
161 return null;
162 }
163 Object o = mMap.valueAt(0);
164 try {
165 return (String) o;
166 } catch (ClassCastException e) {
167 typeWarning("getPairValue()", o, "String", e);
168 return null;
169 }
170 }
171
172 /**
173 * Changes the ClassLoader this Bundle uses when instantiating objects.
174 *
175 * @param loader An explicit ClassLoader to use when instantiating objects
176 * inside of the Bundle.
177 */
178 void setClassLoader(ClassLoader loader) {
179 mClassLoader = loader;
180 }
181
182 /**
183 * Return the ClassLoader currently associated with this Bundle.
184 */
185 ClassLoader getClassLoader() {
186 return mClassLoader;
187 }
188
189 /**
190 * If the underlying data are stored as a Parcel, unparcel them
191 * using the currently assigned class loader.
192 */
193 /* package */ synchronized void unparcel() {
194 if (mParcelledData == null) {
195 if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
196 + ": no parcelled data");
197 return;
198 }
199
200 if (mParcelledData == EMPTY_PARCEL) {
201 if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
202 + ": empty");
203 if (mMap == null) {
204 mMap = new ArrayMap<String, Object>(1);
205 } else {
206 mMap.erase();
207 }
208 mParcelledData = null;
209 return;
210 }
211
212 int N = mParcelledData.readInt();
213 if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
214 + ": reading " + N + " maps");
215 if (N < 0) {
216 return;
217 }
218 if (mMap == null) {
219 mMap = new ArrayMap<String, Object>(N);
220 } else {
221 mMap.erase();
222 mMap.ensureCapacity(N);
223 }
224 mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
225 mParcelledData.recycle();
226 mParcelledData = null;
227 if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
228 + " final map: " + mMap);
229 }
230
231 /**
232 * @hide
233 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700234 public boolean isParcelled() {
Craig Mautner719e6b12014-04-04 20:29:41 -0700235 return mParcelledData != null;
236 }
237
238 /**
239 * Returns the number of mappings contained in this Bundle.
240 *
241 * @return the number of mappings as an int.
242 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700243 public int size() {
Craig Mautner719e6b12014-04-04 20:29:41 -0700244 unparcel();
245 return mMap.size();
246 }
247
248 /**
249 * Returns true if the mapping of this Bundle is empty, false otherwise.
250 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700251 public boolean isEmpty() {
Craig Mautner719e6b12014-04-04 20:29:41 -0700252 unparcel();
253 return mMap.isEmpty();
254 }
255
256 /**
257 * Removes all elements from the mapping of this Bundle.
258 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700259 public void clear() {
Craig Mautner719e6b12014-04-04 20:29:41 -0700260 unparcel();
261 mMap.clear();
262 }
263
264 /**
265 * Returns true if the given key is contained in the mapping
266 * of this Bundle.
267 *
268 * @param key a String key
269 * @return true if the key is part of the mapping, false otherwise
270 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700271 public boolean containsKey(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700272 unparcel();
273 return mMap.containsKey(key);
274 }
275
276 /**
277 * Returns the entry with the given key as an object.
278 *
279 * @param key a String key
280 * @return an Object, or null
281 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800282 @Nullable
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700283 public Object get(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700284 unparcel();
285 return mMap.get(key);
286 }
287
288 /**
289 * Removes any entry with the given key from the mapping of this Bundle.
290 *
291 * @param key a String key
292 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700293 public void remove(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700294 unparcel();
295 mMap.remove(key);
296 }
297
298 /**
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700299 * Inserts all mappings from the given PersistableBundle into this BaseBundle.
Craig Mautner719e6b12014-04-04 20:29:41 -0700300 *
301 * @param bundle a PersistableBundle
302 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700303 public void putAll(PersistableBundle bundle) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700304 unparcel();
305 bundle.unparcel();
306 mMap.putAll(bundle.mMap);
307 }
308
309 /**
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700310 * Inserts all mappings from the given Map into this BaseBundle.
Craig Mautner21d24a22014-04-23 11:45:37 -0700311 *
312 * @param map a Map
313 */
Dianne Hackborna83ce1d2015-03-11 15:16:13 -0700314 void putAll(ArrayMap map) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700315 unparcel();
316 mMap.putAll(map);
317 }
318
319 /**
Craig Mautner719e6b12014-04-04 20:29:41 -0700320 * Returns a Set containing the Strings used as keys in this Bundle.
321 *
322 * @return a Set of String keys
323 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700324 public Set<String> keySet() {
Craig Mautner719e6b12014-04-04 20:29:41 -0700325 unparcel();
326 return mMap.keySet();
327 }
328
329 /**
330 * Inserts a Boolean value into the mapping of this Bundle, replacing
331 * any existing value for the given key. Either key or value may be null.
332 *
333 * @param key a String, or null
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800334 * @param value a boolean
Craig Mautner719e6b12014-04-04 20:29:41 -0700335 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800336 public void putBoolean(@Nullable String key, boolean value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700337 unparcel();
338 mMap.put(key, value);
339 }
340
341 /**
342 * Inserts a byte value into the mapping of this Bundle, replacing
343 * any existing value for the given key.
344 *
345 * @param key a String, or null
346 * @param value a byte
347 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800348 void putByte(@Nullable String key, byte value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700349 unparcel();
350 mMap.put(key, value);
351 }
352
353 /**
354 * Inserts a char value into the mapping of this Bundle, replacing
355 * any existing value for the given key.
356 *
357 * @param key a String, or null
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800358 * @param value a char
Craig Mautner719e6b12014-04-04 20:29:41 -0700359 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800360 void putChar(@Nullable String key, char value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700361 unparcel();
362 mMap.put(key, value);
363 }
364
365 /**
366 * Inserts a short value into the mapping of this Bundle, replacing
367 * any existing value for the given key.
368 *
369 * @param key a String, or null
370 * @param value a short
371 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800372 void putShort(@Nullable String key, short value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700373 unparcel();
374 mMap.put(key, value);
375 }
376
377 /**
378 * Inserts an int value into the mapping of this Bundle, replacing
379 * any existing value for the given key.
380 *
381 * @param key a String, or null
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800382 * @param value an int
Craig Mautner719e6b12014-04-04 20:29:41 -0700383 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800384 public void putInt(@Nullable String key, int value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700385 unparcel();
386 mMap.put(key, value);
387 }
388
389 /**
390 * Inserts a long value into the mapping of this Bundle, replacing
391 * any existing value for the given key.
392 *
393 * @param key a String, or null
394 * @param value a long
395 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800396 public void putLong(@Nullable String key, long value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700397 unparcel();
398 mMap.put(key, value);
399 }
400
401 /**
402 * Inserts a float value into the mapping of this Bundle, replacing
403 * any existing value for the given key.
404 *
405 * @param key a String, or null
406 * @param value a float
407 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800408 void putFloat(@Nullable String key, float value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700409 unparcel();
410 mMap.put(key, value);
411 }
412
413 /**
414 * Inserts a double value into the mapping of this Bundle, replacing
415 * any existing value for the given key.
416 *
417 * @param key a String, or null
418 * @param value a double
419 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800420 public void putDouble(@Nullable String key, double value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700421 unparcel();
422 mMap.put(key, value);
423 }
424
425 /**
426 * Inserts a String value into the mapping of this Bundle, replacing
427 * any existing value for the given key. Either key or value may be null.
428 *
429 * @param key a String, or null
430 * @param value a String, or null
431 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800432 public void putString(@Nullable String key, @Nullable String value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700433 unparcel();
434 mMap.put(key, value);
435 }
436
437 /**
438 * Inserts a CharSequence value into the mapping of this Bundle, replacing
439 * any existing value for the given key. Either key or value may be null.
440 *
441 * @param key a String, or null
442 * @param value a CharSequence, or null
443 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800444 void putCharSequence(@Nullable String key, @Nullable CharSequence value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700445 unparcel();
446 mMap.put(key, value);
447 }
448
449 /**
450 * Inserts an ArrayList<Integer> value into the mapping of this Bundle, replacing
451 * any existing value for the given key. Either key or value may be null.
452 *
453 * @param key a String, or null
454 * @param value an ArrayList<Integer> object, or null
455 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800456 void putIntegerArrayList(@Nullable String key, @Nullable ArrayList<Integer> value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700457 unparcel();
458 mMap.put(key, value);
459 }
460
461 /**
462 * Inserts an ArrayList<String> value into the mapping of this Bundle, replacing
463 * any existing value for the given key. Either key or value may be null.
464 *
465 * @param key a String, or null
466 * @param value an ArrayList<String> object, or null
467 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800468 void putStringArrayList(@Nullable String key, @Nullable ArrayList<String> value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700469 unparcel();
470 mMap.put(key, value);
471 }
472
473 /**
474 * Inserts an ArrayList<CharSequence> value into the mapping of this Bundle, replacing
475 * any existing value for the given key. Either key or value may be null.
476 *
477 * @param key a String, or null
478 * @param value an ArrayList<CharSequence> object, or null
479 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800480 void putCharSequenceArrayList(@Nullable String key, @Nullable ArrayList<CharSequence> value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700481 unparcel();
482 mMap.put(key, value);
483 }
484
485 /**
486 * Inserts a Serializable value into the mapping of this Bundle, replacing
487 * any existing value for the given key. Either key or value may be null.
488 *
489 * @param key a String, or null
490 * @param value a Serializable object, or null
491 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800492 void putSerializable(@Nullable String key, @Nullable Serializable value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700493 unparcel();
494 mMap.put(key, value);
495 }
496
497 /**
498 * Inserts a boolean array value into the mapping of this Bundle, replacing
499 * any existing value for the given key. Either key or value may be null.
500 *
501 * @param key a String, or null
502 * @param value a boolean array object, or null
503 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800504 public void putBooleanArray(@Nullable String key, @Nullable boolean[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700505 unparcel();
506 mMap.put(key, value);
507 }
508
509 /**
510 * Inserts a byte array value into the mapping of this Bundle, replacing
511 * any existing value for the given key. Either key or value may be null.
512 *
513 * @param key a String, or null
514 * @param value a byte array object, or null
515 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800516 void putByteArray(@Nullable String key, @Nullable byte[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700517 unparcel();
518 mMap.put(key, value);
519 }
520
521 /**
522 * Inserts a short array value into the mapping of this Bundle, replacing
523 * any existing value for the given key. Either key or value may be null.
524 *
525 * @param key a String, or null
526 * @param value a short array object, or null
527 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800528 void putShortArray(@Nullable String key, @Nullable short[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700529 unparcel();
530 mMap.put(key, value);
531 }
532
533 /**
534 * Inserts a char array value into the mapping of this Bundle, replacing
535 * any existing value for the given key. Either key or value may be null.
536 *
537 * @param key a String, or null
538 * @param value a char array object, or null
539 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800540 void putCharArray(@Nullable String key, @Nullable char[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700541 unparcel();
542 mMap.put(key, value);
543 }
544
545 /**
546 * Inserts an int array value into the mapping of this Bundle, replacing
547 * any existing value for the given key. Either key or value may be null.
548 *
549 * @param key a String, or null
550 * @param value an int array object, or null
551 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800552 public void putIntArray(@Nullable String key, @Nullable int[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700553 unparcel();
554 mMap.put(key, value);
555 }
556
557 /**
558 * Inserts a long array value into the mapping of this Bundle, replacing
559 * any existing value for the given key. Either key or value may be null.
560 *
561 * @param key a String, or null
562 * @param value a long array object, or null
563 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800564 public void putLongArray(@Nullable String key, @Nullable long[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700565 unparcel();
566 mMap.put(key, value);
567 }
568
569 /**
570 * Inserts a float array value into the mapping of this Bundle, replacing
571 * any existing value for the given key. Either key or value may be null.
572 *
573 * @param key a String, or null
574 * @param value a float array object, or null
575 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800576 void putFloatArray(@Nullable String key, @Nullable float[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700577 unparcel();
578 mMap.put(key, value);
579 }
580
581 /**
582 * Inserts a double array value into the mapping of this Bundle, replacing
583 * any existing value for the given key. Either key or value may be null.
584 *
585 * @param key a String, or null
586 * @param value a double array object, or null
587 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800588 public void putDoubleArray(@Nullable String key, @Nullable double[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700589 unparcel();
590 mMap.put(key, value);
591 }
592
593 /**
594 * Inserts a String array value into the mapping of this Bundle, replacing
595 * any existing value for the given key. Either key or value may be null.
596 *
597 * @param key a String, or null
598 * @param value a String array object, or null
599 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800600 public void putStringArray(@Nullable String key, @Nullable String[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700601 unparcel();
602 mMap.put(key, value);
603 }
604
605 /**
606 * Inserts a CharSequence array value into the mapping of this Bundle, replacing
607 * any existing value for the given key. Either key or value may be null.
608 *
609 * @param key a String, or null
610 * @param value a CharSequence array object, or null
611 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800612 void putCharSequenceArray(@Nullable String key, @Nullable CharSequence[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700613 unparcel();
614 mMap.put(key, value);
615 }
616
617 /**
Craig Mautner719e6b12014-04-04 20:29:41 -0700618 * Returns the value associated with the given key, or false if
619 * no mapping of the desired type exists for the given key.
620 *
621 * @param key a String
622 * @return a boolean value
623 */
Craig Mautner73bdf972014-12-09 18:10:20 -0800624 public boolean getBoolean(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700625 unparcel();
626 if (DEBUG) Log.d(TAG, "Getting boolean in "
627 + Integer.toHexString(System.identityHashCode(this)));
628 return getBoolean(key, false);
629 }
630
631 // Log a message if the value was non-null but not of the expected type
632 void typeWarning(String key, Object value, String className,
633 Object defaultValue, ClassCastException e) {
634 StringBuilder sb = new StringBuilder();
635 sb.append("Key ");
636 sb.append(key);
637 sb.append(" expected ");
638 sb.append(className);
639 sb.append(" but value was a ");
640 sb.append(value.getClass().getName());
641 sb.append(". The default value ");
642 sb.append(defaultValue);
643 sb.append(" was returned.");
644 Log.w(TAG, sb.toString());
645 Log.w(TAG, "Attempt to cast generated internal exception:", e);
646 }
647
648 void typeWarning(String key, Object value, String className,
649 ClassCastException e) {
650 typeWarning(key, value, className, "<null>", e);
651 }
652
653 /**
654 * Returns the value associated with the given key, or defaultValue if
655 * no mapping of the desired type exists for the given key.
656 *
657 * @param key a String
658 * @param defaultValue Value to return if key does not exist
659 * @return a boolean value
660 */
Craig Mautner73bdf972014-12-09 18:10:20 -0800661 public boolean getBoolean(String key, boolean defaultValue) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700662 unparcel();
663 Object o = mMap.get(key);
664 if (o == null) {
665 return defaultValue;
666 }
667 try {
668 return (Boolean) o;
669 } catch (ClassCastException e) {
670 typeWarning(key, o, "Boolean", defaultValue, e);
671 return defaultValue;
672 }
673 }
674
675 /**
676 * Returns the value associated with the given key, or (byte) 0 if
677 * no mapping of the desired type exists for the given key.
678 *
679 * @param key a String
680 * @return a byte value
681 */
682 byte getByte(String key) {
683 unparcel();
684 return getByte(key, (byte) 0);
685 }
686
687 /**
688 * Returns the value associated with the given key, or defaultValue if
689 * no mapping of the desired type exists for the given key.
690 *
691 * @param key a String
692 * @param defaultValue Value to return if key does not exist
693 * @return a byte value
694 */
695 Byte getByte(String key, byte defaultValue) {
696 unparcel();
697 Object o = mMap.get(key);
698 if (o == null) {
699 return defaultValue;
700 }
701 try {
702 return (Byte) o;
703 } catch (ClassCastException e) {
704 typeWarning(key, o, "Byte", defaultValue, e);
705 return defaultValue;
706 }
707 }
708
709 /**
710 * Returns the value associated with the given key, or (char) 0 if
711 * no mapping of the desired type exists for the given key.
712 *
713 * @param key a String
714 * @return a char value
715 */
716 char getChar(String key) {
717 unparcel();
718 return getChar(key, (char) 0);
719 }
720
721 /**
722 * Returns the value associated with the given key, or defaultValue if
723 * no mapping of the desired type exists for the given key.
724 *
725 * @param key a String
726 * @param defaultValue Value to return if key does not exist
727 * @return a char value
728 */
729 char getChar(String key, char defaultValue) {
730 unparcel();
731 Object o = mMap.get(key);
732 if (o == null) {
733 return defaultValue;
734 }
735 try {
736 return (Character) o;
737 } catch (ClassCastException e) {
738 typeWarning(key, o, "Character", defaultValue, e);
739 return defaultValue;
740 }
741 }
742
743 /**
744 * Returns the value associated with the given key, or (short) 0 if
745 * no mapping of the desired type exists for the given key.
746 *
747 * @param key a String
748 * @return a short value
749 */
750 short getShort(String key) {
751 unparcel();
752 return getShort(key, (short) 0);
753 }
754
755 /**
756 * Returns the value associated with the given key, or defaultValue if
757 * no mapping of the desired type exists for the given key.
758 *
759 * @param key a String
760 * @param defaultValue Value to return if key does not exist
761 * @return a short value
762 */
763 short getShort(String key, short defaultValue) {
764 unparcel();
765 Object o = mMap.get(key);
766 if (o == null) {
767 return defaultValue;
768 }
769 try {
770 return (Short) o;
771 } catch (ClassCastException e) {
772 typeWarning(key, o, "Short", defaultValue, e);
773 return defaultValue;
774 }
775 }
776
777 /**
778 * Returns the value associated with the given key, or 0 if
779 * no mapping of the desired type exists for the given key.
780 *
781 * @param key a String
782 * @return an int value
783 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700784 public int getInt(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700785 unparcel();
786 return getInt(key, 0);
787 }
788
789 /**
790 * Returns the value associated with the given key, or defaultValue if
791 * no mapping of the desired type exists for the given key.
792 *
793 * @param key a String
794 * @param defaultValue Value to return if key does not exist
795 * @return an int value
796 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700797 public int getInt(String key, int defaultValue) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700798 unparcel();
799 Object o = mMap.get(key);
800 if (o == null) {
801 return defaultValue;
802 }
803 try {
804 return (Integer) o;
805 } catch (ClassCastException e) {
806 typeWarning(key, o, "Integer", defaultValue, e);
807 return defaultValue;
808 }
809 }
810
811 /**
812 * Returns the value associated with the given key, or 0L if
813 * no mapping of the desired type exists for the given key.
814 *
815 * @param key a String
816 * @return a long value
817 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700818 public long getLong(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700819 unparcel();
820 return getLong(key, 0L);
821 }
822
823 /**
824 * Returns the value associated with the given key, or defaultValue if
825 * no mapping of the desired type exists for the given key.
826 *
827 * @param key a String
828 * @param defaultValue Value to return if key does not exist
829 * @return a long value
830 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700831 public long getLong(String key, long defaultValue) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700832 unparcel();
833 Object o = mMap.get(key);
834 if (o == null) {
835 return defaultValue;
836 }
837 try {
838 return (Long) o;
839 } catch (ClassCastException e) {
840 typeWarning(key, o, "Long", defaultValue, e);
841 return defaultValue;
842 }
843 }
844
845 /**
846 * Returns the value associated with the given key, or 0.0f if
847 * no mapping of the desired type exists for the given key.
848 *
849 * @param key a String
850 * @return a float value
851 */
852 float getFloat(String key) {
853 unparcel();
854 return getFloat(key, 0.0f);
855 }
856
857 /**
858 * Returns the value associated with the given key, or defaultValue if
859 * no mapping of the desired type exists for the given key.
860 *
861 * @param key a String
862 * @param defaultValue Value to return if key does not exist
863 * @return a float value
864 */
865 float getFloat(String key, float defaultValue) {
866 unparcel();
867 Object o = mMap.get(key);
868 if (o == null) {
869 return defaultValue;
870 }
871 try {
872 return (Float) o;
873 } catch (ClassCastException e) {
874 typeWarning(key, o, "Float", defaultValue, e);
875 return defaultValue;
876 }
877 }
878
879 /**
880 * Returns the value associated with the given key, or 0.0 if
881 * no mapping of the desired type exists for the given key.
882 *
883 * @param key a String
884 * @return a double value
885 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700886 public double getDouble(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700887 unparcel();
888 return getDouble(key, 0.0);
889 }
890
891 /**
892 * Returns the value associated with the given key, or defaultValue if
893 * no mapping of the desired type exists for the given key.
894 *
895 * @param key a String
896 * @param defaultValue Value to return if key does not exist
897 * @return a double value
898 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700899 public double getDouble(String key, double defaultValue) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700900 unparcel();
901 Object o = mMap.get(key);
902 if (o == null) {
903 return defaultValue;
904 }
905 try {
906 return (Double) o;
907 } catch (ClassCastException e) {
908 typeWarning(key, o, "Double", defaultValue, e);
909 return defaultValue;
910 }
911 }
912
913 /**
914 * Returns the value associated with the given key, or null if
915 * no mapping of the desired type exists for the given key or a null
916 * value is explicitly associated with the key.
917 *
918 * @param key a String, or null
919 * @return a String value, or null
920 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800921 @Nullable
922 public String getString(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700923 unparcel();
924 final Object o = mMap.get(key);
925 try {
926 return (String) o;
927 } catch (ClassCastException e) {
928 typeWarning(key, o, "String", e);
929 return null;
930 }
931 }
932
933 /**
934 * Returns the value associated with the given key, or defaultValue if
Narayan Kamathaeaf87f2014-06-26 18:10:51 +0100935 * no mapping of the desired type exists for the given key or if a null
936 * value is explicitly associated with the given key.
Craig Mautner719e6b12014-04-04 20:29:41 -0700937 *
938 * @param key a String, or null
Narayan Kamathaeaf87f2014-06-26 18:10:51 +0100939 * @param defaultValue Value to return if key does not exist or if a null
940 * value is associated with the given key.
Craig Mautner719e6b12014-04-04 20:29:41 -0700941 * @return the String value associated with the given key, or defaultValue
942 * if no valid String object is currently mapped to that key.
943 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800944 public String getString(@Nullable String key, String defaultValue) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700945 final String s = getString(key);
946 return (s == null) ? defaultValue : s;
947 }
948
949 /**
950 * Returns the value associated with the given key, or null if
951 * no mapping of the desired type exists for the given key or a null
952 * value is explicitly associated with the key.
953 *
954 * @param key a String, or null
955 * @return a CharSequence value, or null
956 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800957 @Nullable
958 CharSequence getCharSequence(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700959 unparcel();
960 final Object o = mMap.get(key);
961 try {
962 return (CharSequence) o;
963 } catch (ClassCastException e) {
964 typeWarning(key, o, "CharSequence", e);
965 return null;
966 }
967 }
968
969 /**
970 * Returns the value associated with the given key, or defaultValue if
Narayan Kamathaeaf87f2014-06-26 18:10:51 +0100971 * no mapping of the desired type exists for the given key or if a null
972 * value is explicitly associated with the given key.
Craig Mautner719e6b12014-04-04 20:29:41 -0700973 *
974 * @param key a String, or null
Narayan Kamathaeaf87f2014-06-26 18:10:51 +0100975 * @param defaultValue Value to return if key does not exist or if a null
976 * value is associated with the given key.
Craig Mautner719e6b12014-04-04 20:29:41 -0700977 * @return the CharSequence value associated with the given key, or defaultValue
978 * if no valid CharSequence object is currently mapped to that key.
979 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800980 CharSequence getCharSequence(@Nullable String key, CharSequence defaultValue) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700981 final CharSequence cs = getCharSequence(key);
982 return (cs == null) ? defaultValue : cs;
983 }
984
985 /**
986 * Returns the value associated with the given key, or null if
987 * no mapping of the desired type exists for the given key or a null
988 * value is explicitly associated with the key.
989 *
990 * @param key a String, or null
Craig Mautner719e6b12014-04-04 20:29:41 -0700991 * @return a Serializable value, or null
992 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800993 @Nullable
994 Serializable getSerializable(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700995 unparcel();
996 Object o = mMap.get(key);
997 if (o == null) {
998 return null;
999 }
1000 try {
1001 return (Serializable) o;
1002 } catch (ClassCastException e) {
1003 typeWarning(key, o, "Serializable", e);
1004 return null;
1005 }
1006 }
1007
1008 /**
1009 * Returns the value associated with the given key, or null if
1010 * no mapping of the desired type exists for the given key or a null
1011 * value is explicitly associated with the key.
1012 *
1013 * @param key a String, or null
1014 * @return an ArrayList<String> value, or null
1015 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001016 @Nullable
1017 ArrayList<Integer> getIntegerArrayList(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001018 unparcel();
1019 Object o = mMap.get(key);
1020 if (o == null) {
1021 return null;
1022 }
1023 try {
1024 return (ArrayList<Integer>) o;
1025 } catch (ClassCastException e) {
1026 typeWarning(key, o, "ArrayList<Integer>", e);
1027 return null;
1028 }
1029 }
1030
1031 /**
1032 * Returns the value associated with the given key, or null if
1033 * no mapping of the desired type exists for the given key or a null
1034 * value is explicitly associated with the key.
1035 *
1036 * @param key a String, or null
1037 * @return an ArrayList<String> value, or null
1038 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001039 @Nullable
1040 ArrayList<String> getStringArrayList(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001041 unparcel();
1042 Object o = mMap.get(key);
1043 if (o == null) {
1044 return null;
1045 }
1046 try {
1047 return (ArrayList<String>) o;
1048 } catch (ClassCastException e) {
1049 typeWarning(key, o, "ArrayList<String>", e);
1050 return null;
1051 }
1052 }
1053
1054 /**
1055 * Returns the value associated with the given key, or null if
1056 * no mapping of the desired type exists for the given key or a null
1057 * value is explicitly associated with the key.
1058 *
1059 * @param key a String, or null
1060 * @return an ArrayList<CharSequence> value, or null
1061 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001062 @Nullable
1063 ArrayList<CharSequence> getCharSequenceArrayList(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001064 unparcel();
1065 Object o = mMap.get(key);
1066 if (o == null) {
1067 return null;
1068 }
1069 try {
1070 return (ArrayList<CharSequence>) o;
1071 } catch (ClassCastException e) {
1072 typeWarning(key, o, "ArrayList<CharSequence>", e);
1073 return null;
1074 }
1075 }
1076
1077 /**
1078 * Returns the value associated with the given key, or null if
1079 * no mapping of the desired type exists for the given key or a null
1080 * value is explicitly associated with the key.
1081 *
1082 * @param key a String, or null
1083 * @return a boolean[] value, or null
1084 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001085 @Nullable
1086 public boolean[] getBooleanArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001087 unparcel();
1088 Object o = mMap.get(key);
1089 if (o == null) {
1090 return null;
1091 }
1092 try {
1093 return (boolean[]) o;
1094 } catch (ClassCastException e) {
1095 typeWarning(key, o, "byte[]", e);
1096 return null;
1097 }
1098 }
1099
1100 /**
1101 * Returns the value associated with the given key, or null if
1102 * no mapping of the desired type exists for the given key or a null
1103 * value is explicitly associated with the key.
1104 *
1105 * @param key a String, or null
1106 * @return a byte[] value, or null
1107 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001108 @Nullable
1109 byte[] getByteArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001110 unparcel();
1111 Object o = mMap.get(key);
1112 if (o == null) {
1113 return null;
1114 }
1115 try {
1116 return (byte[]) o;
1117 } catch (ClassCastException e) {
1118 typeWarning(key, o, "byte[]", e);
1119 return null;
1120 }
1121 }
1122
1123 /**
1124 * Returns the value associated with the given key, or null if
1125 * no mapping of the desired type exists for the given key or a null
1126 * value is explicitly associated with the key.
1127 *
1128 * @param key a String, or null
1129 * @return a short[] value, or null
1130 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001131 @Nullable
1132 short[] getShortArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001133 unparcel();
1134 Object o = mMap.get(key);
1135 if (o == null) {
1136 return null;
1137 }
1138 try {
1139 return (short[]) o;
1140 } catch (ClassCastException e) {
1141 typeWarning(key, o, "short[]", e);
1142 return null;
1143 }
1144 }
1145
1146 /**
1147 * Returns the value associated with the given key, or null if
1148 * no mapping of the desired type exists for the given key or a null
1149 * value is explicitly associated with the key.
1150 *
1151 * @param key a String, or null
1152 * @return a char[] value, or null
1153 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001154 @Nullable
1155 char[] getCharArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001156 unparcel();
1157 Object o = mMap.get(key);
1158 if (o == null) {
1159 return null;
1160 }
1161 try {
1162 return (char[]) o;
1163 } catch (ClassCastException e) {
1164 typeWarning(key, o, "char[]", e);
1165 return null;
1166 }
1167 }
1168
1169 /**
1170 * Returns the value associated with the given key, or null if
1171 * no mapping of the desired type exists for the given key or a null
1172 * value is explicitly associated with the key.
1173 *
1174 * @param key a String, or null
1175 * @return an int[] value, or null
1176 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001177 @Nullable
1178 public int[] getIntArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001179 unparcel();
1180 Object o = mMap.get(key);
1181 if (o == null) {
1182 return null;
1183 }
1184 try {
1185 return (int[]) o;
1186 } catch (ClassCastException e) {
1187 typeWarning(key, o, "int[]", e);
1188 return null;
1189 }
1190 }
1191
1192 /**
1193 * Returns the value associated with the given key, or null if
1194 * no mapping of the desired type exists for the given key or a null
1195 * value is explicitly associated with the key.
1196 *
1197 * @param key a String, or null
1198 * @return a long[] value, or null
1199 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001200 @Nullable
1201 public long[] getLongArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001202 unparcel();
1203 Object o = mMap.get(key);
1204 if (o == null) {
1205 return null;
1206 }
1207 try {
1208 return (long[]) o;
1209 } catch (ClassCastException e) {
1210 typeWarning(key, o, "long[]", e);
1211 return null;
1212 }
1213 }
1214
1215 /**
1216 * Returns the value associated with the given key, or null if
1217 * no mapping of the desired type exists for the given key or a null
1218 * value is explicitly associated with the key.
1219 *
1220 * @param key a String, or null
1221 * @return a float[] value, or null
1222 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001223 @Nullable
1224 float[] getFloatArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001225 unparcel();
1226 Object o = mMap.get(key);
1227 if (o == null) {
1228 return null;
1229 }
1230 try {
1231 return (float[]) o;
1232 } catch (ClassCastException e) {
1233 typeWarning(key, o, "float[]", e);
1234 return null;
1235 }
1236 }
1237
1238 /**
1239 * Returns the value associated with the given key, or null if
1240 * no mapping of the desired type exists for the given key or a null
1241 * value is explicitly associated with the key.
1242 *
1243 * @param key a String, or null
1244 * @return a double[] value, or null
1245 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001246 @Nullable
1247 public double[] getDoubleArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001248 unparcel();
1249 Object o = mMap.get(key);
1250 if (o == null) {
1251 return null;
1252 }
1253 try {
1254 return (double[]) o;
1255 } catch (ClassCastException e) {
1256 typeWarning(key, o, "double[]", e);
1257 return null;
1258 }
1259 }
1260
1261 /**
1262 * Returns the value associated with the given key, or null if
1263 * no mapping of the desired type exists for the given key or a null
1264 * value is explicitly associated with the key.
1265 *
1266 * @param key a String, or null
1267 * @return a String[] value, or null
1268 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001269 @Nullable
1270 public String[] getStringArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001271 unparcel();
1272 Object o = mMap.get(key);
1273 if (o == null) {
1274 return null;
1275 }
1276 try {
1277 return (String[]) o;
1278 } catch (ClassCastException e) {
1279 typeWarning(key, o, "String[]", e);
1280 return null;
1281 }
1282 }
1283
1284 /**
1285 * Returns the value associated with the given key, or null if
1286 * no mapping of the desired type exists for the given key or a null
1287 * value is explicitly associated with the key.
1288 *
1289 * @param key a String, or null
1290 * @return a CharSequence[] value, or null
1291 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001292 @Nullable
1293 CharSequence[] getCharSequenceArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001294 unparcel();
1295 Object o = mMap.get(key);
1296 if (o == null) {
1297 return null;
1298 }
1299 try {
1300 return (CharSequence[]) o;
1301 } catch (ClassCastException e) {
1302 typeWarning(key, o, "CharSequence[]", e);
1303 return null;
1304 }
1305 }
1306
1307 /**
1308 * Writes the Bundle contents to a Parcel, typically in order for
1309 * it to be passed through an IBinder connection.
1310 * @param parcel The parcel to copy this bundle to.
1311 */
1312 void writeToParcelInner(Parcel parcel, int flags) {
Samuel Tan3cefe6a2015-12-14 13:29:17 -08001313 // Keep implementation in sync with writeToParcel() in
1314 // frameworks/native/libs/binder/PersistableBundle.cpp.
Craig Mautner719e6b12014-04-04 20:29:41 -07001315 if (mParcelledData != null) {
1316 if (mParcelledData == EMPTY_PARCEL) {
1317 parcel.writeInt(0);
1318 } else {
1319 int length = mParcelledData.dataSize();
1320 parcel.writeInt(length);
1321 parcel.writeInt(BUNDLE_MAGIC);
1322 parcel.appendFrom(mParcelledData, 0, length);
1323 }
1324 } else {
1325 // Special case for empty bundles.
1326 if (mMap == null || mMap.size() <= 0) {
1327 parcel.writeInt(0);
1328 return;
1329 }
1330 int lengthPos = parcel.dataPosition();
1331 parcel.writeInt(-1); // dummy, will hold length
1332 parcel.writeInt(BUNDLE_MAGIC);
1333
1334 int startPos = parcel.dataPosition();
1335 parcel.writeArrayMapInternal(mMap);
1336 int endPos = parcel.dataPosition();
1337
1338 // Backpatch length
1339 parcel.setDataPosition(lengthPos);
1340 int length = endPos - startPos;
1341 parcel.writeInt(length);
1342 parcel.setDataPosition(endPos);
1343 }
1344 }
1345
1346 /**
1347 * Reads the Parcel contents into this Bundle, typically in order for
1348 * it to be passed through an IBinder connection.
1349 * @param parcel The parcel to overwrite this bundle from.
1350 */
1351 void readFromParcelInner(Parcel parcel) {
Samuel Tan3cefe6a2015-12-14 13:29:17 -08001352 // Keep implementation in sync with readFromParcel() in
1353 // frameworks/native/libs/binder/PersistableBundle.cpp.
Craig Mautner719e6b12014-04-04 20:29:41 -07001354 int length = parcel.readInt();
Craig Mautner719e6b12014-04-04 20:29:41 -07001355 readFromParcelInner(parcel, length);
1356 }
1357
1358 private void readFromParcelInner(Parcel parcel, int length) {
Adam Lesinski1619ed42015-09-22 13:02:09 -07001359 if (length < 0) {
1360 throw new RuntimeException("Bad length in parcel: " + length);
1361
1362 } else if (length == 0) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001363 // Empty Bundle or end of data.
1364 mParcelledData = EMPTY_PARCEL;
1365 return;
1366 }
Adam Lesinski1619ed42015-09-22 13:02:09 -07001367
Craig Mautner719e6b12014-04-04 20:29:41 -07001368 int magic = parcel.readInt();
1369 if (magic != BUNDLE_MAGIC) {
1370 //noinspection ThrowableInstanceNeverThrown
1371 throw new IllegalStateException("Bad magic number for Bundle: 0x"
1372 + Integer.toHexString(magic));
1373 }
1374
1375 // Advance within this Parcel
1376 int offset = parcel.dataPosition();
Adam Lesinski1619ed42015-09-22 13:02:09 -07001377 parcel.setDataPosition(MathUtils.addOrThrow(offset, length));
Craig Mautner719e6b12014-04-04 20:29:41 -07001378
1379 Parcel p = Parcel.obtain();
1380 p.setDataPosition(0);
1381 p.appendFrom(parcel, offset, length);
1382 if (DEBUG) Log.d(TAG, "Retrieving " + Integer.toHexString(System.identityHashCode(this))
1383 + ": " + length + " bundle bytes starting at " + offset);
1384 p.setDataPosition(0);
1385
1386 mParcelledData = p;
1387 }
1388}