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