blob: 033f079816588d6bdbc4fc948362ecb520399840 [file] [log] [blame]
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08001/*
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 */
16package android.bluetooth;
17
18import java.util.ArrayList;
19import java.util.IllegalFormatConversionException;
20import java.util.List;
21import java.util.UUID;
22
23/**
Matthew Xieddf7e472013-03-01 18:41:02 -080024 * Represents a Bluetooth GATT Characteristic
Matthew Xie33ec9842013-04-03 00:29:27 -070025 *
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}.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -080029 */
30public 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 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800125 * Write characteristic including authentication signature
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800126 */
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 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800225 * 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 */
232 public BluetoothGattCharacteristic(UUID uuid, int properties, int permissions) {
233 initCharacteristic(null, uuid, 0, properties, permissions);
234 }
235
236 /**
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800237 * Create a new BluetoothGattCharacteristic
238 * @hide
239 */
240 /*package*/ BluetoothGattCharacteristic(BluetoothGattService service,
241 UUID uuid, int instanceId,
242 int properties, int permissions) {
Matthew Xieddf7e472013-03-01 18:41:02 -0800243 initCharacteristic(service, uuid, instanceId, properties, permissions);
244 }
245
246 private void initCharacteristic(BluetoothGattService service,
247 UUID uuid, int instanceId,
248 int properties, int permissions) {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800249 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 */
268 /*package*/ int getKeySize() {
269 return mKeySize;
270 }
271
272 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800273 * 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
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800278 */
Matthew Xieddf7e472013-03-01 18:41:02 -0800279 public boolean addDescriptor(BluetoothGattDescriptor descriptor) {
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800280 mDescriptors.add(descriptor);
Matthew Xieddf7e472013-03-01 18:41:02 -0800281 descriptor.setCharacteristic(this);
282 return true;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800283 }
284
285 /**
286 * Returns the service this characteristic belongs to.
287 * @return The asscociated service
288 */
289 public BluetoothGattService getService() {
290 return mService;
291 }
292
293 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800294 * Sets the service associated with this device.
295 * @hide
296 */
297 /*package*/ void setService(BluetoothGattService service) {
298 mService = service;
299 }
300
301 /**
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800302 * Returns the UUID of this characteristic
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800303 *
304 * @return UUID of this characteristic
305 */
306 public UUID getUuid() {
307 return mUuid;
308 }
309
310 /**
311 * Returns the instance ID for this characteristic.
312 *
313 * <p>If a remote device offers multiple characteristics with the same UUID,
314 * the instance ID is used to distuinguish between characteristics.
315 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800316 * @return Instance ID of this characteristic
317 */
318 public int getInstanceId() {
319 return mInstance;
320 }
321
322 /**
323 * Returns the properties of this characteristic.
324 *
325 * <p>The properties contain a bit mask of property flags indicating
326 * the features of this characteristic.
327 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800328 * @return Properties of this characteristic
329 */
330 public int getProperties() {
331 return mProperties;
332 }
333
334 /**
335 * Returns the permissions for this characteristic.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800336 *
337 * @return Permissions of this characteristic
338 */
339 public int getPermissions() {
340 return mPermissions;
341 }
342
343 /**
344 * Gets the write type for this characteristic.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800345 *
346 * @return Write type for this characteristic
347 */
348 public int getWriteType() {
349 return mWriteType;
350 }
351
352 /**
353 * Set the write type for this characteristic
354 *
355 * <p>Setting the write type of a characteristic determines how the
356 * {@link BluetoothGatt#writeCharacteristic} function write this
357 * characteristic.
358 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800359 * @param writeType The write type to for this characteristic. Can be one
360 * of:
361 * {@link #WRITE_TYPE_DEFAULT},
362 * {@link #WRITE_TYPE_NO_RESPONSE} or
363 * {@link #WRITE_TYPE_SIGNED}.
364 */
365 public void setWriteType(int writeType) {
366 mWriteType = writeType;
367 }
368
369 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800370 * Set the desired key size.
371 * @hide
372 */
373 public void setKeySize(int keySize) {
374 mKeySize = keySize;
375 }
376
377 /**
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800378 * Returns a list of descriptors for this characteristic.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800379 *
380 * @return Descriptors for this characteristic
381 */
382 public List<BluetoothGattDescriptor> getDescriptors() {
383 return mDescriptors;
384 }
385
386 /**
387 * Returns a descriptor with a given UUID out of the list of
388 * descriptors for this characteristic.
389 *
Matthew Xieddf7e472013-03-01 18:41:02 -0800390 * @return GATT descriptor object or null if no descriptor with the
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800391 * given UUID was found.
392 */
393 public BluetoothGattDescriptor getDescriptor(UUID uuid) {
394 for(BluetoothGattDescriptor descriptor : mDescriptors) {
395 if (descriptor.getUuid().equals(uuid)) {
396 return descriptor;
397 }
398 }
399 return null;
400 }
401
402 /**
403 * Get the stored value for this characteristic.
404 *
405 * <p>This function returns the stored value for this characteristic as
Matthew Xieddf7e472013-03-01 18:41:02 -0800406 * retrieved by calling {@link BluetoothGatt#readCharacteristic}. The cached
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800407 * value of the characteristic is updated as a result of a read characteristic
408 * operation or if a characteristic update notification has been received.
409 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800410 * @return Cached value of the characteristic
411 */
412 public byte[] getValue() {
413 return mValue;
414 }
415
416 /**
417 * Return the stored value of this characteristic.
418 *
419 * <p>The formatType parameter determines how the characteristic value
420 * is to be interpreted. For example, settting formatType to
421 * {@link #FORMAT_UINT16} specifies that the first two bytes of the
422 * characteristic value at the given offset are interpreted to generate the
423 * return value.
424 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800425 * @param formatType The format type used to interpret the characteristic
426 * value.
427 * @param offset Offset at which the integer value can be found.
428 * @return Cached value of the characteristic or null of offset exceeds
429 * value size.
430 */
431 public Integer getIntValue(int formatType, int offset) {
432 if ((offset + getTypeLen(formatType)) > mValue.length) return null;
433
434 switch (formatType) {
435 case FORMAT_UINT8:
436 return unsignedByteToInt(mValue[offset]);
437
438 case FORMAT_UINT16:
439 return unsignedBytesToInt(mValue[offset], mValue[offset+1]);
440
441 case FORMAT_UINT32:
442 return unsignedBytesToInt(mValue[offset], mValue[offset+1],
443 mValue[offset+2], mValue[offset+3]);
444 case FORMAT_SINT8:
445 return unsignedToSigned(unsignedByteToInt(mValue[offset]), 8);
446
447 case FORMAT_SINT16:
448 return unsignedToSigned(unsignedBytesToInt(mValue[offset],
449 mValue[offset+1]), 16);
450
451 case FORMAT_SINT32:
452 return unsignedToSigned(unsignedBytesToInt(mValue[offset],
453 mValue[offset+1], mValue[offset+2], mValue[offset+3]), 32);
454 }
455
456 return null;
457 }
458
459 /**
460 * Return the stored value of this characteristic.
461 * <p>See {@link #getValue} for details.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800462 *
463 * @param formatType The format type used to interpret the characteristic
464 * value.
465 * @param offset Offset at which the float value can be found.
466 * @return Cached value of the characteristic at a given offset or null
467 * if the requested offset exceeds the value size.
468 */
469 public Float getFloatValue(int formatType, int offset) {
470 if ((offset + getTypeLen(formatType)) > mValue.length) return null;
471
472 switch (formatType) {
473 case FORMAT_SFLOAT:
474 return bytesToFloat(mValue[offset], mValue[offset+1]);
475
476 case FORMAT_FLOAT:
477 return bytesToFloat(mValue[offset], mValue[offset+1],
478 mValue[offset+2], mValue[offset+3]);
479 }
480
481 return null;
482 }
483
484 /**
485 * Return the stored value of this characteristic.
486 * <p>See {@link #getValue} for details.
Matthew Xieddf7e472013-03-01 18:41:02 -0800487 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800488 * @param offset Offset at which the string value can be found.
489 * @return Cached value of the characteristic
490 */
491 public String getStringValue(int offset) {
492 if (offset > mValue.length) return null;
493 byte[] strBytes = new byte[mValue.length - offset];
494 for (int i=0; i != (mValue.length-offset); ++i) strBytes[i] = mValue[offset+i];
495 return new String(strBytes);
496 }
497
498 /**
499 * Updates the locally stored value of this characteristic.
500 *
501 * <p>This function modifies the locally stored cached value of this
502 * characteristic. To send the value to the remote device, call
503 * {@link BluetoothGatt#writeCharacteristic} to send the value to the
504 * remote device.
505 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800506 * @param value New value for this characteristic
507 * @return true if the locally stored value has been set, false if the
508 * requested value could not be stored locally.
509 */
510 public boolean setValue(byte[] value) {
511 mValue = value;
512 return true;
513 }
514
515 /**
516 * Set the locally stored value of this characteristic.
517 * <p>See {@link #setValue(byte[])} for details.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800518 *
519 * @param value New value for this characteristic
520 * @param formatType Integer format type used to transform the value parameter
521 * @param offset Offset at which the value should be placed
522 * @return true if the locally stored value has been set
523 */
524 public boolean setValue(int value, int formatType, int offset) {
525 int len = offset + getTypeLen(formatType);
526 if (mValue == null) mValue = new byte[len];
527 if (len > mValue.length) return false;
528
529 switch (formatType) {
530 case FORMAT_SINT8:
531 value = intToSignedBits(value, 8);
532 // Fall-through intended
533 case FORMAT_UINT8:
534 mValue[offset] = (byte)(value & 0xFF);
535 break;
536
537 case FORMAT_SINT16:
538 value = intToSignedBits(value, 16);
539 // Fall-through intended
540 case FORMAT_UINT16:
541 mValue[offset++] = (byte)(value & 0xFF);
542 mValue[offset] = (byte)((value >> 8) & 0xFF);
543 break;
544
545 case FORMAT_SINT32:
546 value = intToSignedBits(value, 32);
547 // Fall-through intended
548 case FORMAT_UINT32:
549 mValue[offset++] = (byte)(value & 0xFF);
550 mValue[offset++] = (byte)((value >> 8) & 0xFF);
Andre Eisenbach3f366602013-03-08 18:42:24 -0800551 mValue[offset++] = (byte)((value >> 16) & 0xFF);
552 mValue[offset] = (byte)((value >> 24) & 0xFF);
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800553 break;
554
555 default:
556 return false;
557 }
558 return true;
559 }
560
561 /**
562 * Set the locally stored value of this characteristic.
563 * <p>See {@link #setValue(byte[])} for details.
Matthew Xieddf7e472013-03-01 18:41:02 -0800564 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800565 * @param mantissa Mantissa for this characteristic
566 * @param exponent exponent value for this characteristic
567 * @param formatType Float format type used to transform the value parameter
568 * @param offset Offset at which the value should be placed
569 * @return true if the locally stored value has been set
570 */
571 public boolean setValue(int mantissa, int exponent, int formatType, int offset) {
572 int len = offset + getTypeLen(formatType);
573 if (mValue == null) mValue = new byte[len];
574 if (len > mValue.length) return false;
575
576 switch (formatType) {
577 case FORMAT_SFLOAT:
578 mantissa = intToSignedBits(mantissa, 12);
579 exponent = intToSignedBits(exponent, 4);
580 mValue[offset++] = (byte)(mantissa & 0xFF);
581 mValue[offset] = (byte)((mantissa >> 8) & 0x0F);
582 mValue[offset] += (byte)((exponent & 0x0F) << 4);
583 break;
584
585 case FORMAT_FLOAT:
586 mantissa = intToSignedBits(mantissa, 24);
587 exponent = intToSignedBits(exponent, 8);
588 mValue[offset++] = (byte)(mantissa & 0xFF);
589 mValue[offset++] = (byte)((mantissa >> 8) & 0xFF);
590 mValue[offset++] = (byte)((mantissa >> 16) & 0xFF);
591 mValue[offset] += (byte)(exponent & 0xFF);
592 break;
593
594 default:
595 return false;
596 }
597
598 return true;
599 }
600
601 /**
602 * Set the locally stored value of this characteristic.
603 * <p>See {@link #setValue(byte[])} for details.
Matthew Xieddf7e472013-03-01 18:41:02 -0800604 *
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800605 * @param value New value for this characteristic
606 * @return true if the locally stored value has been set
607 */
608 public boolean setValue(String value) {
609 mValue = value.getBytes();
610 return true;
611 }
612
613 /**
614 * Returns the size of a give value type.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800615 */
616 private int getTypeLen(int formatType) {
617 return formatType & 0xF;
618 }
619
620 /**
621 * Convert a signed byte to an unsigned int.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800622 */
623 private int unsignedByteToInt(byte b) {
624 return b & 0xFF;
625 }
626
627 /**
628 * Convert signed bytes to a 16-bit unsigned int.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800629 */
630 private int unsignedBytesToInt(byte b0, byte b1) {
631 return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8));
632 }
633
634 /**
635 * Convert signed bytes to a 32-bit unsigned int.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800636 */
637 private int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) {
638 return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8))
639 + (unsignedByteToInt(b2) << 16) + (unsignedByteToInt(b3) << 24);
640 }
641
642 /**
643 * Convert signed bytes to a 16-bit short float value.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800644 */
645 private float bytesToFloat(byte b0, byte b1) {
646 int mantissa = unsignedToSigned(unsignedByteToInt(b0)
647 + ((unsignedByteToInt(b1) & 0x0F) << 8), 12);
648 int exponent = unsignedToSigned(unsignedByteToInt(b1) >> 4, 4);
649 return (float)(mantissa * Math.pow(10, exponent));
650 }
651
652 /**
653 * Convert signed bytes to a 32-bit short float value.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800654 */
655 private float bytesToFloat(byte b0, byte b1, byte b2, byte b3) {
656 int mantissa = unsignedToSigned(unsignedByteToInt(b0)
657 + (unsignedByteToInt(b1) << 8)
658 + (unsignedByteToInt(b2) << 16), 24);
659 return (float)(mantissa * Math.pow(10, b3));
660 }
661
662 /**
663 * Convert an unsigned integer value to a two's-complement encoded
664 * signed value.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800665 */
666 private int unsignedToSigned(int unsigned, int size) {
667 if ((unsigned & (1 << size-1)) != 0) {
668 unsigned = -1 * ((1 << size-1) - (unsigned & ((1 << size-1) - 1)));
669 }
670 return unsigned;
671 }
672
673 /**
674 * Convert an integer into the signed bits of a given length.
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -0800675 */
676 private int intToSignedBits(int i, int size) {
677 if (i < 0) {
678 i = (1 << size-1) + (i & ((1 << size-1) - 1));
679 }
680 return i;
681 }
682}