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