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