blob: 62e3c3eaa85d4cc9fee29d6c9078fcdd44283e8f [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package io.v.android.libs.discovery.ble;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* A handler for responses from a GattServer.
*/
public class BluetoothGattClientCallback extends BluetoothGattCallback {
// We want to ignore the GATT and GAP services, which are 1800 and 1801 respectively.
static final String GATT_AND_GAP_PREFIX = "0000180";
public interface Callback {
void handle(Map<UUID, Map<UUID, byte[]>> services);
}
private Callback callback;
private Map<UUID, Map<UUID, byte[]>> services;
private BluetoothGatt gatt;
private List<BluetoothGattCharacteristic> chars;
private int pos;
BluetoothGattClientCallback(Callback cb) {
callback = cb;
chars = new ArrayList<>();
services = new Hashtable<>();
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
for (BluetoothGattService service : gatt.getServices()) {
// Skip the GATT AND GAP Services.
if (service.getUuid().toString().startsWith(GATT_AND_GAP_PREFIX)) {
continue;
}
services.put(service.getUuid(), new HashMap<UUID, byte[]>());
// We only keep track of the characteristics that can be read.
for (BluetoothGattCharacteristic ch : chars) {
if ((ch.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) != 0) {
chars.add(ch);
}
}
}
pos = 0;
maybeReadNextCharacteristic();
}
// Reads the next characteristic if there is one. Otherwise calls callback and
// closes the gatt connection.
private void maybeReadNextCharacteristic() {
if (pos >= chars.size()) {
gatt.disconnect();
gatt.close();
callback.handle(services);
return;
}
BluetoothGattCharacteristic c = chars.get(pos++);
if (!gatt.readCharacteristic(c)) {
Log.d("vanadium", "Failed to read characteristic " + c.getUuid());
maybeReadNextCharacteristic();
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
UUID serviceUUID = characteristic.getService().getUuid();
services.get(serviceUUID).put(characteristic.getUuid(), characteristic.getValue());
maybeReadNextCharacteristic();
}
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.d("vanadium", "new connections state is " + newState);
this.gatt = gatt;
if (status != BluetoothGatt.GATT_SUCCESS || newState != BluetoothGatt.STATE_CONNECTED) {
Log.d("vanadium", "failed to connect with status " + status + " state" + newState);
gatt.close();
callback.handle(null);
return;
}
gatt.discoverServices();
}
}