blob: 5c7137341cd39499aa387d7fdfed6a7066298483 [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
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800238 /** @hide */
239 ArrayMap<String, Object> getMap() {
240 unparcel();
241 return mMap;
242 }
243
Craig Mautner719e6b12014-04-04 20:29:41 -0700244 /**
245 * Returns the number of mappings contained in this Bundle.
246 *
247 * @return the number of mappings as an int.
248 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700249 public int size() {
Craig Mautner719e6b12014-04-04 20:29:41 -0700250 unparcel();
251 return mMap.size();
252 }
253
254 /**
255 * Returns true if the mapping of this Bundle is empty, false otherwise.
256 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700257 public boolean isEmpty() {
Craig Mautner719e6b12014-04-04 20:29:41 -0700258 unparcel();
259 return mMap.isEmpty();
260 }
261
262 /**
263 * Removes all elements from the mapping of this Bundle.
264 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700265 public void clear() {
Craig Mautner719e6b12014-04-04 20:29:41 -0700266 unparcel();
267 mMap.clear();
268 }
269
270 /**
271 * Returns true if the given key is contained in the mapping
272 * of this Bundle.
273 *
274 * @param key a String key
275 * @return true if the key is part of the mapping, false otherwise
276 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700277 public boolean containsKey(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700278 unparcel();
279 return mMap.containsKey(key);
280 }
281
282 /**
283 * Returns the entry with the given key as an object.
284 *
285 * @param key a String key
286 * @return an Object, or null
287 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800288 @Nullable
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700289 public Object get(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700290 unparcel();
291 return mMap.get(key);
292 }
293
294 /**
295 * Removes any entry with the given key from the mapping of this Bundle.
296 *
297 * @param key a String key
298 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700299 public void remove(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700300 unparcel();
301 mMap.remove(key);
302 }
303
304 /**
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700305 * Inserts all mappings from the given PersistableBundle into this BaseBundle.
Craig Mautner719e6b12014-04-04 20:29:41 -0700306 *
307 * @param bundle a PersistableBundle
308 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700309 public void putAll(PersistableBundle bundle) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700310 unparcel();
311 bundle.unparcel();
312 mMap.putAll(bundle.mMap);
313 }
314
315 /**
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700316 * Inserts all mappings from the given Map into this BaseBundle.
Craig Mautner21d24a22014-04-23 11:45:37 -0700317 *
318 * @param map a Map
319 */
Dianne Hackborna83ce1d2015-03-11 15:16:13 -0700320 void putAll(ArrayMap map) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700321 unparcel();
322 mMap.putAll(map);
323 }
324
325 /**
Craig Mautner719e6b12014-04-04 20:29:41 -0700326 * Returns a Set containing the Strings used as keys in this Bundle.
327 *
328 * @return a Set of String keys
329 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700330 public Set<String> keySet() {
Craig Mautner719e6b12014-04-04 20:29:41 -0700331 unparcel();
332 return mMap.keySet();
333 }
334
335 /**
336 * Inserts a Boolean value into the mapping of this Bundle, replacing
337 * any existing value for the given key. Either key or value may be null.
338 *
339 * @param key a String, or null
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800340 * @param value a boolean
Craig Mautner719e6b12014-04-04 20:29:41 -0700341 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800342 public void putBoolean(@Nullable String key, boolean value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700343 unparcel();
344 mMap.put(key, value);
345 }
346
347 /**
348 * Inserts a byte value into the mapping of this Bundle, replacing
349 * any existing value for the given key.
350 *
351 * @param key a String, or null
352 * @param value a byte
353 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800354 void putByte(@Nullable String key, byte value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700355 unparcel();
356 mMap.put(key, value);
357 }
358
359 /**
360 * Inserts a char value into the mapping of this Bundle, replacing
361 * any existing value for the given key.
362 *
363 * @param key a String, or null
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800364 * @param value a char
Craig Mautner719e6b12014-04-04 20:29:41 -0700365 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800366 void putChar(@Nullable String key, char value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700367 unparcel();
368 mMap.put(key, value);
369 }
370
371 /**
372 * Inserts a short value into the mapping of this Bundle, replacing
373 * any existing value for the given key.
374 *
375 * @param key a String, or null
376 * @param value a short
377 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800378 void putShort(@Nullable String key, short value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700379 unparcel();
380 mMap.put(key, value);
381 }
382
383 /**
384 * Inserts an int value into the mapping of this Bundle, replacing
385 * any existing value for the given key.
386 *
387 * @param key a String, or null
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800388 * @param value an int
Craig Mautner719e6b12014-04-04 20:29:41 -0700389 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800390 public void putInt(@Nullable String key, int value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700391 unparcel();
392 mMap.put(key, value);
393 }
394
395 /**
396 * Inserts a long value into the mapping of this Bundle, replacing
397 * any existing value for the given key.
398 *
399 * @param key a String, or null
400 * @param value a long
401 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800402 public void putLong(@Nullable String key, long value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700403 unparcel();
404 mMap.put(key, value);
405 }
406
407 /**
408 * Inserts a float value into the mapping of this Bundle, replacing
409 * any existing value for the given key.
410 *
411 * @param key a String, or null
412 * @param value a float
413 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800414 void putFloat(@Nullable String key, float value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700415 unparcel();
416 mMap.put(key, value);
417 }
418
419 /**
420 * Inserts a double value into the mapping of this Bundle, replacing
421 * any existing value for the given key.
422 *
423 * @param key a String, or null
424 * @param value a double
425 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800426 public void putDouble(@Nullable String key, double value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700427 unparcel();
428 mMap.put(key, value);
429 }
430
431 /**
432 * Inserts a String value into the mapping of this Bundle, replacing
433 * any existing value for the given key. Either key or value may be null.
434 *
435 * @param key a String, or null
436 * @param value a String, or null
437 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800438 public void putString(@Nullable String key, @Nullable String value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700439 unparcel();
440 mMap.put(key, value);
441 }
442
443 /**
444 * Inserts a CharSequence value into the mapping of this Bundle, replacing
445 * any existing value for the given key. Either key or value may be null.
446 *
447 * @param key a String, or null
448 * @param value a CharSequence, or null
449 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800450 void putCharSequence(@Nullable String key, @Nullable CharSequence value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700451 unparcel();
452 mMap.put(key, value);
453 }
454
455 /**
456 * Inserts an ArrayList<Integer> value into the mapping of this Bundle, replacing
457 * any existing value for the given key. Either key or value may be null.
458 *
459 * @param key a String, or null
460 * @param value an ArrayList<Integer> object, or null
461 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800462 void putIntegerArrayList(@Nullable String key, @Nullable ArrayList<Integer> value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700463 unparcel();
464 mMap.put(key, value);
465 }
466
467 /**
468 * Inserts an ArrayList<String> value into the mapping of this Bundle, replacing
469 * any existing value for the given key. Either key or value may be null.
470 *
471 * @param key a String, or null
472 * @param value an ArrayList<String> object, or null
473 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800474 void putStringArrayList(@Nullable String key, @Nullable ArrayList<String> value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700475 unparcel();
476 mMap.put(key, value);
477 }
478
479 /**
480 * Inserts an ArrayList<CharSequence> value into the mapping of this Bundle, replacing
481 * any existing value for the given key. Either key or value may be null.
482 *
483 * @param key a String, or null
484 * @param value an ArrayList<CharSequence> object, or null
485 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800486 void putCharSequenceArrayList(@Nullable String key, @Nullable ArrayList<CharSequence> value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700487 unparcel();
488 mMap.put(key, value);
489 }
490
491 /**
492 * Inserts a Serializable value into the mapping of this Bundle, replacing
493 * any existing value for the given key. Either key or value may be null.
494 *
495 * @param key a String, or null
496 * @param value a Serializable object, or null
497 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800498 void putSerializable(@Nullable String key, @Nullable Serializable value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700499 unparcel();
500 mMap.put(key, value);
501 }
502
503 /**
504 * Inserts a boolean array value into the mapping of this Bundle, replacing
505 * any existing value for the given key. Either key or value may be null.
506 *
507 * @param key a String, or null
508 * @param value a boolean array object, or null
509 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800510 public void putBooleanArray(@Nullable String key, @Nullable boolean[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700511 unparcel();
512 mMap.put(key, value);
513 }
514
515 /**
516 * Inserts a byte array value into the mapping of this Bundle, replacing
517 * any existing value for the given key. Either key or value may be null.
518 *
519 * @param key a String, or null
520 * @param value a byte array object, or null
521 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800522 void putByteArray(@Nullable String key, @Nullable byte[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700523 unparcel();
524 mMap.put(key, value);
525 }
526
527 /**
528 * Inserts a short array value into the mapping of this Bundle, replacing
529 * any existing value for the given key. Either key or value may be null.
530 *
531 * @param key a String, or null
532 * @param value a short array object, or null
533 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800534 void putShortArray(@Nullable String key, @Nullable short[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700535 unparcel();
536 mMap.put(key, value);
537 }
538
539 /**
540 * Inserts a char array value into the mapping of this Bundle, replacing
541 * any existing value for the given key. Either key or value may be null.
542 *
543 * @param key a String, or null
544 * @param value a char array object, or null
545 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800546 void putCharArray(@Nullable String key, @Nullable char[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700547 unparcel();
548 mMap.put(key, value);
549 }
550
551 /**
552 * Inserts an int array value into the mapping of this Bundle, replacing
553 * any existing value for the given key. Either key or value may be null.
554 *
555 * @param key a String, or null
556 * @param value an int array object, or null
557 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800558 public void putIntArray(@Nullable String key, @Nullable int[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700559 unparcel();
560 mMap.put(key, value);
561 }
562
563 /**
564 * Inserts a long array value into the mapping of this Bundle, replacing
565 * any existing value for the given key. Either key or value may be null.
566 *
567 * @param key a String, or null
568 * @param value a long array object, or null
569 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800570 public void putLongArray(@Nullable String key, @Nullable long[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700571 unparcel();
572 mMap.put(key, value);
573 }
574
575 /**
576 * Inserts a float array value into the mapping of this Bundle, replacing
577 * any existing value for the given key. Either key or value may be null.
578 *
579 * @param key a String, or null
580 * @param value a float array object, or null
581 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800582 void putFloatArray(@Nullable String key, @Nullable float[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700583 unparcel();
584 mMap.put(key, value);
585 }
586
587 /**
588 * Inserts a double array value into the mapping of this Bundle, replacing
589 * any existing value for the given key. Either key or value may be null.
590 *
591 * @param key a String, or null
592 * @param value a double array object, or null
593 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800594 public void putDoubleArray(@Nullable String key, @Nullable double[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700595 unparcel();
596 mMap.put(key, value);
597 }
598
599 /**
600 * Inserts a String array value into the mapping of this Bundle, replacing
601 * any existing value for the given key. Either key or value may be null.
602 *
603 * @param key a String, or null
604 * @param value a String array object, or null
605 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800606 public void putStringArray(@Nullable String key, @Nullable String[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700607 unparcel();
608 mMap.put(key, value);
609 }
610
611 /**
612 * Inserts a CharSequence array value into the mapping of this Bundle, replacing
613 * any existing value for the given key. Either key or value may be null.
614 *
615 * @param key a String, or null
616 * @param value a CharSequence array object, or null
617 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800618 void putCharSequenceArray(@Nullable String key, @Nullable CharSequence[] value) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700619 unparcel();
620 mMap.put(key, value);
621 }
622
623 /**
Craig Mautner719e6b12014-04-04 20:29:41 -0700624 * Returns the value associated with the given key, or false if
625 * no mapping of the desired type exists for the given key.
626 *
627 * @param key a String
628 * @return a boolean value
629 */
Craig Mautner73bdf972014-12-09 18:10:20 -0800630 public boolean getBoolean(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700631 unparcel();
632 if (DEBUG) Log.d(TAG, "Getting boolean in "
633 + Integer.toHexString(System.identityHashCode(this)));
634 return getBoolean(key, false);
635 }
636
637 // Log a message if the value was non-null but not of the expected type
638 void typeWarning(String key, Object value, String className,
639 Object defaultValue, ClassCastException e) {
640 StringBuilder sb = new StringBuilder();
641 sb.append("Key ");
642 sb.append(key);
643 sb.append(" expected ");
644 sb.append(className);
645 sb.append(" but value was a ");
646 sb.append(value.getClass().getName());
647 sb.append(". The default value ");
648 sb.append(defaultValue);
649 sb.append(" was returned.");
650 Log.w(TAG, sb.toString());
651 Log.w(TAG, "Attempt to cast generated internal exception:", e);
652 }
653
654 void typeWarning(String key, Object value, String className,
655 ClassCastException e) {
656 typeWarning(key, value, className, "<null>", e);
657 }
658
659 /**
660 * Returns the value associated with the given key, or defaultValue if
661 * no mapping of the desired type exists for the given key.
662 *
663 * @param key a String
664 * @param defaultValue Value to return if key does not exist
665 * @return a boolean value
666 */
Craig Mautner73bdf972014-12-09 18:10:20 -0800667 public boolean getBoolean(String key, boolean defaultValue) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700668 unparcel();
669 Object o = mMap.get(key);
670 if (o == null) {
671 return defaultValue;
672 }
673 try {
674 return (Boolean) o;
675 } catch (ClassCastException e) {
676 typeWarning(key, o, "Boolean", defaultValue, e);
677 return defaultValue;
678 }
679 }
680
681 /**
682 * Returns the value associated with the given key, or (byte) 0 if
683 * no mapping of the desired type exists for the given key.
684 *
685 * @param key a String
686 * @return a byte value
687 */
688 byte getByte(String key) {
689 unparcel();
690 return getByte(key, (byte) 0);
691 }
692
693 /**
694 * Returns the value associated with the given key, or defaultValue if
695 * no mapping of the desired type exists for the given key.
696 *
697 * @param key a String
698 * @param defaultValue Value to return if key does not exist
699 * @return a byte value
700 */
701 Byte getByte(String key, byte defaultValue) {
702 unparcel();
703 Object o = mMap.get(key);
704 if (o == null) {
705 return defaultValue;
706 }
707 try {
708 return (Byte) o;
709 } catch (ClassCastException e) {
710 typeWarning(key, o, "Byte", defaultValue, e);
711 return defaultValue;
712 }
713 }
714
715 /**
716 * Returns the value associated with the given key, or (char) 0 if
717 * no mapping of the desired type exists for the given key.
718 *
719 * @param key a String
720 * @return a char value
721 */
722 char getChar(String key) {
723 unparcel();
724 return getChar(key, (char) 0);
725 }
726
727 /**
728 * Returns the value associated with the given key, or defaultValue if
729 * no mapping of the desired type exists for the given key.
730 *
731 * @param key a String
732 * @param defaultValue Value to return if key does not exist
733 * @return a char value
734 */
735 char getChar(String key, char defaultValue) {
736 unparcel();
737 Object o = mMap.get(key);
738 if (o == null) {
739 return defaultValue;
740 }
741 try {
742 return (Character) o;
743 } catch (ClassCastException e) {
744 typeWarning(key, o, "Character", defaultValue, e);
745 return defaultValue;
746 }
747 }
748
749 /**
750 * Returns the value associated with the given key, or (short) 0 if
751 * no mapping of the desired type exists for the given key.
752 *
753 * @param key a String
754 * @return a short value
755 */
756 short getShort(String key) {
757 unparcel();
758 return getShort(key, (short) 0);
759 }
760
761 /**
762 * Returns the value associated with the given key, or defaultValue if
763 * no mapping of the desired type exists for the given key.
764 *
765 * @param key a String
766 * @param defaultValue Value to return if key does not exist
767 * @return a short value
768 */
769 short getShort(String key, short defaultValue) {
770 unparcel();
771 Object o = mMap.get(key);
772 if (o == null) {
773 return defaultValue;
774 }
775 try {
776 return (Short) o;
777 } catch (ClassCastException e) {
778 typeWarning(key, o, "Short", defaultValue, e);
779 return defaultValue;
780 }
781 }
782
783 /**
784 * Returns the value associated with the given key, or 0 if
785 * no mapping of the desired type exists for the given key.
786 *
787 * @param key a String
788 * @return an int value
789 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700790 public int getInt(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700791 unparcel();
792 return getInt(key, 0);
793 }
794
795 /**
796 * Returns the value associated with the given key, or defaultValue if
797 * no mapping of the desired type exists for the given key.
798 *
799 * @param key a String
800 * @param defaultValue Value to return if key does not exist
801 * @return an int value
802 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700803 public int getInt(String key, int defaultValue) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700804 unparcel();
805 Object o = mMap.get(key);
806 if (o == null) {
807 return defaultValue;
808 }
809 try {
810 return (Integer) o;
811 } catch (ClassCastException e) {
812 typeWarning(key, o, "Integer", defaultValue, e);
813 return defaultValue;
814 }
815 }
816
817 /**
818 * Returns the value associated with the given key, or 0L if
819 * no mapping of the desired type exists for the given key.
820 *
821 * @param key a String
822 * @return a long value
823 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700824 public long getLong(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700825 unparcel();
826 return getLong(key, 0L);
827 }
828
829 /**
830 * Returns the value associated with the given key, or defaultValue if
831 * no mapping of the desired type exists for the given key.
832 *
833 * @param key a String
834 * @param defaultValue Value to return if key does not exist
835 * @return a long value
836 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700837 public long getLong(String key, long defaultValue) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700838 unparcel();
839 Object o = mMap.get(key);
840 if (o == null) {
841 return defaultValue;
842 }
843 try {
844 return (Long) o;
845 } catch (ClassCastException e) {
846 typeWarning(key, o, "Long", defaultValue, e);
847 return defaultValue;
848 }
849 }
850
851 /**
852 * Returns the value associated with the given key, or 0.0f if
853 * no mapping of the desired type exists for the given key.
854 *
855 * @param key a String
856 * @return a float value
857 */
858 float getFloat(String key) {
859 unparcel();
860 return getFloat(key, 0.0f);
861 }
862
863 /**
864 * Returns the value associated with the given key, or defaultValue if
865 * no mapping of the desired type exists for the given key.
866 *
867 * @param key a String
868 * @param defaultValue Value to return if key does not exist
869 * @return a float value
870 */
871 float getFloat(String key, float defaultValue) {
872 unparcel();
873 Object o = mMap.get(key);
874 if (o == null) {
875 return defaultValue;
876 }
877 try {
878 return (Float) o;
879 } catch (ClassCastException e) {
880 typeWarning(key, o, "Float", defaultValue, e);
881 return defaultValue;
882 }
883 }
884
885 /**
886 * Returns the value associated with the given key, or 0.0 if
887 * no mapping of the desired type exists for the given key.
888 *
889 * @param key a String
890 * @return a double value
891 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700892 public double getDouble(String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700893 unparcel();
894 return getDouble(key, 0.0);
895 }
896
897 /**
898 * Returns the value associated with the given key, or defaultValue if
899 * no mapping of the desired type exists for the given key.
900 *
901 * @param key a String
902 * @param defaultValue Value to return if key does not exist
903 * @return a double value
904 */
Craig Mautner0a8e160e2014-05-29 10:27:32 -0700905 public double getDouble(String key, double defaultValue) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700906 unparcel();
907 Object o = mMap.get(key);
908 if (o == null) {
909 return defaultValue;
910 }
911 try {
912 return (Double) o;
913 } catch (ClassCastException e) {
914 typeWarning(key, o, "Double", defaultValue, e);
915 return defaultValue;
916 }
917 }
918
919 /**
920 * Returns the value associated with the given key, or null if
921 * no mapping of the desired type exists for the given key or a null
922 * value is explicitly associated with the key.
923 *
924 * @param key a String, or null
925 * @return a String value, or null
926 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800927 @Nullable
928 public String getString(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700929 unparcel();
930 final Object o = mMap.get(key);
931 try {
932 return (String) o;
933 } catch (ClassCastException e) {
934 typeWarning(key, o, "String", e);
935 return null;
936 }
937 }
938
939 /**
940 * Returns the value associated with the given key, or defaultValue if
Narayan Kamathaeaf87f2014-06-26 18:10:51 +0100941 * no mapping of the desired type exists for the given key or if a null
942 * value is explicitly associated with the given key.
Craig Mautner719e6b12014-04-04 20:29:41 -0700943 *
944 * @param key a String, or null
Narayan Kamathaeaf87f2014-06-26 18:10:51 +0100945 * @param defaultValue Value to return if key does not exist or if a null
946 * value is associated with the given key.
Craig Mautner719e6b12014-04-04 20:29:41 -0700947 * @return the String value associated with the given key, or defaultValue
948 * if no valid String object is currently mapped to that key.
949 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800950 public String getString(@Nullable String key, String defaultValue) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700951 final String s = getString(key);
952 return (s == null) ? defaultValue : s;
953 }
954
955 /**
956 * Returns the value associated with the given key, or null if
957 * no mapping of the desired type exists for the given key or a null
958 * value is explicitly associated with the key.
959 *
960 * @param key a String, or null
961 * @return a CharSequence value, or null
962 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800963 @Nullable
964 CharSequence getCharSequence(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700965 unparcel();
966 final Object o = mMap.get(key);
967 try {
968 return (CharSequence) o;
969 } catch (ClassCastException e) {
970 typeWarning(key, o, "CharSequence", e);
971 return null;
972 }
973 }
974
975 /**
976 * Returns the value associated with the given key, or defaultValue if
Narayan Kamathaeaf87f2014-06-26 18:10:51 +0100977 * no mapping of the desired type exists for the given key or if a null
978 * value is explicitly associated with the given key.
Craig Mautner719e6b12014-04-04 20:29:41 -0700979 *
980 * @param key a String, or null
Narayan Kamathaeaf87f2014-06-26 18:10:51 +0100981 * @param defaultValue Value to return if key does not exist or if a null
982 * value is associated with the given key.
Craig Mautner719e6b12014-04-04 20:29:41 -0700983 * @return the CharSequence value associated with the given key, or defaultValue
984 * if no valid CharSequence object is currently mapped to that key.
985 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800986 CharSequence getCharSequence(@Nullable String key, CharSequence defaultValue) {
Craig Mautner719e6b12014-04-04 20:29:41 -0700987 final CharSequence cs = getCharSequence(key);
988 return (cs == null) ? defaultValue : cs;
989 }
990
991 /**
992 * Returns the value associated with the given key, or null if
993 * no mapping of the desired type exists for the given key or a null
994 * value is explicitly associated with the key.
995 *
996 * @param key a String, or null
Craig Mautner719e6b12014-04-04 20:29:41 -0700997 * @return a Serializable value, or null
998 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -0800999 @Nullable
1000 Serializable getSerializable(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001001 unparcel();
1002 Object o = mMap.get(key);
1003 if (o == null) {
1004 return null;
1005 }
1006 try {
1007 return (Serializable) o;
1008 } catch (ClassCastException e) {
1009 typeWarning(key, o, "Serializable", e);
1010 return null;
1011 }
1012 }
1013
1014 /**
1015 * Returns the value associated with the given key, or null if
1016 * no mapping of the desired type exists for the given key or a null
1017 * value is explicitly associated with the key.
1018 *
1019 * @param key a String, or null
1020 * @return an ArrayList<String> value, or null
1021 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001022 @Nullable
1023 ArrayList<Integer> getIntegerArrayList(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001024 unparcel();
1025 Object o = mMap.get(key);
1026 if (o == null) {
1027 return null;
1028 }
1029 try {
1030 return (ArrayList<Integer>) o;
1031 } catch (ClassCastException e) {
1032 typeWarning(key, o, "ArrayList<Integer>", e);
1033 return null;
1034 }
1035 }
1036
1037 /**
1038 * Returns the value associated with the given key, or null if
1039 * no mapping of the desired type exists for the given key or a null
1040 * value is explicitly associated with the key.
1041 *
1042 * @param key a String, or null
1043 * @return an ArrayList<String> value, or null
1044 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001045 @Nullable
1046 ArrayList<String> getStringArrayList(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001047 unparcel();
1048 Object o = mMap.get(key);
1049 if (o == null) {
1050 return null;
1051 }
1052 try {
1053 return (ArrayList<String>) o;
1054 } catch (ClassCastException e) {
1055 typeWarning(key, o, "ArrayList<String>", e);
1056 return null;
1057 }
1058 }
1059
1060 /**
1061 * Returns the value associated with the given key, or null if
1062 * no mapping of the desired type exists for the given key or a null
1063 * value is explicitly associated with the key.
1064 *
1065 * @param key a String, or null
1066 * @return an ArrayList<CharSequence> value, or null
1067 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001068 @Nullable
1069 ArrayList<CharSequence> getCharSequenceArrayList(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001070 unparcel();
1071 Object o = mMap.get(key);
1072 if (o == null) {
1073 return null;
1074 }
1075 try {
1076 return (ArrayList<CharSequence>) o;
1077 } catch (ClassCastException e) {
1078 typeWarning(key, o, "ArrayList<CharSequence>", e);
1079 return null;
1080 }
1081 }
1082
1083 /**
1084 * Returns the value associated with the given key, or null if
1085 * no mapping of the desired type exists for the given key or a null
1086 * value is explicitly associated with the key.
1087 *
1088 * @param key a String, or null
1089 * @return a boolean[] value, or null
1090 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001091 @Nullable
1092 public boolean[] getBooleanArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001093 unparcel();
1094 Object o = mMap.get(key);
1095 if (o == null) {
1096 return null;
1097 }
1098 try {
1099 return (boolean[]) o;
1100 } catch (ClassCastException e) {
1101 typeWarning(key, o, "byte[]", e);
1102 return null;
1103 }
1104 }
1105
1106 /**
1107 * Returns the value associated with the given key, or null if
1108 * no mapping of the desired type exists for the given key or a null
1109 * value is explicitly associated with the key.
1110 *
1111 * @param key a String, or null
1112 * @return a byte[] value, or null
1113 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001114 @Nullable
1115 byte[] getByteArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001116 unparcel();
1117 Object o = mMap.get(key);
1118 if (o == null) {
1119 return null;
1120 }
1121 try {
1122 return (byte[]) o;
1123 } catch (ClassCastException e) {
1124 typeWarning(key, o, "byte[]", e);
1125 return null;
1126 }
1127 }
1128
1129 /**
1130 * Returns the value associated with the given key, or null if
1131 * no mapping of the desired type exists for the given key or a null
1132 * value is explicitly associated with the key.
1133 *
1134 * @param key a String, or null
1135 * @return a short[] value, or null
1136 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001137 @Nullable
1138 short[] getShortArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001139 unparcel();
1140 Object o = mMap.get(key);
1141 if (o == null) {
1142 return null;
1143 }
1144 try {
1145 return (short[]) o;
1146 } catch (ClassCastException e) {
1147 typeWarning(key, o, "short[]", e);
1148 return null;
1149 }
1150 }
1151
1152 /**
1153 * Returns the value associated with the given key, or null if
1154 * no mapping of the desired type exists for the given key or a null
1155 * value is explicitly associated with the key.
1156 *
1157 * @param key a String, or null
1158 * @return a char[] value, or null
1159 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001160 @Nullable
1161 char[] getCharArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001162 unparcel();
1163 Object o = mMap.get(key);
1164 if (o == null) {
1165 return null;
1166 }
1167 try {
1168 return (char[]) o;
1169 } catch (ClassCastException e) {
1170 typeWarning(key, o, "char[]", e);
1171 return null;
1172 }
1173 }
1174
1175 /**
1176 * Returns the value associated with the given key, or null if
1177 * no mapping of the desired type exists for the given key or a null
1178 * value is explicitly associated with the key.
1179 *
1180 * @param key a String, or null
1181 * @return an int[] value, or null
1182 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001183 @Nullable
1184 public int[] getIntArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001185 unparcel();
1186 Object o = mMap.get(key);
1187 if (o == null) {
1188 return null;
1189 }
1190 try {
1191 return (int[]) o;
1192 } catch (ClassCastException e) {
1193 typeWarning(key, o, "int[]", e);
1194 return null;
1195 }
1196 }
1197
1198 /**
1199 * Returns the value associated with the given key, or null if
1200 * no mapping of the desired type exists for the given key or a null
1201 * value is explicitly associated with the key.
1202 *
1203 * @param key a String, or null
1204 * @return a long[] value, or null
1205 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001206 @Nullable
1207 public long[] getLongArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001208 unparcel();
1209 Object o = mMap.get(key);
1210 if (o == null) {
1211 return null;
1212 }
1213 try {
1214 return (long[]) o;
1215 } catch (ClassCastException e) {
1216 typeWarning(key, o, "long[]", e);
1217 return null;
1218 }
1219 }
1220
1221 /**
1222 * Returns the value associated with the given key, or null if
1223 * no mapping of the desired type exists for the given key or a null
1224 * value is explicitly associated with the key.
1225 *
1226 * @param key a String, or null
1227 * @return a float[] value, or null
1228 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001229 @Nullable
1230 float[] getFloatArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001231 unparcel();
1232 Object o = mMap.get(key);
1233 if (o == null) {
1234 return null;
1235 }
1236 try {
1237 return (float[]) o;
1238 } catch (ClassCastException e) {
1239 typeWarning(key, o, "float[]", e);
1240 return null;
1241 }
1242 }
1243
1244 /**
1245 * Returns the value associated with the given key, or null if
1246 * no mapping of the desired type exists for the given key or a null
1247 * value is explicitly associated with the key.
1248 *
1249 * @param key a String, or null
1250 * @return a double[] value, or null
1251 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001252 @Nullable
1253 public double[] getDoubleArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001254 unparcel();
1255 Object o = mMap.get(key);
1256 if (o == null) {
1257 return null;
1258 }
1259 try {
1260 return (double[]) o;
1261 } catch (ClassCastException e) {
1262 typeWarning(key, o, "double[]", e);
1263 return null;
1264 }
1265 }
1266
1267 /**
1268 * Returns the value associated with the given key, or null if
1269 * no mapping of the desired type exists for the given key or a null
1270 * value is explicitly associated with the key.
1271 *
1272 * @param key a String, or null
1273 * @return a String[] value, or null
1274 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001275 @Nullable
1276 public String[] getStringArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001277 unparcel();
1278 Object o = mMap.get(key);
1279 if (o == null) {
1280 return null;
1281 }
1282 try {
1283 return (String[]) o;
1284 } catch (ClassCastException e) {
1285 typeWarning(key, o, "String[]", e);
1286 return null;
1287 }
1288 }
1289
1290 /**
1291 * Returns the value associated with the given key, or null if
1292 * no mapping of the desired type exists for the given key or a null
1293 * value is explicitly associated with the key.
1294 *
1295 * @param key a String, or null
1296 * @return a CharSequence[] value, or null
1297 */
Scott Kennedyc6a65dff2015-03-01 17:10:10 -08001298 @Nullable
1299 CharSequence[] getCharSequenceArray(@Nullable String key) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001300 unparcel();
1301 Object o = mMap.get(key);
1302 if (o == null) {
1303 return null;
1304 }
1305 try {
1306 return (CharSequence[]) o;
1307 } catch (ClassCastException e) {
1308 typeWarning(key, o, "CharSequence[]", e);
1309 return null;
1310 }
1311 }
1312
1313 /**
1314 * Writes the Bundle contents to a Parcel, typically in order for
1315 * it to be passed through an IBinder connection.
1316 * @param parcel The parcel to copy this bundle to.
1317 */
1318 void writeToParcelInner(Parcel parcel, int flags) {
Samuel Tan3cefe6a2015-12-14 13:29:17 -08001319 // Keep implementation in sync with writeToParcel() in
1320 // frameworks/native/libs/binder/PersistableBundle.cpp.
Craig Mautner719e6b12014-04-04 20:29:41 -07001321 if (mParcelledData != null) {
1322 if (mParcelledData == EMPTY_PARCEL) {
1323 parcel.writeInt(0);
1324 } else {
1325 int length = mParcelledData.dataSize();
1326 parcel.writeInt(length);
1327 parcel.writeInt(BUNDLE_MAGIC);
1328 parcel.appendFrom(mParcelledData, 0, length);
1329 }
1330 } else {
1331 // Special case for empty bundles.
1332 if (mMap == null || mMap.size() <= 0) {
1333 parcel.writeInt(0);
1334 return;
1335 }
1336 int lengthPos = parcel.dataPosition();
1337 parcel.writeInt(-1); // dummy, will hold length
1338 parcel.writeInt(BUNDLE_MAGIC);
1339
1340 int startPos = parcel.dataPosition();
1341 parcel.writeArrayMapInternal(mMap);
1342 int endPos = parcel.dataPosition();
1343
1344 // Backpatch length
1345 parcel.setDataPosition(lengthPos);
1346 int length = endPos - startPos;
1347 parcel.writeInt(length);
1348 parcel.setDataPosition(endPos);
1349 }
1350 }
1351
1352 /**
1353 * Reads the Parcel contents into this Bundle, typically in order for
1354 * it to be passed through an IBinder connection.
1355 * @param parcel The parcel to overwrite this bundle from.
1356 */
1357 void readFromParcelInner(Parcel parcel) {
Samuel Tan3cefe6a2015-12-14 13:29:17 -08001358 // Keep implementation in sync with readFromParcel() in
1359 // frameworks/native/libs/binder/PersistableBundle.cpp.
Craig Mautner719e6b12014-04-04 20:29:41 -07001360 int length = parcel.readInt();
Craig Mautner719e6b12014-04-04 20:29:41 -07001361 readFromParcelInner(parcel, length);
1362 }
1363
1364 private void readFromParcelInner(Parcel parcel, int length) {
Adam Lesinski1619ed42015-09-22 13:02:09 -07001365 if (length < 0) {
1366 throw new RuntimeException("Bad length in parcel: " + length);
1367
1368 } else if (length == 0) {
Craig Mautner719e6b12014-04-04 20:29:41 -07001369 // Empty Bundle or end of data.
1370 mParcelledData = EMPTY_PARCEL;
1371 return;
1372 }
Adam Lesinski1619ed42015-09-22 13:02:09 -07001373
Craig Mautner719e6b12014-04-04 20:29:41 -07001374 int magic = parcel.readInt();
1375 if (magic != BUNDLE_MAGIC) {
1376 //noinspection ThrowableInstanceNeverThrown
1377 throw new IllegalStateException("Bad magic number for Bundle: 0x"
1378 + Integer.toHexString(magic));
1379 }
1380
1381 // Advance within this Parcel
1382 int offset = parcel.dataPosition();
Adam Lesinski1619ed42015-09-22 13:02:09 -07001383 parcel.setDataPosition(MathUtils.addOrThrow(offset, length));
Craig Mautner719e6b12014-04-04 20:29:41 -07001384
1385 Parcel p = Parcel.obtain();
1386 p.setDataPosition(0);
1387 p.appendFrom(parcel, offset, length);
1388 if (DEBUG) Log.d(TAG, "Retrieving " + Integer.toHexString(System.identityHashCode(this))
1389 + ": " + length + " bundle bytes starting at " + offset);
1390 p.setDataPosition(0);
1391
1392 mParcelledData = p;
1393 }
1394}