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