这里我们以android 5.0来讲,当两个设备通过HOGP建立连接后,双方可以通过gatt read/write 读/写相关的特性值,
这里以write为例子,例如在APK里面调用如下的API接口,
framework/base/core/java/android/bluetooth/BluetoothGatt.java
/**
*
Writes a given characteristic and its values to the associated remote device.
*
* <p>Once the write operation has been completed, the
* {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
* reporting the result of the operation.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param characteristic Characteristic to write on the remote device
* @return true, if the write operation was initiated successfully
*/
public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
&& (characteristic.getProperties() &
BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;
if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false;
BluetoothGattService service = characteristic.getService();
if (service == null) return false;
BluetoothDevice device = service.getDevice();
if (device == null) return false;
synchronized(mDeviceBusy) {
if (mDeviceBusy) return false;
mDeviceBusy = true;
}
try {
mService.
writeCharacteristic(mClientIf, device.getAddress(),
service.getType(), service.getInstanceId(),
new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
new ParcelUuid(characteristic.getUuid()),
characteristic.getWriteType(), AUTHENTICATION_NONE,
characteristic.getValue());
} catch (RemoteException e) {
Log.e(TAG,"",e);
mDeviceBusy = false;
return false;
}
return true;
}
mService为
IBluetoothGatt mService的一个接口,那么它是在哪里实现的呢?
它是在package/app/bluetooth/src/com/android/bluetooth/GattService.java里面实现的,如下:
/**
* Handlers for incoming service calls
*/
private static class
BluetoothGattBinder extends
IBluetoothGatt.Stub implements IProfileServiceBinder {
private GattService mService;
那么就会调用
BluetoothGattBinder 的writeCharacteristic的方法,如下:
public void
writeCharacteristic(int clientIf, String address, int srvcType,
int srvcInstanceId, ParcelUuid srvcId,
int charInstanceId, ParcelUuid charId,
int writeType, int authReq, byte[] value) {
GattService
service = getService();
if (service == null) return;
service.
writeCharacteristic(clientIf, address, srvcType, srvcInstanceId,
srvcId.getUuid(), charInstanceId,
charId.getUuid(), writeType, authReq,
value);
}
那么会继续在调用GattService里面的
writeCharacteristic
方法,如下:
void writeCharacteristic(int clientIf, String address, int srvcType,
int srvcInstanceId, UUID srvcUuid,
int charInstanceId, UUID charUuid, int writeType,
int authReq, byte[] value) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (isHidUuid(charUuid)) enforcePrivilegedPermission();
if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address);
if (mReliableQueue.contains(address))
writeType = 3; //
Prepared write
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (connId != null)
gattClientWriteCharacteristicNative(connId, srvcType,
srvcInstanceId, srvcUuid.getLeastSignificantBits(),
srvcUuid.getMostSignificantBits(), charInstanceId,
charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(),
writeType, authReq, value);
else
Log.e(TAG, "writeCharacteristic() - No connection for " + address + "...");
}
接下来就会调用JNI的native方法,
gattClientWriteCharacteristicNative,如下:
它是在package/app/bluetooth/jni/
com_android_bluetooth_gatt.cpp
static void
gattClientWriteCharacteristicNative(JNIEnv* env, jobject object,
jint conn_id, jint service_type, jint service_id_inst_id,
jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
jint char_id_inst_id,
jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
jint write_type, jint auth_req, jbyteArray value)
{
if (!sGattIf) return;
if (value == NULL) {
warn("gattClientWriteCharacteristicNative() ignoring NULL array");
return;
}
btgatt_srvc_id_t srvc_id;
srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
btgatt_gatt_id_t char_id;
char_id.inst_id = (uint8_t) char_id_inst_id;
set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
uint16_t len = (uint16_t) env->GetArrayLength(value);
jbyte *p_value = env->GetByteArrayElements(value, NULL);
if (p_value == NULL) return;
sGattIf->client->
write_characteristic(conn_id, &srvc_id, &char_id,
write_type, len, auth_req, (char*)p_value);
env->ReleaseByteArrayElements(value, p_value, 0);
}
JNI的这个接口会继续通过
sGattIf->client的接口调用HAL层相关接口,接口定义如下:
在文件hardware/libhardware/include/hardware/bt_gatt_client.h文件里面,
/** Represents the standard BT-GATT client interface. */
typedef struct {
/** Registers a GATT client application with the stack */
bt_status_t (*register_client)( bt_uuid_t *uuid );
/** Unregister a client application from the stack */
bt_status_t (*unregister_client)(int client_if );
/** Start or stop LE device scanning */
bt_status_t (*scan)( bool start );
/** Create a connection to a remote LE or dual-mode device */
bt_status_t (*connect)( int client_if, const bt_bdaddr_t *bd_addr,
bool is_direct, int transport );
/** Disconnect a remote device or cancel a pending connection */
bt_status_t (*disconnect)( int client_if, const bt_bdaddr_t *bd_addr,
int conn_id);
/** Start or stop advertisements to listen for incoming connections */
bt_status_t (*listen)(int client_if, bool start);
/** Clear the attribute cache for a given device */
bt_status_t (*refresh)( int client_if, const bt_bdaddr_t *bd_addr );
/**
* Enumerate all GATT services on a connected device.
* Optionally, the results can be filtered for a given UUID.
*/
bt_status_t (*search_service)(int conn_id, bt_uuid_t *filter_uuid );
/**
* Enumerate included services for a given service.
* Set start_incl_srvc_id to NULL to get the first included service.
*/
bt_status_t (*get_included_service)( int conn_id, btgatt_srvc_id_t *srvc_id,
btgatt_srvc_id_t *start_incl_srvc_id);
/**
* Enumerate characteristics for a given service.
* Set start_char_id to NULL to get the first characteristic.
*/
bt_status_t (*get_characteristic)( int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *start_char_id);
/**
* Enumerate descriptors for a given characteristic.
* Set start_descr_id to NULL to get the first descriptor.
*/
bt_status_t (*get_descriptor)( int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
btgatt_gatt_id_t *start_descr_id);
/**
Read a characteristic on a remote device */
bt_status_t (*
read_characteristic)( int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
int auth_req );
/**
Write a remote characteristic */
bt_status_t (*
write_characteristic)(int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
int write_type, int len, int auth_req,
char* p_value);
/** Read the descriptor for a given characteristic */
bt_status_t (*read_descriptor)(int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
btgatt_gatt_id_t *descr_id, int auth_req);
/** Write a remote descriptor for a given characteristic */
bt_status_t (*write_descriptor)( int conn_id,
btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id,
btgatt_gatt_id_t *descr_id, int write_type, int len,
int auth_req, char* p_value);
/** Execute a prepared write operation */
bt_status_t (*execute_write)(int conn_id, int execute);
/**
* Register to receive notifications or indications for a given
* characteristic
*/
bt_status_t (*register_for_notification)( int client_if,
const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
btgatt_gatt_id_t *char_id);
/** Deregister a previous request for notifications/indications */
bt_status_t (*deregister_for_notification)( int client_if,
const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
btgatt_gatt_id_t *char_id);
/** Request RSSI for a given remote device */
bt_status_t (*read_remote_rssi)( int client_if, const bt_bdaddr_t *bd_addr);
/** Setup scan filter params */
bt_status_t (*scan_filter_param_setup)(btgatt_filt_param_setup_t filt_param);
/** Configure a scan filter condition */
bt_status_t (*scan_filter_add_remove)(int client_if, int action, int filt_type,
int filt_index, int company_id,
int company_id_mask, const bt_uuid_t *p_uuid,
const bt_uuid_t *p_uuid_mask, const bt_bdaddr_t *bd_addr,
char addr_type, int data_len, char* p_data, int mask_len,
char* p_mask);
/** Clear all scan filter conditions for specific filter index*/
bt_status_t (*scan_filter_clear)(int client_if, int filt_index);
/** Enable / disable scan filter feature*/
bt_status_t (*scan_filter_enable)(int client_if, bool enable);
/** Determine the type of the remote device (LE, BR/EDR, Dual-mode) */
int (*get_device_type)( const bt_bdaddr_t *bd_addr );
/** Set the advertising data or scan response data */
bt_status_t (*set_adv_data)(int client_if, bool set_scan_rsp, bool include_name,
bool include_txpower, int min_interval, int max_interval, int appearance,
uint16_t manufacturer_len, char* manufacturer_data,
uint16_t service_data_len, char* service_data,
uint16_t service_uuid_len, char* service_uuid);
/** Configure the MTU for a given connection */
bt_status_t (*configure_mtu)(int conn_id, int mtu);
/** Request a connection parameter update */
bt_status_t (*conn_parameter_update)(const bt_bdaddr_t *bd_addr, int min_interval,
int max_interval, int latency, int timeout);
/** Sets the LE scan interval and window in units of N*0.625 msec */
bt_status_t (*set_scan_parameters)(int client_if, int scan_interval, int scan_window);
/* Setup the parameters as per spec, user manual specified values and enable multi ADV */
bt_status_t (*multi_adv_enable)(int client_if, int min_interval,int max_interval,int adv_type,
int chnl_map, int tx_power, int timeout_s);
/* Update the parameters as per spec, user manual specified values and restart multi ADV */
bt_status_t (*multi_adv_update)(int client_if, int min_interval,int max_interval,int adv_type,
int chnl_map, int tx_power, int timeout_s); </