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