• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
4 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
5 import static android.os.Build.VERSION_CODES.KITKAT_WATCH;
6 import static android.os.Build.VERSION_CODES.LOLLIPOP;
7 import static android.os.Build.VERSION_CODES.M;
8 import static android.os.Build.VERSION_CODES.O_MR1;
9 import static android.os.Build.VERSION_CODES.P;
10 import static org.robolectric.RuntimeEnvironment.castNativePtr;
11 
12 import android.os.BadParcelableException;
13 import android.os.IBinder;
14 import android.os.Parcel;
15 import android.os.ParcelFileDescriptor;
16 import android.os.Parcelable;
17 import android.text.TextUtils;
18 import android.util.Log;
19 import android.util.Pair;
20 import java.io.ByteArrayInputStream;
21 import java.io.ByteArrayOutputStream;
22 import java.io.FileDescriptor;
23 import java.io.IOException;
24 import java.io.ObjectInputStream;
25 import java.io.ObjectOutputStream;
26 import java.io.RandomAccessFile;
27 import java.lang.reflect.Field;
28 import java.lang.reflect.Modifier;
29 import java.util.ArrayList;
30 import java.util.LinkedHashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Objects;
34 import org.robolectric.annotation.HiddenApi;
35 import org.robolectric.annotation.Implementation;
36 import org.robolectric.annotation.Implements;
37 import org.robolectric.annotation.RealObject;
38 import org.robolectric.util.ReflectionHelpers;
39 
40 @Implements(Parcel.class)
41 @SuppressWarnings("unchecked")
42 public class ShadowParcel {
43   private static final String TAG = "Parcel";
44 
45   @RealObject private Parcel realObject;
46   private static final Map<Long, ByteBuffer> NATIVE_PTR_TO_PARCEL = new LinkedHashMap<>();
47   private static long nextNativePtr = 1; // this needs to start above 0, which is a magic number to Parcel
48 
49   @Implementation(maxSdk = JELLY_BEAN_MR1)
50   @SuppressWarnings("TypeParameterUnusedInFormals")
readParcelable(ClassLoader loader)51   protected <T extends Parcelable> T readParcelable(ClassLoader loader) {
52     // prior to JB MR2, readParcelableCreator() is inlined here.
53     Parcelable.Creator<?> creator = readParcelableCreator(loader);
54     if (creator == null) {
55       return null;
56     }
57 
58     if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
59       Parcelable.ClassLoaderCreator<?> classLoaderCreator =
60           (Parcelable.ClassLoaderCreator<?>) creator;
61       return (T) classLoaderCreator.createFromParcel(realObject, loader);
62     }
63     return (T) creator.createFromParcel(realObject);
64   }
65 
66   @HiddenApi
67   @Implementation(minSdk = JELLY_BEAN_MR2)
readParcelableCreator(ClassLoader loader)68   public Parcelable.Creator<?> readParcelableCreator(ClassLoader loader) {
69     //note: calling `readString` will also consume the string, and increment the data-pointer.
70     //which is exactly what we need, since we do not call the real `readParcelableCreator`.
71     final String name = realObject.readString();
72     if (name == null) {
73       return null;
74     }
75 
76     Parcelable.Creator<?> creator;
77     try {
78       // If loader == null, explicitly emulate Class.forName(String) "caller
79       // classloader" behavior.
80       ClassLoader parcelableClassLoader =
81           (loader == null ? getClass().getClassLoader() : loader);
82       // Avoid initializing the Parcelable class until we know it implements
83       // Parcelable and has the necessary CREATOR field. http://b/1171613.
84       Class<?> parcelableClass = Class.forName(name, false /* initialize */,
85           parcelableClassLoader);
86       if (!Parcelable.class.isAssignableFrom(parcelableClass)) {
87         throw new BadParcelableException("Parcelable protocol requires that the "
88             + "class implements Parcelable");
89       }
90       Field f = parcelableClass.getField("CREATOR");
91 
92       // this is a fix for JDK8<->Android VM incompatibility:
93       // Apparently, JDK will not allow access to a public field if its
94       // class is not visible (private or package-private) from the call-site.
95       f.setAccessible(true);
96 
97       if ((f.getModifiers() & Modifier.STATIC) == 0) {
98         throw new BadParcelableException("Parcelable protocol requires "
99             + "the CREATOR object to be static on class " + name);
100       }
101       Class<?> creatorType = f.getType();
102       if (!Parcelable.Creator.class.isAssignableFrom(creatorType)) {
103         // Fail before calling Field.get(), not after, to avoid initializing
104         // parcelableClass unnecessarily.
105         throw new BadParcelableException("Parcelable protocol requires a "
106             + "Parcelable.Creator object called "
107             + "CREATOR on class " + name);
108       }
109       creator = (Parcelable.Creator<?>) f.get(null);
110     } catch (IllegalAccessException e) {
111       Log.e(TAG, "Illegal access when unmarshalling: " + name, e);
112       throw new BadParcelableException(
113           "IllegalAccessException when unmarshalling: " + name);
114     } catch (ClassNotFoundException e) {
115       Log.e(TAG, "Class not found when unmarshalling: " + name, e);
116       throw new BadParcelableException(
117           "ClassNotFoundException when unmarshalling: " + name);
118     } catch (NoSuchFieldException e) {
119       throw new BadParcelableException("Parcelable protocol requires a "
120           + "Parcelable.Creator object called "
121           + "CREATOR on class " + name);
122     }
123     if (creator == null) {
124       throw new BadParcelableException("Parcelable protocol requires a "
125           + "non-null Parcelable.Creator object called "
126           + "CREATOR on class " + name);
127     }
128     return creator;
129   }
130 
131   @Implementation
writeByteArray(byte[] b, int offset, int len)132   protected void writeByteArray(byte[] b, int offset, int len) {
133     if (b == null) {
134       realObject.writeInt(-1);
135       return;
136     }
137     Number nativePtr = ReflectionHelpers.getField(realObject, "mNativePtr");
138     nativeWriteByteArray(nativePtr.longValue(), b, offset, len);
139   }
140 
141   @HiddenApi
142   @Implementation(maxSdk = KITKAT_WATCH)
nativeDataSize(int nativePtr)143   public static int nativeDataSize(int nativePtr) {
144     return nativeDataSize((long) nativePtr);
145   }
146 
147   @Implementation(minSdk = LOLLIPOP)
nativeDataSize(long nativePtr)148   protected static int nativeDataSize(long nativePtr) {
149     return NATIVE_PTR_TO_PARCEL.get(nativePtr).dataSize();
150   }
151 
152   @HiddenApi
153   @Implementation(maxSdk = KITKAT_WATCH)
nativeDataAvail(int nativePtr)154   public static int nativeDataAvail(int nativePtr) {
155     return nativeDataAvail((long) nativePtr);
156   }
157 
158   @Implementation(minSdk = LOLLIPOP)
nativeDataAvail(long nativePtr)159   protected static int nativeDataAvail(long nativePtr) {
160     return NATIVE_PTR_TO_PARCEL.get(nativePtr).dataAvailable();
161   }
162 
163   @HiddenApi
164   @Implementation(maxSdk = KITKAT_WATCH)
nativeDataPosition(int nativePtr)165   public static int nativeDataPosition(int nativePtr) {
166     return nativeDataPosition((long) nativePtr);
167   }
168 
169   @Implementation(minSdk = LOLLIPOP)
nativeDataPosition(long nativePtr)170   protected static int nativeDataPosition(long nativePtr) {
171     return NATIVE_PTR_TO_PARCEL.get(nativePtr).dataPosition();
172   }
173 
174   @HiddenApi
175   @Implementation(maxSdk = KITKAT_WATCH)
nativeDataCapacity(int nativePtr)176   public static int nativeDataCapacity(int nativePtr) {
177     return nativeDataCapacity((long) nativePtr);
178   }
179 
180   @Implementation(minSdk = LOLLIPOP)
nativeDataCapacity(long nativePtr)181   protected static int nativeDataCapacity(long nativePtr) {
182     return NATIVE_PTR_TO_PARCEL.get(nativePtr).dataCapacity();
183   }
184 
185   @HiddenApi
186   @Implementation(maxSdk = KITKAT_WATCH)
nativeSetDataSize(int nativePtr, int size)187   public static void nativeSetDataSize(int nativePtr, int size) {
188     nativeSetDataSize((long) nativePtr, size);
189   }
190 
191   @Implementation(minSdk = LOLLIPOP)
192   @SuppressWarnings("robolectric.ShadowReturnTypeMismatch")
nativeSetDataSize(long nativePtr, int size)193   protected static void nativeSetDataSize(long nativePtr, int size) {
194     NATIVE_PTR_TO_PARCEL.get(nativePtr).setDataSize(size);
195   }
196 
197   @HiddenApi
198   @Implementation(maxSdk = KITKAT_WATCH)
nativeSetDataPosition(int nativePtr, int pos)199   public static void nativeSetDataPosition(int nativePtr, int pos) {
200     nativeSetDataPosition((long) nativePtr, pos);
201   }
202 
203   @Implementation(minSdk = LOLLIPOP)
nativeSetDataPosition(long nativePtr, int pos)204   protected static void nativeSetDataPosition(long nativePtr, int pos) {
205     NATIVE_PTR_TO_PARCEL.get(nativePtr).setDataPosition(pos);
206   }
207 
208   @HiddenApi
209   @Implementation(maxSdk = KITKAT_WATCH)
nativeSetDataCapacity(int nativePtr, int size)210   public static void nativeSetDataCapacity(int nativePtr, int size) {
211     nativeSetDataCapacity((long) nativePtr, size);
212   }
213 
214   @Implementation(minSdk = LOLLIPOP)
nativeSetDataCapacity(long nativePtr, int size)215   protected static void nativeSetDataCapacity(long nativePtr, int size) {
216     NATIVE_PTR_TO_PARCEL.get(nativePtr).setDataCapacity(size);
217   }
218 
219   @HiddenApi
220   @Implementation(maxSdk = KITKAT_WATCH)
nativeWriteByteArray(int nativePtr, byte[] b, int offset, int len)221   public static void nativeWriteByteArray(int nativePtr, byte[] b, int offset, int len) {
222     nativeWriteByteArray((long) nativePtr, b, offset, len);
223   }
224 
225   @Implementation(minSdk = LOLLIPOP)
nativeWriteByteArray(long nativePtr, byte[] b, int offset, int len)226   protected static void nativeWriteByteArray(long nativePtr, byte[] b, int offset, int len) {
227     NATIVE_PTR_TO_PARCEL.get(nativePtr).writeByteArray(b, offset, len);
228   }
229 
230   // duplicate the writeBlob implementation from latest android, to avoid referencing the
231   // non-existent-in-JDK java.util.Arrays.checkOffsetAndCount method.
232   @Implementation(minSdk = M)
writeBlob(byte[] b, int offset, int len)233   protected void writeBlob(byte[] b, int offset, int len) {
234     if (b == null) {
235       realObject.writeInt(-1);
236       return;
237     }
238     throwsIfOutOfBounds(b.length, offset, len);
239     long nativePtr = ReflectionHelpers.getField(realObject, "mNativePtr");
240     nativeWriteBlob(nativePtr, b, offset, len);
241   }
242 
throwsIfOutOfBounds(int len, int offset, int count)243   private static void throwsIfOutOfBounds(int len, int offset, int count) {
244     if (len < 0) {
245       throw new ArrayIndexOutOfBoundsException("Negative length: " + len);
246     }
247 
248     if ((offset | count) < 0 || offset > len - count) {
249       throw new ArrayIndexOutOfBoundsException();
250     }
251   }
252 
253   // nativeWriteBlob was introduced in lollipop, thus no need for a int nativePtr variant
254   @Implementation(minSdk = LOLLIPOP)
nativeWriteBlob(long nativePtr, byte[] b, int offset, int len)255   protected static void nativeWriteBlob(long nativePtr, byte[] b, int offset, int len) {
256     nativeWriteByteArray(nativePtr, b, offset, len);
257   }
258 
259   @HiddenApi
260   @Implementation(maxSdk = KITKAT_WATCH)
nativeWriteInt(int nativePtr, int val)261   public static void nativeWriteInt(int nativePtr, int val) {
262     nativeWriteInt((long) nativePtr, val);
263   }
264 
265   @Implementation(minSdk = LOLLIPOP)
nativeWriteInt(long nativePtr, int val)266   protected static void nativeWriteInt(long nativePtr, int val) {
267     NATIVE_PTR_TO_PARCEL.get(nativePtr).writeInt(val);
268   }
269 
270   @HiddenApi
271   @Implementation(maxSdk = KITKAT_WATCH)
nativeWriteLong(int nativePtr, long val)272   public static void nativeWriteLong(int nativePtr, long val) {
273     nativeWriteLong((long) nativePtr, val);
274   }
275 
276   @Implementation(minSdk = LOLLIPOP)
nativeWriteLong(long nativePtr, long val)277   protected static void nativeWriteLong(long nativePtr, long val) {
278     NATIVE_PTR_TO_PARCEL.get(nativePtr).writeLong(val);
279   }
280 
281   @HiddenApi
282   @Implementation(maxSdk = KITKAT_WATCH)
nativeWriteFloat(int nativePtr, float val)283   public static void nativeWriteFloat(int nativePtr, float val) {
284     nativeWriteFloat((long) nativePtr, val);
285   }
286 
287   @Implementation(minSdk = LOLLIPOP)
nativeWriteFloat(long nativePtr, float val)288   protected static void nativeWriteFloat(long nativePtr, float val) {
289     NATIVE_PTR_TO_PARCEL.get(nativePtr).writeFloat(val);
290   }
291 
292   @HiddenApi
293   @Implementation(maxSdk = KITKAT_WATCH)
nativeWriteDouble(int nativePtr, double val)294   public static void nativeWriteDouble(int nativePtr, double val) {
295     nativeWriteDouble((long) nativePtr, val);
296   }
297 
298   @Implementation(minSdk = LOLLIPOP)
nativeWriteDouble(long nativePtr, double val)299   protected static void nativeWriteDouble(long nativePtr, double val) {
300     NATIVE_PTR_TO_PARCEL.get(nativePtr).writeDouble(val);
301   }
302 
303   @HiddenApi
304   @Implementation(maxSdk = KITKAT_WATCH)
nativeWriteString(int nativePtr, String val)305   public static void nativeWriteString(int nativePtr, String val) {
306     nativeWriteString((long) nativePtr, val);
307   }
308 
309   @Implementation(minSdk = LOLLIPOP)
nativeWriteString(long nativePtr, String val)310   protected static void nativeWriteString(long nativePtr, String val) {
311     NATIVE_PTR_TO_PARCEL.get(nativePtr).writeString(val);
312   }
313 
314   @HiddenApi
315   @Implementation(maxSdk = KITKAT_WATCH)
nativeWriteStrongBinder(int nativePtr, IBinder val)316   protected static void nativeWriteStrongBinder(int nativePtr, IBinder val) {
317     nativeWriteStrongBinder((long) nativePtr, val);
318   }
319 
320   @Implementation(minSdk = LOLLIPOP)
nativeWriteStrongBinder(long nativePtr, IBinder val)321   protected static void nativeWriteStrongBinder(long nativePtr, IBinder val) {
322     NATIVE_PTR_TO_PARCEL.get(nativePtr).writeStrongBinder(val);
323   }
324 
325   @HiddenApi
326   @Implementation(maxSdk = KITKAT_WATCH)
nativeCreateByteArray(int nativePtr)327   public static byte[] nativeCreateByteArray(int nativePtr) {
328     return nativeCreateByteArray((long) nativePtr);
329   }
330 
331   @Implementation(minSdk = LOLLIPOP)
nativeCreateByteArray(long nativePtr)332   protected static byte[] nativeCreateByteArray(long nativePtr) {
333     return NATIVE_PTR_TO_PARCEL.get(nativePtr).readByteArray();
334   }
335 
336   // nativeReadBlob was introduced in lollipop, thus no need for a int nativePtr variant
337   @Implementation(minSdk = LOLLIPOP)
nativeReadBlob(long nativePtr)338   protected static byte[] nativeReadBlob(long nativePtr) {
339     return nativeCreateByteArray(nativePtr);
340   }
341 
342   @Implementation(minSdk = O_MR1)
nativeReadByteArray(long nativePtr, byte[] dest, int destLen)343   protected static boolean nativeReadByteArray(long nativePtr, byte[] dest, int destLen) {
344     return NATIVE_PTR_TO_PARCEL.get(nativePtr).readByteArray(dest, destLen);
345   }
346 
347   @HiddenApi
348   @Implementation(maxSdk = KITKAT_WATCH)
nativeReadInt(int nativePtr)349   public static int nativeReadInt(int nativePtr) {
350     return nativeReadInt((long) nativePtr);
351   }
352 
353   @Implementation(minSdk = LOLLIPOP)
nativeReadInt(long nativePtr)354   protected static int nativeReadInt(long nativePtr) {
355     return NATIVE_PTR_TO_PARCEL.get(nativePtr).readInt();
356   }
357 
358   @HiddenApi
359   @Implementation(maxSdk = KITKAT_WATCH)
nativeReadLong(int nativePtr)360   public static long nativeReadLong(int nativePtr) {
361     return nativeReadLong((long) nativePtr);
362   }
363 
364   @Implementation(minSdk = LOLLIPOP)
nativeReadLong(long nativePtr)365   protected static long nativeReadLong(long nativePtr) {
366     return NATIVE_PTR_TO_PARCEL.get(nativePtr).readLong();
367   }
368 
369   @HiddenApi
370   @Implementation(maxSdk = KITKAT_WATCH)
nativeReadFloat(int nativePtr)371   public static float nativeReadFloat(int nativePtr) {
372     return nativeReadFloat((long) nativePtr);
373   }
374 
375   @Implementation(minSdk = LOLLIPOP)
nativeReadFloat(long nativePtr)376   protected static float nativeReadFloat(long nativePtr) {
377     return NATIVE_PTR_TO_PARCEL.get(nativePtr).readFloat();
378   }
379 
380   @HiddenApi
381   @Implementation(maxSdk = KITKAT_WATCH)
nativeReadDouble(int nativePtr)382   public static double nativeReadDouble(int nativePtr) {
383     return nativeReadDouble((long) nativePtr);
384   }
385 
386   @Implementation(minSdk = LOLLIPOP)
nativeReadDouble(long nativePtr)387   protected static double nativeReadDouble(long nativePtr) {
388     return NATIVE_PTR_TO_PARCEL.get(nativePtr).readDouble();
389   }
390 
391   @HiddenApi
392   @Implementation(maxSdk = KITKAT_WATCH)
nativeReadString(int nativePtr)393   public static String nativeReadString(int nativePtr) {
394     return nativeReadString((long) nativePtr);
395   }
396 
397   @Implementation(minSdk = LOLLIPOP)
nativeReadString(long nativePtr)398   protected static String nativeReadString(long nativePtr) {
399     return NATIVE_PTR_TO_PARCEL.get(nativePtr).readString();
400   }
401 
402   @HiddenApi
403   @Implementation(maxSdk = KITKAT_WATCH)
nativeReadStrongBinder(int nativePtr)404   protected static IBinder nativeReadStrongBinder(int nativePtr) {
405     return nativeReadStrongBinder((long) nativePtr);
406   }
407 
408   @Implementation(minSdk = LOLLIPOP)
nativeReadStrongBinder(long nativePtr)409   protected static IBinder nativeReadStrongBinder(long nativePtr) {
410     return NATIVE_PTR_TO_PARCEL.get(nativePtr).readStrongBinder();
411   }
412 
413   @Implementation @HiddenApi
nativeCreate()414   synchronized public static Number nativeCreate() {
415     long nativePtr = nextNativePtr++;
416     NATIVE_PTR_TO_PARCEL.put(nativePtr, new ByteBuffer());
417     return castNativePtr(nativePtr);
418   }
419 
420   @HiddenApi
421   @Implementation(maxSdk = KITKAT_WATCH)
nativeFreeBuffer(int nativePtr)422   public static void nativeFreeBuffer(int nativePtr) {
423     nativeFreeBuffer((long) nativePtr);
424   }
425 
426   @Implementation(minSdk = LOLLIPOP)
427   @SuppressWarnings("robolectric.ShadowReturnTypeMismatch")
nativeFreeBuffer(long nativePtr)428   protected static void nativeFreeBuffer(long nativePtr) {
429     NATIVE_PTR_TO_PARCEL.get(nativePtr).clear();
430   }
431 
432   @HiddenApi
433   @Implementation(maxSdk = KITKAT_WATCH)
nativeDestroy(int nativePtr)434   public static void nativeDestroy(int nativePtr) {
435     nativeDestroy((long) nativePtr);
436   }
437 
438   @Implementation(minSdk = LOLLIPOP)
nativeDestroy(long nativePtr)439   protected static void nativeDestroy(long nativePtr) {
440     NATIVE_PTR_TO_PARCEL.remove(nativePtr);
441   }
442 
443   @HiddenApi
444   @Implementation(maxSdk = KITKAT_WATCH)
nativeMarshall(int nativePtr)445   public static byte[] nativeMarshall(int nativePtr) {
446     return nativeMarshall((long) nativePtr);
447   }
448 
449   @Implementation(minSdk = LOLLIPOP)
nativeMarshall(long nativePtr)450   protected static byte[] nativeMarshall(long nativePtr) {
451     return NATIVE_PTR_TO_PARCEL.get(nativePtr).toByteArray();
452   }
453 
454   @HiddenApi
455   @Implementation(maxSdk = KITKAT_WATCH)
nativeUnmarshall(int nativePtr, byte[] data, int offset, int length)456   public static void nativeUnmarshall(int nativePtr, byte[] data, int offset, int length) {
457     nativeUnmarshall((long) nativePtr, data, offset, length);
458   }
459 
460   @Implementation(minSdk = LOLLIPOP)
461   @SuppressWarnings("robolectric.ShadowReturnTypeMismatch")
nativeUnmarshall(long nativePtr, byte[] data, int offset, int length)462   protected static void nativeUnmarshall(long nativePtr, byte[] data, int offset, int length) {
463     NATIVE_PTR_TO_PARCEL.put(nativePtr, ByteBuffer.fromByteArray(data, offset, length));
464   }
465 
466   @HiddenApi
467   @Implementation(maxSdk = KITKAT_WATCH)
nativeAppendFrom(int thisNativePtr, int otherNativePtr, int offset, int length)468   public static void nativeAppendFrom(int thisNativePtr, int otherNativePtr, int offset, int length) {
469     nativeAppendFrom((long) thisNativePtr, otherNativePtr, offset, length);
470   }
471 
472   @Implementation(minSdk = LOLLIPOP)
473   @SuppressWarnings("robolectric.ShadowReturnTypeMismatch")
nativeAppendFrom( long thisNativePtr, long otherNativePtr, int offset, int length)474   protected static void nativeAppendFrom(
475       long thisNativePtr, long otherNativePtr, int offset, int length) {
476     ByteBuffer thisByteBuffer = NATIVE_PTR_TO_PARCEL.get(thisNativePtr);
477     ByteBuffer otherByteBuffer = NATIVE_PTR_TO_PARCEL.get(otherNativePtr);
478     thisByteBuffer.appendFrom(otherByteBuffer, offset, length);
479   }
480 
481   @HiddenApi
482   @Implementation(maxSdk = KITKAT_WATCH)
nativeWriteInterfaceToken(int nativePtr, String interfaceName)483   public static void nativeWriteInterfaceToken(int nativePtr, String interfaceName) {
484     nativeWriteInterfaceToken((long) nativePtr, interfaceName);
485   }
486 
487   @Implementation(minSdk = LOLLIPOP)
nativeWriteInterfaceToken(long nativePtr, String interfaceName)488   protected static void nativeWriteInterfaceToken(long nativePtr, String interfaceName) {
489     // Write StrictMode.ThreadPolicy bits (assume 0 for test).
490     nativeWriteInt(nativePtr, 0);
491     nativeWriteString(nativePtr, interfaceName);
492   }
493 
494   @HiddenApi
495   @Implementation(maxSdk = KITKAT_WATCH)
nativeEnforceInterface(int nativePtr, String interfaceName)496   public static void nativeEnforceInterface(int nativePtr, String interfaceName) {
497     nativeEnforceInterface((long) nativePtr, interfaceName);
498   }
499 
500   @Implementation(minSdk = LOLLIPOP)
nativeEnforceInterface(long nativePtr, String interfaceName)501   protected static void nativeEnforceInterface(long nativePtr, String interfaceName) {
502     // Consume StrictMode.ThreadPolicy bits (don't bother setting in test).
503     nativeReadInt(nativePtr);
504     String actualInterfaceName = nativeReadString(nativePtr);
505     if (!Objects.equals(interfaceName, actualInterfaceName)) {
506       throw new SecurityException("Binder invocation to an incorrect interface");
507     }
508   }
509 
510   private static class ByteBuffer {
511 
512     // List of elements where a pair is a piece of data and the sizeof that data
513     private List<Pair<Integer, ?>> buffer = new ArrayList<>();
514     private int index;
515 
516     /**
517      * Removes all elements from the byte buffer
518      */
clear()519     public void clear() {
520       index = 0;
521       buffer.clear();
522     }
523 
524     /**
525      * Reads a byte array from the byte buffer based on the current data position
526      */
readByteArray()527     public byte[] readByteArray() {
528       int length = readInt();
529       if (length == -1) {
530         return null;
531       }
532       byte[] array = new byte[length];
533       for (int i = 0; i < length; i++) {
534         array[i] = readByte();
535       }
536       return array;
537     }
538 
539     /**
540      * Reads a byte array from the byte buffer based on the current data position
541      */
readByteArray(byte[] dest, int destLen)542     public boolean readByteArray(byte[] dest, int destLen) {
543       int length = readInt();
544       if (length >= 0 && length <= dataAvailable() && length == destLen) {
545         for (int i = 0; i < length; i++) {
546           dest[i] = readByte();
547         }
548         return true;
549       }
550       return false;
551     }
552 
553     /**
554      * Writes a byte to the byte buffer at the current data position
555      */
writeByte(byte b)556     public void writeByte(byte b) {
557       writeValue(Byte.SIZE / 8, b);
558     }
559 
560     /**
561      * Writes a byte array starting at offset for length bytes to the byte buffer at the current
562      * data position
563      */
writeByteArray(byte[] b, int offset, int length)564     public void writeByteArray(byte[] b, int offset, int length) {
565       writeInt(b.length);
566       for (int i = offset; i < offset + length && i < b.length; i++) {
567         writeByte(b[i]);
568       }
569     }
570 
571     /**
572      * Reads a byte from the byte buffer based on the current data position
573      */
readByte()574     public byte readByte() {
575       return readValue((byte) 0);
576     }
577 
578     /**
579      * Writes an int to the byte buffer at the current data position
580      */
writeInt(int i)581     public void writeInt(int i) {
582       writeValue(Integer.SIZE / 8, i);
583     }
584 
585     /**
586      * Reads a int from the byte buffer based on the current data position
587      */
readInt()588     public int readInt() {
589       return readValue(0);
590     }
591 
592     /**
593      * Writes a long to the byte buffer at the current data position
594      */
writeLong(long l)595     public void writeLong(long l) {
596       writeValue(Long.SIZE / 8, l);
597     }
598 
599     /**
600      * Reads a long from the byte buffer based on the current data position
601      */
readLong()602     public long readLong() {
603       return readValue(0L);
604     }
605 
606     /**
607      * Writes a float to the byte buffer at the current data position
608      */
writeFloat(float f)609     public void writeFloat(float f) {
610       writeValue(Float.SIZE / 8, f);
611     }
612 
613     /**
614      * Reads a float from the byte buffer based on the current data position
615      */
readFloat()616     public float readFloat() {
617       return readValue(0f);
618     }
619 
620     /**
621      * Writes a double to the byte buffer at the current data position
622      */
writeDouble(double d)623     public void writeDouble(double d) {
624       writeValue(Double.SIZE / 8, d);
625     }
626 
627     /**
628      * Reads a double from the byte buffer based on the current data position
629      */
readDouble()630     public double readDouble() {
631       return readValue(0d);
632     }
633 
634     /**
635      * Writes a String to the byte buffer at the current data position
636      */
writeString(String s)637     public void writeString(String s) {
638       int length = TextUtils.isEmpty(s) ? Integer.SIZE / 8 : s.length();
639       writeValue(length, s);
640     }
641 
642     /**
643      * Reads a String from the byte buffer based on the current data position
644      */
readString()645     public String readString() {
646       return readValue(null);
647     }
648 
649     /**
650      * Writes an IBinder to the byte buffer at the current data position
651      */
writeStrongBinder(IBinder b)652     public void writeStrongBinder(IBinder b) {
653       // Size of struct flat_binder_object in android/binder.h used to encode binders in the real
654       // parceling code.
655       int length = 5 * Integer.SIZE / 8;
656       writeValue(length, b);
657     }
658 
659     /**
660      * Reads an IBinder from the byte buffer based on the current data position
661      */
readStrongBinder()662     public IBinder readStrongBinder() {
663       return readValue(null);
664     }
665 
666     /**
667      * Appends the contents of the other byte buffer to this byte buffer
668      * starting at offset and ending at length.
669      *
670      * @param other ByteBuffer to append to this one
671      * @param offset number of bytes from beginning of byte buffer to start copy from
672      * @param length number of bytes to copy
673      */
appendFrom(ByteBuffer other, int offset, int length)674     public void appendFrom(ByteBuffer other, int offset, int length) {
675       int otherIndex = other.toIndex(offset);
676       int otherEndIndex = other.toIndex(offset + length);
677       for (int i = otherIndex; i < otherEndIndex && i < other.buffer.size(); i++) {
678         int elementSize = other.buffer.get(i).first;
679         Object elementValue = other.buffer.get(i).second;
680         writeValue(elementSize, elementValue);
681       }
682     }
683 
684     /**
685      * Creates a Byte buffer from a raw byte array.
686      *
687      * @param array byte array to read from
688      * @param offset starting position in bytes to start reading array at
689      * @param length number of bytes to read from array
690      */
fromByteArray(byte[] array, int offset, int length)691     public static ByteBuffer fromByteArray(byte[] array, int offset, int length) {
692       ByteBuffer byteBuffer = new ByteBuffer();
693 
694       try {
695         ByteArrayInputStream bis = new ByteArrayInputStream(array, offset,
696             length);
697         ObjectInputStream ois = new ObjectInputStream(bis);
698         int numElements = ois.readInt();
699         for (int i = 0; i < numElements; i++) {
700           int sizeOf = ois.readInt();
701           Object value = ois.readObject();
702           byteBuffer.buffer.add(Pair.create(sizeOf, value));
703         }
704         return byteBuffer;
705       } catch (Exception e) {
706         throw new RuntimeException(e);
707       }
708     }
709 
710     /**
711      * Converts a ByteBuffer to a raw byte array. This method should be
712      * symmetrical with fromByteArray.
713      */
toByteArray()714     public byte[] toByteArray() {
715       try {
716         ByteArrayOutputStream bos = new ByteArrayOutputStream();
717         ObjectOutputStream oos = new ObjectOutputStream(bos);
718         int length = buffer.size();
719         oos.writeInt(length);
720         for (Pair<Integer, ?> element : buffer) {
721           oos.writeInt(element.first);
722           oos.writeObject(element.second);
723         }
724         return bos.toByteArray();
725       } catch (IOException e) {
726         throw new RuntimeException(e);
727       }
728     }
729 
730     /**
731      * Number of unused bytes in this byte buffer.
732      */
dataAvailable()733     public int dataAvailable() {
734       return dataSize() - dataPosition();
735     }
736 
737     /**
738      * Total buffer size in bytes of byte buffer included unused space.
739      */
dataCapacity()740     public int dataCapacity() {
741       return dataSize();
742     }
743 
744     /**
745      * Current data position of byte buffer in bytes. Reads / writes are from this position.
746      */
dataPosition()747     public int dataPosition() {
748       return toDataPosition(index);
749     }
750 
751     /**
752      * Current amount of bytes currently written for ByteBuffer.
753      */
dataSize()754     public int dataSize() {
755       int totalSize = totalSize();
756       int dataPosition = dataPosition();
757       return totalSize > dataPosition ? totalSize : dataPosition;
758     }
759 
760     /**
761      * Sets the current data position.
762      *
763      * @param pos
764      *          Desired position in bytes
765      */
setDataPosition(int pos)766     public void setDataPosition(int pos) {
767       index = toIndex(pos);
768     }
769 
setDataSize(int size)770     public void setDataSize(int size) {
771       // TODO
772     }
773 
setDataCapacity(int size)774     public void setDataCapacity(int size) {
775       // TODO
776     }
777 
totalSize()778     private int totalSize() {
779       int size = 0;
780       for (Pair<Integer, ?> element : buffer) {
781         size += element.first;
782       }
783       return size;
784     }
785 
readValue(T defaultValue)786     private <T> T readValue(T defaultValue) {
787       return (index < buffer.size()) ? (T) buffer.get(index++).second : defaultValue;
788     }
789 
writeValue(int i, Object o)790     private void writeValue(int i, Object o) {
791       // Align the data size to 4-byte boundaries like Parcel does.
792       final int pad = (4 - (i & 3)) & 3;
793       if (pad != 0) {
794         i += pad;
795       }
796 
797       Pair<Integer, ?> value = Pair.create(i, o);
798       if (index < buffer.size()) {
799         buffer.set(index, value);
800       } else {
801         buffer.add(value);
802       }
803       index++;
804     }
805 
toDataPosition(int index)806     private int toDataPosition(int index) {
807       int pos = 0;
808       for (int i = 0; i < index; i++) {
809         pos += buffer.get(i).first;
810       }
811       return pos;
812     }
813 
toIndex(int dataPosition)814     private int toIndex(int dataPosition) {
815       int calculatedPos = 0;
816       int i = 0;
817       for (; i < buffer.size() && calculatedPos < dataPosition; i++) {
818         calculatedPos += buffer.get(i).first;
819       }
820       return i;
821     }
822   }
823 
824   @Implementation(maxSdk = P)
openFileDescriptor(String file, int mode)825   protected static FileDescriptor openFileDescriptor(String file, int mode) throws IOException {
826     RandomAccessFile randomAccessFile =
827         new RandomAccessFile(file, mode == ParcelFileDescriptor.MODE_READ_ONLY ? "r" : "rw");
828     return randomAccessFile.getFD();
829   }
830 }
831