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      */
BluetoothGattCharacteristic(UUID uuid, int properties, int permissions)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      */
BluetoothGattCharacteristic(BluetoothGattService service, UUID uuid, int instanceId, int properties, int permissions)239     /*package*/ BluetoothGattCharacteristic(BluetoothGattService service,
240                                             UUID uuid, int instanceId,
241                                             int properties, int permissions) {
242         initCharacteristic(service, uuid, instanceId, properties, permissions);
243     }
244 
initCharacteristic(BluetoothGattService service, UUID uuid, int instanceId, int properties, int permissions)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      */
getKeySize()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      */
addDescriptor(BluetoothGattDescriptor descriptor)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      */
getDescriptor(UUID uuid, int instanceId)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      */
getService()302     public BluetoothGattService getService() {
303         return mService;
304     }
305 
306     /**
307      * Sets the service associated with this device.
308      * @hide
309      */
setService(BluetoothGattService service)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      */
getUuid()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      */
getInstanceId()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      */
getProperties()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      */
getPermissions()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      */
getWriteType()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      */
setWriteType(int writeType)378     public void setWriteType(int writeType) {
379         mWriteType = writeType;
380     }
381 
382     /**
383      * Set the desired key size.
384      * @hide
385      */
setKeySize(int keySize)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      */
getDescriptors()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      */
getDescriptor(UUID uuid)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      */
getValue()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      */
getIntValue(int formatType, int offset)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      */
getFloatValue(int formatType, int offset)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      */
getStringValue(int offset)504     public String getStringValue(int offset) {
505         if (mValue == null || 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      */
setValue(byte[] value)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      */
setValue(int value, int formatType, int offset)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      */
setValue(int mantissa, int exponent, int formatType, int offset)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      */
setValue(String value)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      */
getTypeLen(int formatType)629     private int getTypeLen(int formatType) {
630         return formatType & 0xF;
631     }
632 
633     /**
634      * Convert a signed byte to an unsigned int.
635      */
unsignedByteToInt(byte b)636     private int unsignedByteToInt(byte b) {
637         return b & 0xFF;
638     }
639 
640     /**
641      * Convert signed bytes to a 16-bit unsigned int.
642      */
unsignedBytesToInt(byte b0, byte b1)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      */
unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3)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      */
bytesToFloat(byte b0, byte b1)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      */
bytesToFloat(byte b0, byte b1, byte b2, byte b3)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      */
unsignedToSigned(int unsigned, int size)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      */
intToSignedBits(int i, int size)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