1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.os;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.annotation.TestApi;
24 import android.annotation.UnsupportedAppUsage;
25 
26 import libcore.util.NativeAllocationRegistry;
27 
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 
33 /** @hide */
34 @SystemApi
35 @TestApi
36 public class HwParcel {
37     private static final String TAG = "HwParcel";
38 
39     @IntDef(prefix = { "STATUS_" }, value = {
40         STATUS_SUCCESS,
41     })
42     @Retention(RetentionPolicy.SOURCE)
43     public @interface Status {}
44 
45     /**
46      * Success return error for a transaction. Written to parcels
47      * using writeStatus.
48      */
49     public static final int STATUS_SUCCESS      = 0;
50 
51     private static final NativeAllocationRegistry sNativeRegistry;
52 
53     @UnsupportedAppUsage
HwParcel(boolean allocate)54     private HwParcel(boolean allocate) {
55         native_setup(allocate);
56 
57         sNativeRegistry.registerNativeAllocation(
58                 this,
59                 mNativeContext);
60     }
61 
62     /**
63      * Creates an initialized and empty parcel.
64      */
HwParcel()65     public HwParcel() {
66         native_setup(true /* allocate */);
67 
68         sNativeRegistry.registerNativeAllocation(
69                 this,
70                 mNativeContext);
71     }
72 
73     /**
74      * Writes an interface token into the parcel used to verify that
75      * a transaction has made it to the write type of interface.
76      *
77      * @param interfaceName fully qualified name of interface message
78      *     is being sent to.
79      */
writeInterfaceToken(String interfaceName)80     public native final void writeInterfaceToken(String interfaceName);
81     /**
82      * Writes a boolean value to the end of the parcel.
83      * @param val to write
84      */
writeBool(boolean val)85     public native final void writeBool(boolean val);
86     /**
87      * Writes a byte value to the end of the parcel.
88      * @param val to write
89      */
writeInt8(byte val)90     public native final void writeInt8(byte val);
91     /**
92      * Writes a short value to the end of the parcel.
93      * @param val to write
94      */
writeInt16(short val)95     public native final void writeInt16(short val);
96     /**
97      * Writes a int value to the end of the parcel.
98      * @param val to write
99      */
writeInt32(int val)100     public native final void writeInt32(int val);
101     /**
102      * Writes a long value to the end of the parcel.
103      * @param val to write
104      */
writeInt64(long val)105     public native final void writeInt64(long val);
106     /**
107      * Writes a float value to the end of the parcel.
108      * @param val to write
109      */
writeFloat(float val)110     public native final void writeFloat(float val);
111     /**
112      * Writes a double value to the end of the parcel.
113      * @param val to write
114      */
writeDouble(double val)115     public native final void writeDouble(double val);
116     /**
117      * Writes a String value to the end of the parcel.
118      *
119      * Note, this will be converted to UTF-8 when it is written.
120      *
121      * @param val to write
122      */
writeString(String val)123     public native final void writeString(String val);
124     /**
125      * Writes a native handle (without duplicating the underlying
126      * file descriptors) to the end of the parcel.
127      *
128      * @param val to write
129      */
writeNativeHandle(@ullable NativeHandle val)130     public native final void writeNativeHandle(@Nullable NativeHandle val);
131 
132     /**
133      * Writes an array of boolean values to the end of the parcel.
134      * @param val to write
135      */
writeBoolVector(boolean[] val)136     private native final void writeBoolVector(boolean[] val);
137     /**
138      * Writes an array of byte values to the end of the parcel.
139      * @param val to write
140      */
writeInt8Vector(byte[] val)141     private native final void writeInt8Vector(byte[] val);
142     /**
143      * Writes an array of short values to the end of the parcel.
144      * @param val to write
145      */
writeInt16Vector(short[] val)146     private native final void writeInt16Vector(short[] val);
147     /**
148      * Writes an array of int values to the end of the parcel.
149      * @param val to write
150      */
writeInt32Vector(int[] val)151     private native final void writeInt32Vector(int[] val);
152     /**
153      * Writes an array of long values to the end of the parcel.
154      * @param val to write
155      */
writeInt64Vector(long[] val)156     private native final void writeInt64Vector(long[] val);
157     /**
158      * Writes an array of float values to the end of the parcel.
159      * @param val to write
160      */
writeFloatVector(float[] val)161     private native final void writeFloatVector(float[] val);
162     /**
163      * Writes an array of double values to the end of the parcel.
164      * @param val to write
165      */
writeDoubleVector(double[] val)166     private native final void writeDoubleVector(double[] val);
167     /**
168      * Writes an array of String values to the end of the parcel.
169      *
170      * Note, these will be converted to UTF-8 as they are written.
171      *
172      * @param val to write
173      */
writeStringVector(String[] val)174     private native final void writeStringVector(String[] val);
175     /**
176      * Writes an array of native handles to the end of the parcel.
177      *
178      * Individual elements may be null but not the whole array.
179      *
180      * @param val array of {@link NativeHandle} objects to write
181      */
writeNativeHandleVector(NativeHandle[] val)182     private native final void writeNativeHandleVector(NativeHandle[] val);
183 
184     /**
185      * Helper method to write a list of Booleans to val.
186      * @param val list to write
187      */
writeBoolVector(ArrayList<Boolean> val)188     public final void writeBoolVector(ArrayList<Boolean> val) {
189         final int n = val.size();
190         boolean[] array = new boolean[n];
191         for (int i = 0; i < n; ++i) {
192             array[i] = val.get(i);
193         }
194 
195         writeBoolVector(array);
196     }
197 
198     /**
199      * Helper method to write a list of Booleans to the end of the parcel.
200      * @param val list to write
201      */
writeInt8Vector(ArrayList<Byte> val)202     public final void writeInt8Vector(ArrayList<Byte> val) {
203         final int n = val.size();
204         byte[] array = new byte[n];
205         for (int i = 0; i < n; ++i) {
206             array[i] = val.get(i);
207         }
208 
209         writeInt8Vector(array);
210     }
211 
212     /**
213      * Helper method to write a list of Shorts to the end of the parcel.
214      * @param val list to write
215      */
writeInt16Vector(ArrayList<Short> val)216     public final void writeInt16Vector(ArrayList<Short> val) {
217         final int n = val.size();
218         short[] array = new short[n];
219         for (int i = 0; i < n; ++i) {
220             array[i] = val.get(i);
221         }
222 
223         writeInt16Vector(array);
224     }
225 
226     /**
227      * Helper method to write a list of Integers to the end of the parcel.
228      * @param val list to write
229      */
writeInt32Vector(ArrayList<Integer> val)230     public final void writeInt32Vector(ArrayList<Integer> val) {
231         final int n = val.size();
232         int[] array = new int[n];
233         for (int i = 0; i < n; ++i) {
234             array[i] = val.get(i);
235         }
236 
237         writeInt32Vector(array);
238     }
239 
240     /**
241      * Helper method to write a list of Longs to the end of the parcel.
242      * @param val list to write
243      */
writeInt64Vector(ArrayList<Long> val)244     public final void writeInt64Vector(ArrayList<Long> val) {
245         final int n = val.size();
246         long[] array = new long[n];
247         for (int i = 0; i < n; ++i) {
248             array[i] = val.get(i);
249         }
250 
251         writeInt64Vector(array);
252     }
253 
254     /**
255      * Helper method to write a list of Floats to the end of the parcel.
256      * @param val list to write
257      */
writeFloatVector(ArrayList<Float> val)258     public final void writeFloatVector(ArrayList<Float> val) {
259         final int n = val.size();
260         float[] array = new float[n];
261         for (int i = 0; i < n; ++i) {
262             array[i] = val.get(i);
263         }
264 
265         writeFloatVector(array);
266     }
267 
268     /**
269      * Helper method to write a list of Doubles to the end of the parcel.
270      * @param val list to write
271      */
writeDoubleVector(ArrayList<Double> val)272     public final void writeDoubleVector(ArrayList<Double> val) {
273         final int n = val.size();
274         double[] array = new double[n];
275         for (int i = 0; i < n; ++i) {
276             array[i] = val.get(i);
277         }
278 
279         writeDoubleVector(array);
280     }
281 
282     /**
283      * Helper method to write a list of Strings to the end of the parcel.
284      * @param val list to write
285      */
writeStringVector(ArrayList<String> val)286     public final void writeStringVector(ArrayList<String> val) {
287         writeStringVector(val.toArray(new String[val.size()]));
288     }
289 
290     /**
291      * Helper method to write a list of native handles to the end of the parcel.
292      * @param val list of {@link NativeHandle} objects to write
293      */
writeNativeHandleVector(@onNull ArrayList<NativeHandle> val)294     public final void writeNativeHandleVector(@NonNull ArrayList<NativeHandle> val) {
295         writeNativeHandleVector(val.toArray(new NativeHandle[val.size()]));
296     }
297 
298     /**
299      * Write a hwbinder object to the end of the parcel.
300      * @param binder value to write
301      */
writeStrongBinder(IHwBinder binder)302     public native final void writeStrongBinder(IHwBinder binder);
303 
304     /**
305      * Checks to make sure that the interface name matches the name written by the parcel
306      * sender by writeInterfaceToken
307      *
308      * @throws SecurityException interface doesn't match
309      */
enforceInterface(String interfaceName)310     public native final void enforceInterface(String interfaceName);
311 
312     /**
313      * Reads a boolean value from the current location in the parcel.
314      * @return value parsed from the parcel
315      * @throws IllegalArgumentException if the parcel has no more data
316      */
readBool()317     public native final boolean readBool();
318     /**
319      * Reads a byte value from the current location in the parcel.
320      * @return value parsed from the parcel
321      * @throws IllegalArgumentException if the parcel has no more data
322      */
readInt8()323     public native final byte readInt8();
324     /**
325      * Reads a short value from the current location in the parcel.
326      * @return value parsed from the parcel
327      * @throws IllegalArgumentException if the parcel has no more data
328      */
readInt16()329     public native final short readInt16();
330     /**
331      * Reads a int value from the current location in the parcel.
332      * @return value parsed from the parcel
333      * @throws IllegalArgumentException if the parcel has no more data
334      */
readInt32()335     public native final int readInt32();
336     /**
337      * Reads a long value from the current location in the parcel.
338      * @return value parsed from the parcel
339      * @throws IllegalArgumentException if the parcel has no more data
340      */
readInt64()341     public native final long readInt64();
342     /**
343      * Reads a float value from the current location in the parcel.
344      * @return value parsed from the parcel
345      * @throws IllegalArgumentException if the parcel has no more data
346      */
readFloat()347     public native final float readFloat();
348     /**
349      * Reads a double value from the current location in the parcel.
350      * @return value parsed from the parcel
351      * @throws IllegalArgumentException if the parcel has no more data
352      */
readDouble()353     public native final double readDouble();
354     /**
355      * Reads a String value from the current location in the parcel.
356      * @return value parsed from the parcel
357      * @throws IllegalArgumentException if the parcel has no more data
358      */
readString()359     public native final String readString();
360     /**
361      * Reads a native handle (without duplicating the underlying file
362      * descriptors) from the parcel. These file descriptors will only
363      * be open for the duration that the binder window is open. If they
364      * are needed further, you must call {@link NativeHandle#dup()}.
365      *
366      * @return a {@link NativeHandle} instance parsed from the parcel
367      * @throws IllegalArgumentException if the parcel has no more data
368      */
readNativeHandle()369     public native final @Nullable NativeHandle readNativeHandle();
370     /**
371      * Reads an embedded native handle (without duplicating the underlying
372      * file descriptors) from the parcel. These file descriptors will only
373      * be open for the duration that the binder window is open. If they
374      * are needed further, you must call {@link NativeHandle#dup()}. You
375      * do not need to call close on the NativeHandle returned from this.
376      *
377      * @param parentHandle handle from which to read the embedded object
378      * @param offset offset into parent
379      * @return a {@link NativeHandle} instance parsed from the parcel
380      * @throws IllegalArgumentException if the parcel has no more data
381      */
readEmbeddedNativeHandle( long parentHandle, long offset)382     public native final @Nullable NativeHandle readEmbeddedNativeHandle(
383             long parentHandle, long offset);
384 
385     /**
386      * Reads an array of boolean values from the parcel.
387      * @return array of parsed values
388      * @throws IllegalArgumentException if the parcel has no more data
389      */
readBoolVectorAsArray()390     private native final boolean[] readBoolVectorAsArray();
391     /**
392      * Reads an array of byte values from the parcel.
393      * @return array of parsed values
394      * @throws IllegalArgumentException if the parcel has no more data
395      */
readInt8VectorAsArray()396     private native final byte[] readInt8VectorAsArray();
397     /**
398      * Reads an array of short values from the parcel.
399      * @return array of parsed values
400      * @throws IllegalArgumentException if the parcel has no more data
401      */
readInt16VectorAsArray()402     private native final short[] readInt16VectorAsArray();
403     /**
404      * Reads an array of int values from the parcel.
405      * @return array of parsed values
406      * @throws IllegalArgumentException if the parcel has no more data
407      */
readInt32VectorAsArray()408     private native final int[] readInt32VectorAsArray();
409     /**
410      * Reads an array of long values from the parcel.
411      * @return array of parsed values
412      * @throws IllegalArgumentException if the parcel has no more data
413      */
readInt64VectorAsArray()414     private native final long[] readInt64VectorAsArray();
415     /**
416      * Reads an array of float values from the parcel.
417      * @return array of parsed values
418      * @throws IllegalArgumentException if the parcel has no more data
419      */
readFloatVectorAsArray()420     private native final float[] readFloatVectorAsArray();
421     /**
422      * Reads an array of double values from the parcel.
423      * @return array of parsed values
424      * @throws IllegalArgumentException if the parcel has no more data
425      */
readDoubleVectorAsArray()426     private native final double[] readDoubleVectorAsArray();
427     /**
428      * Reads an array of String values from the parcel.
429      * @return array of parsed values
430      * @throws IllegalArgumentException if the parcel has no more data
431      */
readStringVectorAsArray()432     private native final String[] readStringVectorAsArray();
433     /**
434      * Reads an array of native handles from the parcel.
435      * @return array of {@link NativeHandle} objects
436      * @throws IllegalArgumentException if the parcel has no more data
437      */
readNativeHandleAsArray()438     private native final NativeHandle[] readNativeHandleAsArray();
439 
440     /**
441      * Convenience method to read a Boolean vector as an ArrayList.
442      * @return array of parsed values.
443      * @throws IllegalArgumentException if the parcel has no more data
444      */
readBoolVector()445     public final ArrayList<Boolean> readBoolVector() {
446         Boolean[] array = HwBlob.wrapArray(readBoolVectorAsArray());
447 
448         return new ArrayList<Boolean>(Arrays.asList(array));
449     }
450 
451     /**
452      * Convenience method to read a Byte vector as an ArrayList.
453      * @return array of parsed values.
454      * @throws IllegalArgumentException if the parcel has no more data
455      */
readInt8Vector()456     public final ArrayList<Byte> readInt8Vector() {
457         Byte[] array = HwBlob.wrapArray(readInt8VectorAsArray());
458 
459         return new ArrayList<Byte>(Arrays.asList(array));
460     }
461 
462     /**
463      * Convenience method to read a Short vector as an ArrayList.
464      * @return array of parsed values.
465      * @throws IllegalArgumentException if the parcel has no more data
466      */
readInt16Vector()467     public final ArrayList<Short> readInt16Vector() {
468         Short[] array = HwBlob.wrapArray(readInt16VectorAsArray());
469 
470         return new ArrayList<Short>(Arrays.asList(array));
471     }
472 
473     /**
474      * Convenience method to read a Integer vector as an ArrayList.
475      * @return array of parsed values.
476      * @throws IllegalArgumentException if the parcel has no more data
477      */
readInt32Vector()478     public final ArrayList<Integer> readInt32Vector() {
479         Integer[] array = HwBlob.wrapArray(readInt32VectorAsArray());
480 
481         return new ArrayList<Integer>(Arrays.asList(array));
482     }
483 
484     /**
485      * Convenience method to read a Long vector as an ArrayList.
486      * @return array of parsed values.
487      * @throws IllegalArgumentException if the parcel has no more data
488      */
readInt64Vector()489     public final ArrayList<Long> readInt64Vector() {
490         Long[] array = HwBlob.wrapArray(readInt64VectorAsArray());
491 
492         return new ArrayList<Long>(Arrays.asList(array));
493     }
494 
495     /**
496      * Convenience method to read a Float vector as an ArrayList.
497      * @return array of parsed values.
498      * @throws IllegalArgumentException if the parcel has no more data
499      */
readFloatVector()500     public final ArrayList<Float> readFloatVector() {
501         Float[] array = HwBlob.wrapArray(readFloatVectorAsArray());
502 
503         return new ArrayList<Float>(Arrays.asList(array));
504     }
505 
506     /**
507      * Convenience method to read a Double vector as an ArrayList.
508      * @return array of parsed values.
509      * @throws IllegalArgumentException if the parcel has no more data
510      */
readDoubleVector()511     public final ArrayList<Double> readDoubleVector() {
512         Double[] array = HwBlob.wrapArray(readDoubleVectorAsArray());
513 
514         return new ArrayList<Double>(Arrays.asList(array));
515     }
516 
517     /**
518      * Convenience method to read a String vector as an ArrayList.
519      * @return array of parsed values.
520      * @throws IllegalArgumentException if the parcel has no more data
521      */
readStringVector()522     public final ArrayList<String> readStringVector() {
523         return new ArrayList<String>(Arrays.asList(readStringVectorAsArray()));
524     }
525 
526     /**
527      * Convenience method to read a vector of native handles as an ArrayList.
528      * @return array of {@link NativeHandle} objects.
529      * @throws IllegalArgumentException if the parcel has no more data
530      */
readNativeHandleVector()531     public final @NonNull ArrayList<NativeHandle> readNativeHandleVector() {
532         return new ArrayList<NativeHandle>(Arrays.asList(readNativeHandleAsArray()));
533     }
534 
535     /**
536      * Reads a strong binder value from the parcel.
537      * @return binder object read from parcel or null if no binder can be read
538      * @throws IllegalArgumentException if the parcel has no more data
539      */
readStrongBinder()540     public native final IHwBinder readStrongBinder();
541 
542     /**
543      * Read opaque segment of data as a blob.
544      * @return blob of size expectedSize
545      * @throws IllegalArgumentException if the parcel has no more data
546      */
readBuffer(long expectedSize)547     public native final HwBlob readBuffer(long expectedSize);
548 
549     /**
550      * Read a buffer written using scatter gather.
551      *
552      * @param expectedSize size that buffer should be
553      * @param parentHandle handle from which to read the embedded buffer
554      * @param offset offset into parent
555      * @param nullable whether or not to allow for a null return
556      * @return blob of data with size expectedSize
557      * @throws NoSuchElementException if an embedded buffer is not available to read
558      * @throws IllegalArgumentException if expectedSize < 0
559      * @throws NullPointerException if the transaction specified the blob to be null
560      *    but nullable is false
561      */
readEmbeddedBuffer( long expectedSize, long parentHandle, long offset, boolean nullable)562     public native final HwBlob readEmbeddedBuffer(
563             long expectedSize, long parentHandle, long offset,
564             boolean nullable);
565 
566     /**
567      * Write a buffer into the transaction.
568      * @param blob blob to write into the parcel.
569      */
writeBuffer(HwBlob blob)570     public native final void writeBuffer(HwBlob blob);
571     /**
572      * Write a status value into the blob.
573      * @param status value to write
574      */
writeStatus(int status)575     public native final void writeStatus(int status);
576     /**
577      * @throws IllegalArgumentException if a success vaue cannot be read
578      * @throws RemoteException if success value indicates a transaction error
579      */
verifySuccess()580     public native final void verifySuccess();
581     /**
582      * Should be called to reduce memory pressure when this object no longer needs
583      * to be written to.
584      */
releaseTemporaryStorage()585     public native final void releaseTemporaryStorage();
586     /**
587      * Should be called when object is no longer needed to reduce possible memory
588      * pressure if the Java GC does not get to this object in time.
589      */
release()590     public native final void release();
591 
592     /**
593      * Sends the parcel to the specified destination.
594      */
send()595     public native final void send();
596 
597     // Returns address of the "freeFunction".
native_init()598     private static native final long native_init();
599 
native_setup(boolean allocate)600     private native final void native_setup(boolean allocate);
601 
602     static {
603         long freeFunction = native_init();
604 
605         sNativeRegistry = new NativeAllocationRegistry(
606                 HwParcel.class.getClassLoader(),
607                 freeFunction,
608                 128 /* size */);
609     }
610 
611     private long mNativeContext;
612 }
613 
614