• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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