Home | History | Annotate | Download | only in bluetooth
      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      */
    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      */
    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      */
    252     public BluetoothGattCharacteristic(UUID uuid, int instanceId,
    253                                        int properties, int permissions) {
    254         initCharacteristic(null, uuid, instanceId, properties, permissions);
    255     }
    256 
    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      */
    278     public int describeContents() {
    279         return 0;
    280     }
    281 
    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 
    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 deisred key size.
    325      * @hide
    326      */
    327     /*package*/ 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      */
    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      */
    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      */
    362     public BluetoothGattService getService() {
    363         return mService;
    364     }
    365 
    366     /**
    367      * Sets the service associated with this device.
    368      * @hide
    369      */
    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      */
    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      */
    391     public int getInstanceId() {
    392         return mInstance;
    393     }
    394 
    395     /**
    396      * Returns the properties of this characteristic.
    397      *
    398      * <p>The properties contain a bit mask of property flags indicating
    399      * the features of this characteristic.
    400      *
    401      * @return Properties of this characteristic
    402      */
    403     public int getProperties() {
    404         return mProperties;
    405     }
    406 
    407     /**
    408      * Returns the permissions for this characteristic.
    409      *
    410      * @return Permissions of this characteristic
    411      */
    412     public int getPermissions() {
    413         return mPermissions;
    414     }
    415 
    416     /**
    417      * Gets the write type for this characteristic.
    418      *
    419      * @return Write type for this characteristic
    420      */
    421     public int getWriteType() {
    422         return mWriteType;
    423     }
    424 
    425     /**
    426      * Set the write type for this characteristic
    427      *
    428      * <p>Setting the write type of a characteristic determines how the
    429      * {@link BluetoothGatt#writeCharacteristic} function write this
    430      * characteristic.
    431      *
    432      * @param writeType The write type to for this characteristic. Can be one
    433      *                  of:
    434      *                  {@link #WRITE_TYPE_DEFAULT},
    435      *                  {@link #WRITE_TYPE_NO_RESPONSE} or
    436      *                  {@link #WRITE_TYPE_SIGNED}.
    437      */
    438     public void setWriteType(int writeType) {
    439         mWriteType = writeType;
    440     }
    441 
    442     /**
    443      * Set the desired key size.
    444      * @hide
    445      */
    446     public void setKeySize(int keySize) {
    447         mKeySize = keySize;
    448     }
    449 
    450     /**
    451      * Returns a list of descriptors for this characteristic.
    452      *
    453      * @return Descriptors for this characteristic
    454      */
    455     public List<BluetoothGattDescriptor> getDescriptors() {
    456         return mDescriptors;
    457     }
    458 
    459     /**
    460      * Returns a descriptor with a given UUID out of the list of
    461      * descriptors for this characteristic.
    462      *
    463      * @return GATT descriptor object or null if no descriptor with the
    464      *         given UUID was found.
    465      */
    466     public BluetoothGattDescriptor getDescriptor(UUID uuid) {
    467         for(BluetoothGattDescriptor descriptor : mDescriptors) {
    468             if (descriptor.getUuid().equals(uuid)) {
    469                 return descriptor;
    470             }
    471         }
    472         return null;
    473     }
    474 
    475     /**
    476      * Get the stored value for this characteristic.
    477      *
    478      * <p>This function returns the stored value for this characteristic as
    479      * retrieved by calling {@link BluetoothGatt#readCharacteristic}. The cached
    480      * value of the characteristic is updated as a result of a read characteristic
    481      * operation or if a characteristic update notification has been received.
    482      *
    483      * @return Cached value of the characteristic
    484      */
    485     public byte[] getValue() {
    486         return mValue;
    487     }
    488 
    489     /**
    490      * Return the stored value of this characteristic.
    491      *
    492      * <p>The formatType parameter determines how the characteristic value
    493      * is to be interpreted. For example, settting formatType to
    494      * {@link #FORMAT_UINT16} specifies that the first two bytes of the
    495      * characteristic value at the given offset are interpreted to generate the
    496      * return value.
    497      *
    498      * @param formatType The format type used to interpret the characteristic
    499      *                   value.
    500      * @param offset Offset at which the integer value can be found.
    501      * @return Cached value of the characteristic or null of offset exceeds
    502      *         value size.
    503      */
    504     public Integer getIntValue(int formatType, int offset) {
    505         if ((offset + getTypeLen(formatType)) > mValue.length) return null;
    506 
    507         switch (formatType) {
    508             case FORMAT_UINT8:
    509                 return unsignedByteToInt(mValue[offset]);
    510 
    511             case FORMAT_UINT16:
    512                 return unsignedBytesToInt(mValue[offset], mValue[offset+1]);
    513 
    514             case FORMAT_UINT32:
    515                 return unsignedBytesToInt(mValue[offset],   mValue[offset+1],
    516                                           mValue[offset+2], mValue[offset+3]);
    517             case FORMAT_SINT8:
    518                 return unsignedToSigned(unsignedByteToInt(mValue[offset]), 8);
    519 
    520             case FORMAT_SINT16:
    521                 return unsignedToSigned(unsignedBytesToInt(mValue[offset],
    522                                                            mValue[offset+1]), 16);
    523 
    524             case FORMAT_SINT32:
    525                 return unsignedToSigned(unsignedBytesToInt(mValue[offset],
    526                         mValue[offset+1], mValue[offset+2], mValue[offset+3]), 32);
    527         }
    528 
    529         return null;
    530     }
    531 
    532     /**
    533      * Return the stored value of this characteristic.
    534      * <p>See {@link #getValue} for details.
    535      *
    536      * @param formatType The format type used to interpret the characteristic
    537      *                   value.
    538      * @param offset Offset at which the float value can be found.
    539      * @return Cached value of the characteristic at a given offset or null
    540      *         if the requested offset exceeds the value size.
    541      */
    542     public Float getFloatValue(int formatType, int offset) {
    543         if ((offset + getTypeLen(formatType)) > mValue.length) return null;
    544 
    545         switch (formatType) {
    546             case FORMAT_SFLOAT:
    547                 return bytesToFloat(mValue[offset], mValue[offset+1]);
    548 
    549             case FORMAT_FLOAT:
    550                 return bytesToFloat(mValue[offset],   mValue[offset+1],
    551                                     mValue[offset+2], mValue[offset+3]);
    552         }
    553 
    554         return null;
    555     }
    556 
    557     /**
    558      * Return the stored value of this characteristic.
    559      * <p>See {@link #getValue} for details.
    560      *
    561      * @param offset Offset at which the string value can be found.
    562      * @return Cached value of the characteristic
    563      */
    564     public String getStringValue(int offset) {
    565         if (mValue == null || offset > mValue.length) return null;
    566         byte[] strBytes = new byte[mValue.length - offset];
    567         for (int i=0; i != (mValue.length-offset); ++i) strBytes[i] = mValue[offset+i];
    568         return new String(strBytes);
    569     }
    570 
    571     /**
    572      * Updates the locally stored value of this characteristic.
    573      *
    574      * <p>This function modifies the locally stored cached value of this
    575      * characteristic. To send the value to the remote device, call
    576      * {@link BluetoothGatt#writeCharacteristic} to send the value to the
    577      * remote device.
    578      *
    579      * @param value New value for this characteristic
    580      * @return true if the locally stored value has been set, false if the
    581      *              requested value could not be stored locally.
    582      */
    583     public boolean setValue(byte[] value) {
    584         mValue = value;
    585         return true;
    586     }
    587 
    588     /**
    589      * Set the locally stored value of this characteristic.
    590      * <p>See {@link #setValue(byte[])} for details.
    591      *
    592      * @param value New value for this characteristic
    593      * @param formatType Integer format type used to transform the value parameter
    594      * @param offset Offset at which the value should be placed
    595      * @return true if the locally stored value has been set
    596      */
    597     public boolean setValue(int value, int formatType, int offset) {
    598         int len = offset + getTypeLen(formatType);
    599         if (mValue == null) mValue = new byte[len];
    600         if (len > mValue.length) return false;
    601 
    602         switch (formatType) {
    603             case FORMAT_SINT8:
    604                 value = intToSignedBits(value, 8);
    605                 // Fall-through intended
    606             case FORMAT_UINT8:
    607                 mValue[offset] = (byte)(value & 0xFF);
    608                 break;
    609 
    610             case FORMAT_SINT16:
    611                 value = intToSignedBits(value, 16);
    612                 // Fall-through intended
    613             case FORMAT_UINT16:
    614                 mValue[offset++] = (byte)(value & 0xFF);
    615                 mValue[offset] = (byte)((value >> 8) & 0xFF);
    616                 break;
    617 
    618             case FORMAT_SINT32:
    619                 value = intToSignedBits(value, 32);
    620                 // Fall-through intended
    621             case FORMAT_UINT32:
    622                 mValue[offset++] = (byte)(value & 0xFF);
    623                 mValue[offset++] = (byte)((value >> 8) & 0xFF);
    624                 mValue[offset++] = (byte)((value >> 16) & 0xFF);
    625                 mValue[offset] = (byte)((value >> 24) & 0xFF);
    626                 break;
    627 
    628             default:
    629                 return false;
    630         }
    631         return true;
    632     }
    633 
    634     /**
    635      * Set the locally stored value of this characteristic.
    636      * <p>See {@link #setValue(byte[])} for details.
    637      *
    638      * @param mantissa Mantissa for this characteristic
    639      * @param exponent  exponent value for this characteristic
    640      * @param formatType Float format type used to transform the value parameter
    641      * @param offset Offset at which the value should be placed
    642      * @return true if the locally stored value has been set
    643      */
    644     public boolean setValue(int mantissa, int exponent, int formatType, int offset) {
    645         int len = offset + getTypeLen(formatType);
    646         if (mValue == null) mValue = new byte[len];
    647         if (len > mValue.length) return false;
    648 
    649         switch (formatType) {
    650             case FORMAT_SFLOAT:
    651                 mantissa = intToSignedBits(mantissa, 12);
    652                 exponent = intToSignedBits(exponent, 4);
    653                 mValue[offset++] = (byte)(mantissa & 0xFF);
    654                 mValue[offset] = (byte)((mantissa >> 8) & 0x0F);
    655                 mValue[offset] += (byte)((exponent & 0x0F) << 4);
    656                 break;
    657 
    658             case FORMAT_FLOAT:
    659                 mantissa = intToSignedBits(mantissa, 24);
    660                 exponent = intToSignedBits(exponent, 8);
    661                 mValue[offset++] = (byte)(mantissa & 0xFF);
    662                 mValue[offset++] = (byte)((mantissa >> 8) & 0xFF);
    663                 mValue[offset++] = (byte)((mantissa >> 16) & 0xFF);
    664                 mValue[offset] += (byte)(exponent & 0xFF);
    665                 break;
    666 
    667             default:
    668                 return false;
    669         }
    670 
    671         return true;
    672     }
    673 
    674     /**
    675      * Set the locally stored value of this characteristic.
    676      * <p>See {@link #setValue(byte[])} for details.
    677      *
    678      * @param value New value for this characteristic
    679      * @return true if the locally stored value has been set
    680      */
    681     public boolean setValue(String value) {
    682         mValue = value.getBytes();
    683         return true;
    684     }
    685 
    686     /**
    687      * Returns the size of a give value type.
    688      */
    689     private int getTypeLen(int formatType) {
    690         return formatType & 0xF;
    691     }
    692 
    693     /**
    694      * Convert a signed byte to an unsigned int.
    695      */
    696     private int unsignedByteToInt(byte b) {
    697         return b & 0xFF;
    698     }
    699 
    700     /**
    701      * Convert signed bytes to a 16-bit unsigned int.
    702      */
    703     private int unsignedBytesToInt(byte b0, byte b1) {
    704         return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8));
    705     }
    706 
    707     /**
    708      * Convert signed bytes to a 32-bit unsigned int.
    709      */
    710     private int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) {
    711         return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8))
    712              + (unsignedByteToInt(b2) << 16) + (unsignedByteToInt(b3) << 24);
    713     }
    714 
    715     /**
    716      * Convert signed bytes to a 16-bit short float value.
    717      */
    718     private float bytesToFloat(byte b0, byte b1) {
    719         int mantissa = unsignedToSigned(unsignedByteToInt(b0)
    720                         + ((unsignedByteToInt(b1) & 0x0F) << 8), 12);
    721         int exponent = unsignedToSigned(unsignedByteToInt(b1) >> 4, 4);
    722         return (float)(mantissa * Math.pow(10, exponent));
    723     }
    724 
    725     /**
    726      * Convert signed bytes to a 32-bit short float value.
    727      */
    728     private float bytesToFloat(byte b0, byte b1, byte b2, byte b3) {
    729         int mantissa = unsignedToSigned(unsignedByteToInt(b0)
    730                         + (unsignedByteToInt(b1) << 8)
    731                         + (unsignedByteToInt(b2) << 16), 24);
    732         return (float)(mantissa * Math.pow(10, b3));
    733     }
    734 
    735     /**
    736      * Convert an unsigned integer value to a two's-complement encoded
    737      * signed value.
    738      */
    739     private int unsignedToSigned(int unsigned, int size) {
    740         if ((unsigned & (1 << size-1)) != 0) {
    741             unsigned = -1 * ((1 << size-1) - (unsigned & ((1 << size-1) - 1)));
    742         }
    743         return unsigned;
    744     }
    745 
    746     /**
    747      * Convert an integer into the signed bits of a given length.
    748      */
    749     private int intToSignedBits(int i, int size) {
    750         if (i < 0) {
    751             i = (1 << size-1) + (i & ((1 << size-1) - 1));
    752         }
    753         return i;
    754     }
    755 }
    756