1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.mojo.bindings;
6 
7 import org.chromium.mojo.bindings.Interface.Proxy;
8 import org.chromium.mojo.system.DataPipe;
9 import org.chromium.mojo.system.Handle;
10 import org.chromium.mojo.system.InvalidHandle;
11 import org.chromium.mojo.system.MessagePipeHandle;
12 import org.chromium.mojo.system.SharedBufferHandle;
13 import org.chromium.mojo.system.UntypedHandle;
14 
15 import java.nio.ByteOrder;
16 import java.nio.charset.Charset;
17 
18 /**
19  * A Decoder is a helper class for deserializing a mojo struct. It enables deserialization of basic
20  * types from a {@link Message} object at a given offset into it's byte buffer.
21  */
22 public class Decoder {
23 
24     /**
25      * Helper class to validate the decoded message.
26      */
27     static final class Validator {
28 
29         /**
30          * Minimal value for the next handle to deserialize.
31          */
32         private int mMinNextClaimedHandle;
33         /**
34          * Minimal value of the start of the next memory to claim.
35          */
36         private long mMinNextMemory;
37         /**
38          * The current nesting level when decoding.
39          */
40         private long mStackDepth;
41 
42         /**
43          * The maximal memory accessible.
44          */
45         private final long mMaxMemory;
46 
47         /**
48          * The number of handles in the message.
49          */
50         private final long mNumberOfHandles;
51 
52         /**
53          * The maximum nesting level when decoding.
54          */
55         private static final int MAX_RECURSION_DEPTH = 100;
56 
57         /**
58          * Constructor.
59          */
Validator(long maxMemory, int numberOfHandles)60         Validator(long maxMemory, int numberOfHandles) {
61             mMaxMemory = maxMemory;
62             mNumberOfHandles = numberOfHandles;
63             mStackDepth = 0;
64         }
65 
claimHandle(int handle)66         public void claimHandle(int handle) {
67             if (handle < mMinNextClaimedHandle) {
68                 throw new DeserializationException(
69                         "Trying to access handle out of order.");
70             }
71             if (handle >= mNumberOfHandles) {
72                 throw new DeserializationException("Trying to access non present handle.");
73             }
74             mMinNextClaimedHandle = handle + 1;
75         }
76 
claimMemory(long start, long end)77         public void claimMemory(long start, long end) {
78             if (start % BindingsHelper.ALIGNMENT != 0) {
79                 throw new DeserializationException("Incorrect starting alignment: " + start + ".");
80             }
81             if (start < mMinNextMemory) {
82                 throw new DeserializationException("Trying to access memory out of order.");
83             }
84             if (end < start) {
85                 throw new DeserializationException("Incorrect memory range.");
86             }
87             if (end > mMaxMemory) {
88                 throw new DeserializationException("Trying to access out of range memory.");
89             }
90             mMinNextMemory = BindingsHelper.align(end);
91         }
92 
increaseStackDepth()93         public void increaseStackDepth() {
94             ++mStackDepth;
95             if (mStackDepth >= MAX_RECURSION_DEPTH) {
96                 throw new DeserializationException("Recursion depth limit exceeded.");
97             }
98         }
99 
decreaseStackDepth()100         public void decreaseStackDepth() {
101             --mStackDepth;
102         }
103     }
104 
105     /**
106      * The message to deserialize from.
107      */
108     private final Message mMessage;
109 
110     /**
111      * The base offset in the byte buffer.
112      */
113     private final int mBaseOffset;
114 
115     /**
116      * Validator for the decoded message.
117      */
118     private final Validator mValidator;
119 
120     /**
121      * Constructor.
122      *
123      * @param message The message to decode.
124      */
Decoder(Message message)125     public Decoder(Message message) {
126         this(message, new Validator(message.getData().limit(), message.getHandles().size()), 0);
127     }
128 
Decoder(Message message, Validator validator, int baseOffset)129     private Decoder(Message message, Validator validator, int baseOffset) {
130         mMessage = message;
131         mMessage.getData().order(ByteOrder.LITTLE_ENDIAN);
132         mBaseOffset = baseOffset;
133         mValidator = validator;
134     }
135 
136     /**
137      * Deserializes a {@link DataHeader} at the current position.
138      */
readDataHeader()139     public DataHeader readDataHeader() {
140         // Claim the memory for the header.
141         mValidator.claimMemory(mBaseOffset, mBaseOffset + DataHeader.HEADER_SIZE);
142         DataHeader result = readDataHeaderAtOffset(0, false);
143         // Claim the rest of the memory.
144         mValidator.claimMemory(mBaseOffset + DataHeader.HEADER_SIZE, mBaseOffset + result.size);
145         return result;
146     }
147 
148     /**
149      * Deserializes a {@link DataHeader} for an union at the given offset.
150      */
readDataHeaderForUnion(int offset)151     public DataHeader readDataHeaderForUnion(int offset) {
152         DataHeader result = readDataHeaderAtOffset(offset, true);
153         if (result.size == 0) {
154             if (result.elementsOrVersion != 0) {
155                 throw new DeserializationException(
156                         "Unexpected version tag for a null union. Expecting 0, found: "
157                         + result.elementsOrVersion);
158             }
159         } else if (result.size != BindingsHelper.UNION_SIZE) {
160             throw new DeserializationException(
161                     "Unexpected size of an union. The size must be 0 for a null union, or 16 for "
162                     + "a non-null union.");
163         }
164         return result;
165     }
166 
167     /**
168      * @returns a decoder suitable to decode an union defined as the root object of a message.
169      */
decoderForSerializedUnion()170     public Decoder decoderForSerializedUnion() {
171         mValidator.claimMemory(0, BindingsHelper.UNION_SIZE);
172         return this;
173     }
174 
175     /**
176      * Deserializes a {@link DataHeader} at the given offset.
177      */
readDataHeaderAtOffset(int offset, boolean isUnion)178     private DataHeader readDataHeaderAtOffset(int offset, boolean isUnion) {
179         int size = readInt(offset + DataHeader.SIZE_OFFSET);
180         int elementsOrVersion = readInt(offset + DataHeader.ELEMENTS_OR_VERSION_OFFSET);
181         if (size < 0) {
182             throw new DeserializationException(
183                     "Negative size. Unsigned integers are not valid for java.");
184         }
185         if (elementsOrVersion < 0 && (!isUnion || elementsOrVersion != -1)) {
186             throw new DeserializationException(
187                     "Negative elements or version. Unsigned integers are not valid for java.");
188         }
189 
190         return new DataHeader(size, elementsOrVersion);
191     }
192 
readAndValidateDataHeader(DataHeader[] versionArray)193     public DataHeader readAndValidateDataHeader(DataHeader[] versionArray) {
194         DataHeader header = readDataHeader();
195         int maxVersionIndex = versionArray.length - 1;
196         if (header.elementsOrVersion <= versionArray[maxVersionIndex].elementsOrVersion) {
197             DataHeader referenceHeader = null;
198             for (int index = maxVersionIndex; index >= 0; index--) {
199                 DataHeader dataHeader = versionArray[index];
200                 if (header.elementsOrVersion >= dataHeader.elementsOrVersion) {
201                     referenceHeader = dataHeader;
202                     break;
203                 }
204             }
205             if (referenceHeader == null || referenceHeader.size != header.size) {
206                 throw new DeserializationException(
207                         "Header doesn't correspond to any known version.");
208             }
209         } else {
210             if (header.size < versionArray[maxVersionIndex].size) {
211                 throw new DeserializationException("Message newer than the last known version"
212                         + " cannot be shorter than required by the last known version.");
213             }
214         }
215         return header;
216     }
217 
218     /**
219      * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an
220      * array where elements are pointers.
221      */
readDataHeaderForPointerArray(int expectedLength)222     public DataHeader readDataHeaderForPointerArray(int expectedLength) {
223         return readDataHeaderForArray(BindingsHelper.POINTER_SIZE, expectedLength);
224     }
225 
226     /**
227      * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an
228      * array where elements are unions.
229      */
readDataHeaderForUnionArray(int expectedLength)230     public DataHeader readDataHeaderForUnionArray(int expectedLength) {
231         return readDataHeaderForArray(BindingsHelper.UNION_SIZE, expectedLength);
232     }
233 
234     /**
235      * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for a map.
236      */
readDataHeaderForMap()237     public void readDataHeaderForMap() {
238         DataHeader si = readDataHeader();
239         if (si.size != BindingsHelper.MAP_STRUCT_HEADER.size) {
240             throw new DeserializationException(
241                     "Incorrect header for map. The size is incorrect.");
242         }
243         if (si.elementsOrVersion != BindingsHelper.MAP_STRUCT_HEADER.elementsOrVersion) {
244             throw new DeserializationException(
245                     "Incorrect header for map. The version is incorrect.");
246         }
247     }
248 
249     /**
250      * Deserializes a byte at the given offset.
251      */
readByte(int offset)252     public byte readByte(int offset) {
253         validateBufferSize(offset, 1);
254         return mMessage.getData().get(mBaseOffset + offset);
255     }
256 
257     /**
258      * Deserializes a boolean at the given offset, re-using any partially read byte.
259      */
readBoolean(int offset, int bit)260     public boolean readBoolean(int offset, int bit) {
261         validateBufferSize(offset, 1);
262         return (readByte(offset) & (1 << bit)) != 0;
263     }
264 
265     /**
266      * Deserializes a short at the given offset.
267      */
readShort(int offset)268     public short readShort(int offset) {
269         validateBufferSize(offset, 2);
270         return mMessage.getData().getShort(mBaseOffset + offset);
271     }
272 
273     /**
274      * Deserializes an int at the given offset.
275      */
readInt(int offset)276     public int readInt(int offset) {
277         validateBufferSize(offset, 4);
278         return mMessage.getData().getInt(mBaseOffset + offset);
279     }
280 
281     /**
282      * Deserializes a float at the given offset.
283      */
readFloat(int offset)284     public float readFloat(int offset) {
285         validateBufferSize(offset, 4);
286         return mMessage.getData().getFloat(mBaseOffset + offset);
287     }
288 
289     /**
290      * Deserializes a long at the given offset.
291      */
readLong(int offset)292     public long readLong(int offset) {
293         validateBufferSize(offset, 8);
294         return mMessage.getData().getLong(mBaseOffset + offset);
295     }
296 
297     /**
298      * Deserializes a double at the given offset.
299      */
readDouble(int offset)300     public double readDouble(int offset) {
301         validateBufferSize(offset, 8);
302         return mMessage.getData().getDouble(mBaseOffset + offset);
303     }
304 
305     /**
306      * Deserializes a pointer at the given offset. Returns a Decoder suitable to decode the content
307      * of the pointer.
308      */
readPointer(int offset, boolean nullable)309     public Decoder readPointer(int offset, boolean nullable) {
310         int basePosition = mBaseOffset + offset;
311         long pointerOffset = readLong(offset);
312         if (pointerOffset == 0) {
313             if (!nullable) {
314                 throw new DeserializationException(
315                         "Trying to decode null pointer for a non-nullable type.");
316             }
317             return null;
318         }
319         int newPosition = (int) (basePosition + pointerOffset);
320         // The method |getDecoderAtPosition| will validate that the pointer address is valid.
321         return getDecoderAtPosition(newPosition);
322 
323     }
324 
325     /**
326      * Deserializes an array of boolean at the given offset.
327      */
readBooleans(int offset, int arrayNullability, int expectedLength)328     public boolean[] readBooleans(int offset, int arrayNullability, int expectedLength) {
329         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
330         if (d == null) {
331             return null;
332         }
333         DataHeader si = d.readDataHeaderForBooleanArray(expectedLength);
334         byte[] bytes = new byte[(si.elementsOrVersion + 7) / BindingsHelper.ALIGNMENT];
335         d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
336         d.mMessage.getData().get(bytes);
337         boolean[] result = new boolean[si.elementsOrVersion];
338         for (int i = 0; i < bytes.length; ++i) {
339             for (int j = 0; j < BindingsHelper.ALIGNMENT; ++j) {
340                 int booleanIndex = i * BindingsHelper.ALIGNMENT + j;
341                 if (booleanIndex < result.length) {
342                     result[booleanIndex] = (bytes[i] & (1 << j)) != 0;
343                 }
344             }
345         }
346         return result;
347     }
348 
349     /**
350      * Deserializes an array of bytes at the given offset.
351      */
readBytes(int offset, int arrayNullability, int expectedLength)352     public byte[] readBytes(int offset, int arrayNullability, int expectedLength) {
353         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
354         if (d == null) {
355             return null;
356         }
357         DataHeader si = d.readDataHeaderForArray(1, expectedLength);
358         byte[] result = new byte[si.elementsOrVersion];
359         d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
360         d.mMessage.getData().get(result);
361         return result;
362     }
363 
364     /**
365      * Deserializes an array of shorts at the given offset.
366      */
readShorts(int offset, int arrayNullability, int expectedLength)367     public short[] readShorts(int offset, int arrayNullability, int expectedLength) {
368         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
369         if (d == null) {
370             return null;
371         }
372         DataHeader si = d.readDataHeaderForArray(2, expectedLength);
373         short[] result = new short[si.elementsOrVersion];
374         d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
375         d.mMessage.getData().asShortBuffer().get(result);
376         return result;
377     }
378 
379     /**
380      * Deserializes an array of ints at the given offset.
381      */
readInts(int offset, int arrayNullability, int expectedLength)382     public int[] readInts(int offset, int arrayNullability, int expectedLength) {
383         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
384         if (d == null) {
385             return null;
386         }
387         DataHeader si = d.readDataHeaderForArray(4, expectedLength);
388         int[] result = new int[si.elementsOrVersion];
389         d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
390         d.mMessage.getData().asIntBuffer().get(result);
391         return result;
392     }
393 
394     /**
395      * Deserializes an array of floats at the given offset.
396      */
readFloats(int offset, int arrayNullability, int expectedLength)397     public float[] readFloats(int offset, int arrayNullability, int expectedLength) {
398         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
399         if (d == null) {
400             return null;
401         }
402         DataHeader si = d.readDataHeaderForArray(4, expectedLength);
403         float[] result = new float[si.elementsOrVersion];
404         d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
405         d.mMessage.getData().asFloatBuffer().get(result);
406         return result;
407     }
408 
409     /**
410      * Deserializes an array of longs at the given offset.
411      */
readLongs(int offset, int arrayNullability, int expectedLength)412     public long[] readLongs(int offset, int arrayNullability, int expectedLength) {
413         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
414         if (d == null) {
415             return null;
416         }
417         DataHeader si = d.readDataHeaderForArray(8, expectedLength);
418         long[] result = new long[si.elementsOrVersion];
419         d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
420         d.mMessage.getData().asLongBuffer().get(result);
421         return result;
422     }
423 
424     /**
425      * Deserializes an array of doubles at the given offset.
426      */
readDoubles(int offset, int arrayNullability, int expectedLength)427     public double[] readDoubles(int offset, int arrayNullability, int expectedLength) {
428         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
429         if (d == null) {
430             return null;
431         }
432         DataHeader si = d.readDataHeaderForArray(8, expectedLength);
433         double[] result = new double[si.elementsOrVersion];
434         d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
435         d.mMessage.getData().asDoubleBuffer().get(result);
436         return result;
437     }
438 
439     /**
440      * Deserializes an |Handle| at the given offset.
441      */
readHandle(int offset, boolean nullable)442     public Handle readHandle(int offset, boolean nullable) {
443         int index = readInt(offset);
444         if (index == -1) {
445             if (!nullable) {
446                 throw new DeserializationException(
447                         "Trying to decode an invalid handle for a non-nullable type.");
448             }
449             return InvalidHandle.INSTANCE;
450         }
451         mValidator.claimHandle(index);
452         return mMessage.getHandles().get(index);
453     }
454 
455     /**
456      * Deserializes an |UntypedHandle| at the given offset.
457      */
readUntypedHandle(int offset, boolean nullable)458     public UntypedHandle readUntypedHandle(int offset, boolean nullable) {
459         return readHandle(offset, nullable).toUntypedHandle();
460     }
461 
462     /**
463      * Deserializes a |ConsumerHandle| at the given offset.
464      */
readConsumerHandle(int offset, boolean nullable)465     public DataPipe.ConsumerHandle readConsumerHandle(int offset, boolean nullable) {
466         return readUntypedHandle(offset, nullable).toDataPipeConsumerHandle();
467     }
468 
469     /**
470      * Deserializes a |ProducerHandle| at the given offset.
471      */
readProducerHandle(int offset, boolean nullable)472     public DataPipe.ProducerHandle readProducerHandle(int offset, boolean nullable) {
473         return readUntypedHandle(offset, nullable).toDataPipeProducerHandle();
474     }
475 
476     /**
477      * Deserializes a |MessagePipeHandle| at the given offset.
478      */
readMessagePipeHandle(int offset, boolean nullable)479     public MessagePipeHandle readMessagePipeHandle(int offset, boolean nullable) {
480         return readUntypedHandle(offset, nullable).toMessagePipeHandle();
481     }
482 
483     /**
484      * Deserializes a |SharedBufferHandle| at the given offset.
485      */
readSharedBufferHandle(int offset, boolean nullable)486     public SharedBufferHandle readSharedBufferHandle(int offset, boolean nullable) {
487         return readUntypedHandle(offset, nullable).toSharedBufferHandle();
488     }
489 
490     /**
491      * Deserializes an interface at the given offset.
492      *
493      * @return a proxy to the service.
494      */
readServiceInterface(int offset, boolean nullable, Interface.Manager<?, P> manager)495     public <P extends Proxy> P readServiceInterface(int offset, boolean nullable,
496             Interface.Manager<?, P> manager) {
497         MessagePipeHandle handle = readMessagePipeHandle(offset, nullable);
498         if (!handle.isValid()) {
499             return null;
500         }
501         int version = readInt(offset + BindingsHelper.SERIALIZED_HANDLE_SIZE);
502         return manager.attachProxy(handle, version);
503     }
504 
505     /**
506      * Deserializes a |InterfaceRequest| at the given offset.
507      */
readInterfaceRequest(int offset, boolean nullable)508     public <I extends Interface> InterfaceRequest<I> readInterfaceRequest(int offset,
509             boolean nullable) {
510         MessagePipeHandle handle = readMessagePipeHandle(offset, nullable);
511         if (handle == null) {
512             return null;
513         }
514         return new InterfaceRequest<I>(handle);
515     }
516 
517     /**
518      * Deserializes an associated interface at the given offset. Not yet supported.
519      */
readAssociatedServiceInterfaceNotSupported(int offset, boolean nullable)520     public AssociatedInterfaceNotSupported readAssociatedServiceInterfaceNotSupported(int offset,
521             boolean nullable) {
522         return null;
523     }
524 
525     /**
526      * Deserializes an associated interface request at the given offset. Not yet supported.
527      */
readAssociatedInterfaceRequestNotSupported( int offset, boolean nullable)528     public AssociatedInterfaceRequestNotSupported readAssociatedInterfaceRequestNotSupported(
529             int offset, boolean nullable) {
530         return null;
531     }
532 
533     /**
534      * Deserializes a string at the given offset.
535      */
readString(int offset, boolean nullable)536     public String readString(int offset, boolean nullable) {
537         final int arrayNullability = nullable ? BindingsHelper.ARRAY_NULLABLE : 0;
538         byte[] bytes = readBytes(offset, arrayNullability, BindingsHelper.UNSPECIFIED_ARRAY_LENGTH);
539         if (bytes == null) {
540             return null;
541         }
542         return new String(bytes, Charset.forName("utf8"));
543     }
544 
545     /**
546      * Deserializes an array of |Handle| at the given offset.
547      */
readHandles(int offset, int arrayNullability, int expectedLength)548     public Handle[] readHandles(int offset, int arrayNullability, int expectedLength) {
549         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
550         if (d == null) {
551             return null;
552         }
553         DataHeader si = d.readDataHeaderForArray(4, expectedLength);
554         Handle[] result = new Handle[si.elementsOrVersion];
555         for (int i = 0; i < result.length; ++i) {
556             result[i] = d.readHandle(
557                     DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
558                     BindingsHelper.isElementNullable(arrayNullability));
559         }
560         return result;
561     }
562 
563     /**
564      * Deserializes an array of |UntypedHandle| at the given offset.
565      */
readUntypedHandles( int offset, int arrayNullability, int expectedLength)566     public UntypedHandle[] readUntypedHandles(
567             int offset, int arrayNullability, int expectedLength) {
568         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
569         if (d == null) {
570             return null;
571         }
572         DataHeader si = d.readDataHeaderForArray(4, expectedLength);
573         UntypedHandle[] result = new UntypedHandle[si.elementsOrVersion];
574         for (int i = 0; i < result.length; ++i) {
575             result[i] = d.readUntypedHandle(
576                     DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
577                     BindingsHelper.isElementNullable(arrayNullability));
578         }
579         return result;
580     }
581 
582     /**
583      * Deserializes an array of |ConsumerHandle| at the given offset.
584      */
readConsumerHandles( int offset, int arrayNullability, int expectedLength)585     public DataPipe.ConsumerHandle[] readConsumerHandles(
586             int offset, int arrayNullability, int expectedLength) {
587         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
588         if (d == null) {
589             return null;
590         }
591         DataHeader si = d.readDataHeaderForArray(4, expectedLength);
592         DataPipe.ConsumerHandle[] result = new DataPipe.ConsumerHandle[si.elementsOrVersion];
593         for (int i = 0; i < result.length; ++i) {
594             result[i] = d.readConsumerHandle(
595                     DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
596                     BindingsHelper.isElementNullable(arrayNullability));
597         }
598         return result;
599     }
600 
601     /**
602      * Deserializes an array of |ProducerHandle| at the given offset.
603      */
readProducerHandles( int offset, int arrayNullability, int expectedLength)604     public DataPipe.ProducerHandle[] readProducerHandles(
605             int offset, int arrayNullability, int expectedLength) {
606         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
607         if (d == null) {
608             return null;
609         }
610         DataHeader si = d.readDataHeaderForArray(4, expectedLength);
611         DataPipe.ProducerHandle[] result = new DataPipe.ProducerHandle[si.elementsOrVersion];
612         for (int i = 0; i < result.length; ++i) {
613             result[i] = d.readProducerHandle(
614                     DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
615                     BindingsHelper.isElementNullable(arrayNullability));
616         }
617         return result;
618 
619     }
620 
621     /**
622      * Deserializes an array of |MessagePipeHandle| at the given offset.
623      */
readMessagePipeHandles( int offset, int arrayNullability, int expectedLength)624     public MessagePipeHandle[] readMessagePipeHandles(
625             int offset, int arrayNullability, int expectedLength) {
626         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
627         if (d == null) {
628             return null;
629         }
630         DataHeader si = d.readDataHeaderForArray(4, expectedLength);
631         MessagePipeHandle[] result = new MessagePipeHandle[si.elementsOrVersion];
632         for (int i = 0; i < result.length; ++i) {
633             result[i] = d.readMessagePipeHandle(
634                     DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
635                     BindingsHelper.isElementNullable(arrayNullability));
636         }
637         return result;
638 
639     }
640 
641     /**
642      * Deserializes an array of |SharedBufferHandle| at the given offset.
643      */
readSharedBufferHandles( int offset, int arrayNullability, int expectedLength)644     public SharedBufferHandle[] readSharedBufferHandles(
645             int offset, int arrayNullability, int expectedLength) {
646         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
647         if (d == null) {
648             return null;
649         }
650         DataHeader si = d.readDataHeaderForArray(4, expectedLength);
651         SharedBufferHandle[] result = new SharedBufferHandle[si.elementsOrVersion];
652         for (int i = 0; i < result.length; ++i) {
653             result[i] = d.readSharedBufferHandle(
654                     DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
655                     BindingsHelper.isElementNullable(arrayNullability));
656         }
657         return result;
658 
659     }
660 
661     /**
662      * Deserializes an array of |ServiceHandle| at the given offset.
663      */
readServiceInterfaces( int offset, int arrayNullability, int expectedLength, Interface.Manager<S, P> manager)664     public <S extends Interface, P extends Proxy> S[] readServiceInterfaces(
665             int offset, int arrayNullability, int expectedLength, Interface.Manager<S, P> manager) {
666         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
667         if (d == null) {
668             return null;
669         }
670         DataHeader si =
671                 d.readDataHeaderForArray(BindingsHelper.SERIALIZED_INTERFACE_SIZE, expectedLength);
672         S[] result = manager.buildArray(si.elementsOrVersion);
673         for (int i = 0; i < result.length; ++i) {
674             // This cast is necessary because java 6 doesn't handle wildcard correctly when using
675             // Manager<S, ? extends S>
676             @SuppressWarnings("unchecked")
677             S value = (S) d.readServiceInterface(
678                     DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_INTERFACE_SIZE * i,
679                     BindingsHelper.isElementNullable(arrayNullability), manager);
680             result[i] = value;
681         }
682         return result;
683     }
684 
685     /**
686      * Deserializes an array of |InterfaceRequest| at the given offset.
687      */
readInterfaceRequests( int offset, int arrayNullability, int expectedLength)688     public <I extends Interface> InterfaceRequest<I>[] readInterfaceRequests(
689             int offset, int arrayNullability, int expectedLength) {
690         Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
691         if (d == null) {
692             return null;
693         }
694         DataHeader si = d.readDataHeaderForArray(4, expectedLength);
695         @SuppressWarnings("unchecked")
696         InterfaceRequest<I>[] result = new InterfaceRequest[si.elementsOrVersion];
697         for (int i = 0; i < result.length; ++i) {
698             result[i] = d.readInterfaceRequest(
699                     DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
700                     BindingsHelper.isElementNullable(arrayNullability));
701         }
702         return result;
703     }
704 
705     /**
706      * Deserializes an array of associated interfaces at the given offset. Not yet supported.
707      */
readAssociatedServiceInterfaceNotSupporteds( int offset, int arrayNullability, int expectedLength)708     public AssociatedInterfaceNotSupported[] readAssociatedServiceInterfaceNotSupporteds(
709             int offset, int arrayNullability, int expectedLength) {
710         return null;
711     }
712 
713     /**
714      * Deserializes an array of associated interface requests at the given offset. Not yet
715      * supported.
716      */
readAssociatedInterfaceRequestNotSupporteds( int offset, int arrayNullability, int expectedLength)717     public AssociatedInterfaceRequestNotSupported[] readAssociatedInterfaceRequestNotSupporteds(
718             int offset, int arrayNullability, int expectedLength) {
719         return null;
720     }
721 
722     /**
723      * Returns a view of this decoder at the offset |offset|.
724      */
getDecoderAtPosition(int offset)725     private Decoder getDecoderAtPosition(int offset) {
726         return new Decoder(mMessage, mValidator, offset);
727     }
728 
729     /**
730      * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an
731      * array of booleans.
732      */
readDataHeaderForBooleanArray(int expectedLength)733     private DataHeader readDataHeaderForBooleanArray(int expectedLength) {
734         DataHeader dataHeader = readDataHeader();
735         if (dataHeader.size < DataHeader.HEADER_SIZE + (dataHeader.elementsOrVersion + 7) / 8) {
736             throw new DeserializationException("Array header is incorrect.");
737         }
738         if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
739                 && dataHeader.elementsOrVersion != expectedLength) {
740             throw new DeserializationException("Incorrect array length. Expected: " + expectedLength
741                     + ", but got: " + dataHeader.elementsOrVersion + ".");
742         }
743         return dataHeader;
744     }
745 
746     /**
747      * Deserializes a {@link DataHeader} of an array at the given offset.
748      */
readDataHeaderForArray(long elementSize, int expectedLength)749     private DataHeader readDataHeaderForArray(long elementSize, int expectedLength) {
750         DataHeader dataHeader = readDataHeader();
751         if (dataHeader.size
752                 < (DataHeader.HEADER_SIZE + elementSize * dataHeader.elementsOrVersion)) {
753             throw new DeserializationException("Array header is incorrect.");
754         }
755         if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
756                 && dataHeader.elementsOrVersion != expectedLength) {
757             throw new DeserializationException("Incorrect array length. Expected: " + expectedLength
758                     + ", but got: " + dataHeader.elementsOrVersion + ".");
759         }
760         return dataHeader;
761     }
762 
validateBufferSize(int offset, int size)763     private void validateBufferSize(int offset, int size) {
764         if (mMessage.getData().limit() < offset + size) {
765             throw new DeserializationException("Buffer is smaller than expected.");
766         }
767     }
768 
increaseStackDepth()769     public void increaseStackDepth() {
770         mValidator.increaseStackDepth();
771     }
772 
decreaseStackDepth()773     public void decreaseStackDepth() {
774         mValidator.decreaseStackDepth();
775     }
776 }
777