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