1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.bluetooth; 17 18 import android.annotation.IntDef; 19 import android.annotation.NonNull; 20 import android.compat.annotation.UnsupportedAppUsage; 21 import android.os.Parcel; 22 import android.os.ParcelUuid; 23 import android.os.Parcelable; 24 25 import java.lang.annotation.Retention; 26 import java.lang.annotation.RetentionPolicy; 27 import java.util.ArrayList; 28 import java.util.List; 29 import java.util.UUID; 30 31 /** 32 * Represents a Bluetooth GATT Characteristic 33 * 34 * <p>A GATT characteristic is a basic data element used to construct a GATT service, {@link 35 * BluetoothGattService}. The characteristic contains a value as well as additional information and 36 * optional GATT descriptors, {@link BluetoothGattDescriptor}. 37 */ 38 public class BluetoothGattCharacteristic implements Parcelable { 39 40 /** Characteristic property: Characteristic is broadcastable. */ 41 public static final int PROPERTY_BROADCAST = 0x01; 42 43 /** Characteristic property: Characteristic is readable. */ 44 public static final int PROPERTY_READ = 0x02; 45 46 /** Characteristic property: Characteristic can be written without response. */ 47 public static final int PROPERTY_WRITE_NO_RESPONSE = 0x04; 48 49 /** Characteristic property: Characteristic can be written. */ 50 public static final int PROPERTY_WRITE = 0x08; 51 52 /** Characteristic property: Characteristic supports notification */ 53 public static final int PROPERTY_NOTIFY = 0x10; 54 55 /** Characteristic property: Characteristic supports indication */ 56 public static final int PROPERTY_INDICATE = 0x20; 57 58 /** Characteristic property: Characteristic supports write with signature */ 59 public static final int PROPERTY_SIGNED_WRITE = 0x40; 60 61 /** Characteristic property: Characteristic has extended properties */ 62 public static final int PROPERTY_EXTENDED_PROPS = 0x80; 63 64 /** Characteristic read permission */ 65 public static final int PERMISSION_READ = 0x01; 66 67 /** Characteristic permission: Allow encrypted read operations */ 68 public static final int PERMISSION_READ_ENCRYPTED = 0x02; 69 70 /** Characteristic permission: Allow reading with person-in-the-middle protection */ 71 public static final int PERMISSION_READ_ENCRYPTED_MITM = 0x04; 72 73 /** Characteristic write permission */ 74 public static final int PERMISSION_WRITE = 0x10; 75 76 /** Characteristic permission: Allow encrypted writes */ 77 public static final int PERMISSION_WRITE_ENCRYPTED = 0x20; 78 79 /** Characteristic permission: Allow encrypted writes with person-in-the-middle protection */ 80 public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 0x40; 81 82 /** Characteristic permission: Allow signed write operations */ 83 public static final int PERMISSION_WRITE_SIGNED = 0x80; 84 85 /** 86 * Characteristic permission: Allow signed write operations with person-in-the-middle protection 87 */ 88 public static final int PERMISSION_WRITE_SIGNED_MITM = 0x100; 89 90 /** @hide */ 91 @Retention(RetentionPolicy.SOURCE) 92 @IntDef( 93 prefix = "WRITE_TYPE_", 94 value = {WRITE_TYPE_DEFAULT, WRITE_TYPE_NO_RESPONSE, WRITE_TYPE_SIGNED}) 95 public @interface WriteType {} 96 97 /** Write characteristic, requesting acknowledgement by the remote device */ 98 public static final int WRITE_TYPE_DEFAULT = 0x02; 99 100 /** Write characteristic without requiring a response by the remote device */ 101 public static final int WRITE_TYPE_NO_RESPONSE = 0x01; 102 103 /** Write characteristic including authentication signature */ 104 public static final int WRITE_TYPE_SIGNED = 0x04; 105 106 /** Characteristic value format type uint8 */ 107 public static final int FORMAT_UINT8 = 0x11; 108 109 /** Characteristic value format type uint16 */ 110 public static final int FORMAT_UINT16 = 0x12; 111 112 /** Characteristic value format type uint32 */ 113 public static final int FORMAT_UINT32 = 0x14; 114 115 /** Characteristic value format type sint8 */ 116 public static final int FORMAT_SINT8 = 0x21; 117 118 /** Characteristic value format type sint16 */ 119 public static final int FORMAT_SINT16 = 0x22; 120 121 /** Characteristic value format type sint32 */ 122 public static final int FORMAT_SINT32 = 0x24; 123 124 /** Characteristic value format type sfloat (16-bit float) */ 125 public static final int FORMAT_SFLOAT = 0x32; 126 127 /** Characteristic value format type float (32-bit float) */ 128 public static final int FORMAT_FLOAT = 0x34; 129 130 /** 131 * The UUID of this characteristic. 132 * 133 * @hide 134 */ 135 protected UUID mUuid; 136 137 /** 138 * Instance ID for this characteristic. 139 * 140 * @hide 141 */ 142 @UnsupportedAppUsage protected int mInstance; 143 144 /** 145 * Characteristic properties. 146 * 147 * @hide 148 */ 149 protected int mProperties; 150 151 /** 152 * Characteristic permissions. 153 * 154 * @hide 155 */ 156 protected int mPermissions; 157 158 /** 159 * Key size (default = 16). 160 * 161 * @hide 162 */ 163 protected int mKeySize = 16; 164 165 /** 166 * Write type for this characteristic. 167 * 168 * @hide 169 */ 170 protected @WriteType int mWriteType; 171 172 /** 173 * Back-reference to the service this characteristic belongs to. 174 * 175 * @hide 176 */ 177 @UnsupportedAppUsage protected BluetoothGattService mService; 178 179 /** 180 * The cached value of this characteristic. 181 * 182 * @hide 183 */ 184 protected byte[] mValue; 185 186 /** List of descriptors included in this characteristic. */ 187 protected List<BluetoothGattDescriptor> mDescriptors; 188 189 /** 190 * Create a new BluetoothGattCharacteristic. 191 * 192 * @param uuid The UUID for this characteristic 193 * @param properties Properties of this characteristic 194 * @param permissions Permissions for this characteristic 195 */ BluetoothGattCharacteristic(UUID uuid, int properties, int permissions)196 public BluetoothGattCharacteristic(UUID uuid, int properties, int permissions) { 197 initCharacteristic(null, uuid, 0, properties, permissions); 198 } 199 200 /** 201 * Create a new BluetoothGattCharacteristic 202 * 203 * @hide 204 */ BluetoothGattCharacteristic( BluetoothGattService service, UUID uuid, int instanceId, int properties, int permissions)205 /*package*/ BluetoothGattCharacteristic( 206 BluetoothGattService service, 207 UUID uuid, 208 int instanceId, 209 int properties, 210 int permissions) { 211 initCharacteristic(service, uuid, instanceId, properties, permissions); 212 } 213 214 /** 215 * Create a new BluetoothGattCharacteristic 216 * 217 * @hide 218 */ BluetoothGattCharacteristic(UUID uuid, int instanceId, int properties, int permissions)219 public BluetoothGattCharacteristic(UUID uuid, int instanceId, int properties, int permissions) { 220 initCharacteristic(null, uuid, instanceId, properties, permissions); 221 } 222 initCharacteristic( BluetoothGattService service, UUID uuid, int instanceId, int properties, int permissions)223 private void initCharacteristic( 224 BluetoothGattService service, 225 UUID uuid, 226 int instanceId, 227 int properties, 228 int permissions) { 229 mUuid = uuid; 230 mInstance = instanceId; 231 mProperties = properties; 232 mPermissions = permissions; 233 mService = service; 234 mValue = null; 235 mDescriptors = new ArrayList<>(); 236 237 if ((mProperties & PROPERTY_WRITE_NO_RESPONSE) != 0) { 238 mWriteType = WRITE_TYPE_NO_RESPONSE; 239 } else { 240 mWriteType = WRITE_TYPE_DEFAULT; 241 } 242 } 243 244 @Override describeContents()245 public int describeContents() { 246 return 0; 247 } 248 249 @Override writeToParcel(Parcel out, int flags)250 public void writeToParcel(Parcel out, int flags) { 251 (new ParcelUuid(mUuid)).writeToParcel(out, flags); 252 out.writeInt(mInstance); 253 out.writeInt(mProperties); 254 out.writeInt(mPermissions); 255 out.writeInt(mKeySize); 256 out.writeInt(mWriteType); 257 out.writeTypedList(mDescriptors); 258 } 259 260 public static final @NonNull Creator<BluetoothGattCharacteristic> CREATOR = 261 new Creator<>() { 262 public BluetoothGattCharacteristic createFromParcel(Parcel in) { 263 return new BluetoothGattCharacteristic(in); 264 } 265 266 public BluetoothGattCharacteristic[] newArray(int size) { 267 return new BluetoothGattCharacteristic[size]; 268 } 269 }; 270 BluetoothGattCharacteristic(Parcel in)271 private BluetoothGattCharacteristic(Parcel in) { 272 mUuid = ParcelUuid.CREATOR.createFromParcel(in).getUuid(); 273 mInstance = in.readInt(); 274 mProperties = in.readInt(); 275 mPermissions = in.readInt(); 276 mKeySize = in.readInt(); 277 mWriteType = in.readInt(); 278 279 mDescriptors = in.createTypedArrayList(BluetoothGattDescriptor.CREATOR); 280 for (BluetoothGattDescriptor desc : mDescriptors) { 281 desc.setCharacteristic(this); 282 } 283 } 284 285 /** 286 * Returns the desired key size. 287 * 288 * @hide 289 */ getKeySize()290 public int getKeySize() { 291 return mKeySize; 292 } 293 294 /** 295 * Adds a descriptor to this characteristic. 296 * 297 * @param descriptor Descriptor to be added to this characteristic. 298 * @return true, if the descriptor was added to the characteristic 299 */ addDescriptor(BluetoothGattDescriptor descriptor)300 public boolean addDescriptor(BluetoothGattDescriptor descriptor) { 301 mDescriptors.add(descriptor); 302 descriptor.setCharacteristic(this); 303 return true; 304 } 305 306 /** 307 * Get a descriptor by UUID and instance id. 308 * 309 * @hide 310 */ getDescriptor(UUID uuid, int instanceId)311 /*package*/ BluetoothGattDescriptor getDescriptor(UUID uuid, int instanceId) { 312 for (BluetoothGattDescriptor descriptor : mDescriptors) { 313 if (descriptor.getUuid().equals(uuid) && descriptor.getInstanceId() == instanceId) { 314 return descriptor; 315 } 316 } 317 return null; 318 } 319 320 /** 321 * Returns the service this characteristic belongs to. 322 * 323 * @return The associated service 324 */ getService()325 public BluetoothGattService getService() { 326 return mService; 327 } 328 329 /** 330 * Sets the service associated with this device. 331 * 332 * @hide 333 */ 334 @UnsupportedAppUsage setService(BluetoothGattService service)335 /*package*/ void setService(BluetoothGattService service) { 336 mService = service; 337 } 338 339 /** 340 * Returns the UUID of this characteristic 341 * 342 * @return UUID of this characteristic 343 */ getUuid()344 public UUID getUuid() { 345 return mUuid; 346 } 347 348 /** 349 * Returns the instance ID for this characteristic. 350 * 351 * <p>If a remote device offers multiple characteristics with the same UUID, the instance ID is 352 * used to distinguish between characteristics. 353 * 354 * @return Instance ID of this characteristic 355 */ getInstanceId()356 public int getInstanceId() { 357 return mInstance; 358 } 359 360 /** 361 * Force the instance ID. 362 * 363 * @hide 364 */ setInstanceId(int instanceId)365 public void setInstanceId(int instanceId) { 366 mInstance = instanceId; 367 } 368 369 /** 370 * Returns the properties of this characteristic. 371 * 372 * <p>The properties contain a bit mask of property flags indicating the features of this 373 * characteristic. 374 * 375 * @return Properties of this characteristic 376 */ getProperties()377 public int getProperties() { 378 return mProperties; 379 } 380 381 /** 382 * Returns the permissions for this characteristic. 383 * 384 * @return Permissions of this characteristic 385 */ getPermissions()386 public int getPermissions() { 387 return mPermissions; 388 } 389 390 /** 391 * Gets the write type for this characteristic. 392 * 393 * @return Write type for this characteristic 394 */ getWriteType()395 public @WriteType int getWriteType() { 396 return mWriteType; 397 } 398 399 /** 400 * Set the write type for this characteristic 401 * 402 * <p>Setting the write type of a characteristic determines how the {@link 403 * BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} function write 404 * this characteristic. 405 * 406 * @param writeType The write type to for this characteristic. 407 */ setWriteType(@riteType int writeType)408 public void setWriteType(@WriteType int writeType) { 409 mWriteType = writeType; 410 } 411 412 /** 413 * Set the desired key size. 414 * 415 * @hide 416 */ 417 @UnsupportedAppUsage setKeySize(int keySize)418 public void setKeySize(int keySize) { 419 mKeySize = keySize; 420 } 421 422 /** 423 * Returns a list of descriptors for this characteristic. 424 * 425 * @return Descriptors for this characteristic 426 */ getDescriptors()427 public List<BluetoothGattDescriptor> getDescriptors() { 428 return mDescriptors; 429 } 430 431 /** 432 * Returns a descriptor with a given UUID out of the list of descriptors for this 433 * characteristic. 434 * 435 * @return GATT descriptor object or null if no descriptor with the given UUID was found. 436 */ getDescriptor(UUID uuid)437 public BluetoothGattDescriptor getDescriptor(UUID uuid) { 438 for (BluetoothGattDescriptor descriptor : mDescriptors) { 439 if (descriptor.getUuid().equals(uuid)) { 440 return descriptor; 441 } 442 } 443 return null; 444 } 445 446 /** 447 * Get the stored value for this characteristic. 448 * 449 * <p>This function returns the stored value for this characteristic as retrieved by calling 450 * {@link BluetoothGatt#readCharacteristic}. The cached value of the characteristic is updated 451 * as a result of a read characteristic operation or if a characteristic update notification has 452 * been received. 453 * 454 * @return Cached value of the characteristic 455 * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} instead 456 */ 457 @Deprecated getValue()458 public byte[] getValue() { 459 return mValue; 460 } 461 462 /** 463 * Return the stored value of this characteristic. 464 * 465 * <p>The formatType parameter determines how the characteristic value is to be interpreted. For 466 * example, setting formatType to {@link #FORMAT_UINT16} specifies that the first two bytes of 467 * the characteristic value at the given offset are interpreted to generate the return value. 468 * 469 * @param formatType The format type used to interpret the characteristic value. 470 * @param offset Offset at which the integer value can be found. 471 * @return Cached value of the characteristic or null of offset exceeds value size. 472 * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get 473 * the characteristic value 474 */ 475 @Deprecated getIntValue(int formatType, int offset)476 public Integer getIntValue(int formatType, int offset) { 477 if ((offset + getTypeLen(formatType)) > mValue.length) return null; 478 479 switch (formatType) { 480 case FORMAT_UINT8: 481 return unsignedByteToInt(mValue[offset]); 482 483 case FORMAT_UINT16: 484 return unsignedBytesToInt(mValue[offset], mValue[offset + 1]); 485 486 case FORMAT_UINT32: 487 return unsignedBytesToInt( 488 mValue[offset], mValue[offset + 1], mValue[offset + 2], mValue[offset + 3]); 489 case FORMAT_SINT8: 490 return unsignedToSigned(unsignedByteToInt(mValue[offset]), 8); 491 492 case FORMAT_SINT16: 493 return unsignedToSigned(unsignedBytesToInt(mValue[offset], mValue[offset + 1]), 16); 494 495 case FORMAT_SINT32: 496 return unsignedToSigned( 497 unsignedBytesToInt( 498 mValue[offset], 499 mValue[offset + 1], 500 mValue[offset + 2], 501 mValue[offset + 3]), 502 32); 503 } 504 505 return null; 506 } 507 508 /** 509 * Return the stored value of this characteristic. 510 * 511 * <p>See {@link #getValue} for details. 512 * 513 * @param formatType The format type used to interpret the characteristic value. 514 * @param offset Offset at which the float value can be found. 515 * @return Cached value of the characteristic at a given offset or null if the requested offset 516 * exceeds the value size. 517 * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get 518 * the characteristic value 519 */ 520 @Deprecated getFloatValue(int formatType, int offset)521 public Float getFloatValue(int formatType, int offset) { 522 if ((offset + getTypeLen(formatType)) > mValue.length) return null; 523 524 switch (formatType) { 525 case FORMAT_SFLOAT: 526 return bytesToFloat(mValue[offset], mValue[offset + 1]); 527 528 case FORMAT_FLOAT: 529 return bytesToFloat( 530 mValue[offset], mValue[offset + 1], mValue[offset + 2], mValue[offset + 3]); 531 } 532 533 return null; 534 } 535 536 /** 537 * Return the stored value of this characteristic. 538 * 539 * <p>See {@link #getValue} for details. 540 * 541 * @param offset Offset at which the string value can be found. 542 * @return Cached value of the characteristic 543 * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get 544 * the characteristic value 545 */ 546 @Deprecated getStringValue(int offset)547 public String getStringValue(int offset) { 548 if (mValue == null || offset > mValue.length) return null; 549 byte[] strBytes = new byte[mValue.length - offset]; 550 for (int i = 0; i != (mValue.length - offset); ++i) strBytes[i] = mValue[offset + i]; 551 return new String(strBytes); 552 } 553 554 /** 555 * Updates the locally stored value of this characteristic. 556 * 557 * <p>This function modifies the locally stored cached value of this characteristic. To send the 558 * value to the remote device, call {@link BluetoothGatt#writeCharacteristic} to send the value 559 * to the remote device. 560 * 561 * @param value New value for this characteristic 562 * @return true if the locally stored value has been set, false if the requested value could not 563 * be stored locally. 564 * @deprecated Pass the characteristic value directly into {@link 565 * BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} 566 */ 567 @Deprecated setValue(byte[] value)568 public boolean setValue(byte[] value) { 569 mValue = value; 570 return true; 571 } 572 573 /** 574 * Set the locally stored value of this characteristic. 575 * 576 * <p>See {@link #setValue(byte[])} for details. 577 * 578 * @param value New value for this characteristic 579 * @param formatType Integer format type used to transform the value parameter 580 * @param offset Offset at which the value should be placed 581 * @return true if the locally stored value has been set 582 * @deprecated Pass the characteristic value directly into {@link 583 * BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} 584 */ 585 @Deprecated setValue(int value, int formatType, int offset)586 public boolean setValue(int value, int formatType, int offset) { 587 int len = offset + getTypeLen(formatType); 588 if (mValue == null) mValue = new byte[len]; 589 if (len > mValue.length) return false; 590 591 switch (formatType) { 592 case FORMAT_SINT8: 593 value = intToSignedBits(value, 8); 594 // Fall-through intended 595 case FORMAT_UINT8: 596 mValue[offset] = (byte) (value & 0xFF); 597 break; 598 599 case FORMAT_SINT16: 600 value = intToSignedBits(value, 16); 601 // Fall-through intended 602 case FORMAT_UINT16: 603 mValue[offset++] = (byte) (value & 0xFF); 604 mValue[offset] = (byte) ((value >> 8) & 0xFF); 605 break; 606 607 case FORMAT_SINT32: 608 value = intToSignedBits(value, 32); 609 // Fall-through intended 610 case FORMAT_UINT32: 611 mValue[offset++] = (byte) (value & 0xFF); 612 mValue[offset++] = (byte) ((value >> 8) & 0xFF); 613 mValue[offset++] = (byte) ((value >> 16) & 0xFF); 614 mValue[offset] = (byte) ((value >> 24) & 0xFF); 615 break; 616 617 default: 618 return false; 619 } 620 return true; 621 } 622 623 /** 624 * Set the locally stored value of this characteristic. 625 * 626 * <p>See {@link #setValue(byte[])} for details. 627 * 628 * @param mantissa Mantissa for this characteristic 629 * @param exponent exponent value for this characteristic 630 * @param formatType Float format type used to transform the value parameter 631 * @param offset Offset at which the value should be placed 632 * @return true if the locally stored value has been set 633 * @deprecated Pass the characteristic value directly into {@link 634 * BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} 635 */ 636 @Deprecated setValue(int mantissa, int exponent, int formatType, int offset)637 public boolean setValue(int mantissa, int exponent, int formatType, int offset) { 638 int len = offset + getTypeLen(formatType); 639 if (mValue == null) mValue = new byte[len]; 640 if (len > mValue.length) return false; 641 642 switch (formatType) { 643 case FORMAT_SFLOAT: 644 mantissa = intToSignedBits(mantissa, 12); 645 exponent = intToSignedBits(exponent, 4); 646 mValue[offset++] = (byte) (mantissa & 0xFF); 647 mValue[offset] = (byte) ((mantissa >> 8) & 0x0F); 648 mValue[offset] += (byte) ((exponent & 0x0F) << 4); 649 break; 650 651 case FORMAT_FLOAT: 652 mantissa = intToSignedBits(mantissa, 24); 653 exponent = intToSignedBits(exponent, 8); 654 mValue[offset++] = (byte) (mantissa & 0xFF); 655 mValue[offset++] = (byte) ((mantissa >> 8) & 0xFF); 656 mValue[offset++] = (byte) ((mantissa >> 16) & 0xFF); 657 mValue[offset] += (byte) (exponent & 0xFF); 658 break; 659 660 default: 661 return false; 662 } 663 664 return true; 665 } 666 667 /** 668 * Set the locally stored value of this characteristic. 669 * 670 * <p>See {@link #setValue(byte[])} for details. 671 * 672 * @param value New value for this characteristic 673 * @return true if the locally stored value has been set 674 * @deprecated Pass the characteristic value directly into {@link 675 * BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} 676 */ 677 @Deprecated setValue(String value)678 public boolean setValue(String value) { 679 mValue = value.getBytes(); 680 return true; 681 } 682 683 /** Returns the size of a give value type. */ getTypeLen(int formatType)684 private static int getTypeLen(int formatType) { 685 return formatType & 0xF; 686 } 687 688 /** Convert a signed byte to an unsigned int. */ unsignedByteToInt(byte b)689 private static int unsignedByteToInt(byte b) { 690 return b & 0xFF; 691 } 692 693 /** Convert signed bytes to a 16-bit unsigned int. */ unsignedBytesToInt(byte b0, byte b1)694 private static int unsignedBytesToInt(byte b0, byte b1) { 695 return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8)); 696 } 697 698 /** Convert signed bytes to a 32-bit unsigned int. */ unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3)699 private static int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) { 700 return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8)) 701 + (unsignedByteToInt(b2) << 16) 702 + (unsignedByteToInt(b3) << 24); 703 } 704 705 /** Convert signed bytes to a 16-bit short float value. */ bytesToFloat(byte b0, byte b1)706 private static float bytesToFloat(byte b0, byte b1) { 707 int mantissa = 708 unsignedToSigned(unsignedByteToInt(b0) + ((unsignedByteToInt(b1) & 0x0F) << 8), 12); 709 int exponent = unsignedToSigned(unsignedByteToInt(b1) >> 4, 4); 710 return (float) (mantissa * Math.pow(10, exponent)); 711 } 712 713 /** Convert signed bytes to a 32-bit short float value. */ bytesToFloat(byte b0, byte b1, byte b2, byte b3)714 private static float bytesToFloat(byte b0, byte b1, byte b2, byte b3) { 715 int mantissa = 716 unsignedToSigned( 717 unsignedByteToInt(b0) 718 + (unsignedByteToInt(b1) << 8) 719 + (unsignedByteToInt(b2) << 16), 720 24); 721 return (float) (mantissa * Math.pow(10, b3)); 722 } 723 724 /** Convert an unsigned integer value to a two's-complement encoded signed value. */ unsignedToSigned(int unsigned, int size)725 private static int unsignedToSigned(int unsigned, int size) { 726 if ((unsigned & (1 << (size - 1))) != 0) { 727 unsigned = -1 * ((1 << (size - 1)) - (unsigned & ((1 << (size - 1)) - 1))); 728 } 729 return unsigned; 730 } 731 732 /** Convert an integer into the signed bits of a given length. */ intToSignedBits(int i, int size)733 private static int intToSignedBits(int i, int size) { 734 if (i < 0) { 735 i = (1 << (size - 1)) + (i & ((1 << (size - 1)) - 1)); 736 } 737 return i; 738 } 739 } 740