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