一、分析
BluetoothHeadset
VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV
HeadsetStateMachine
Pending
Connected
AudioOn
MultiHFPending
processUnknownAt
com_android_bluetooth_hfp.cpp
sBluetoothHfpCallbacks //BT_PROFILE_HANDSFREE_ID
unknown_at_callback
system/bt/btif/src/bluetooth.cc
btif_hf.cc
case BTA_AG_AT_UNAT_EVT:
HAL_CBACK(bt_hf_callbacks, unknown_at_cmd_cb, p_data->val.str, &btif_hf_cb[idx].connected_bda);
bta_ag_cmd.cc
bta_ag_at_err_cback
bta_ag_at.cc
bta_ag_at_parse
bta_ag_process_at
bta_ag_act.cc
bta_ag_rfc_data //Read and process data from RFCOMM
[ 357.354523] input: alibaba as /devices/virtual/misc/uhid/0005:005D:0001.0002/input/input4
[ 357.355372] keychord: using input dev alibaba for fevent
[ 357.355918] hid-generic 0005:005D:0001.0002: input,hidraw1: BLUETOOTH HID v0.00 Keyboard [alibaba] on
[ 363.780095] healthd: battery l=96 v=8392 t=18.8 h=2 st=2 chg=u
[ 372.013850] healthd: battery l=97 v=8392 t=18.8 h=2 st=2 chg=u
[ 375.564042] input: alibaba as /devices/virtual/misc/uhid/0005:005D:0001.0003/input/input5
[ 375.565919] keychord: using input dev alibaba for fevent
[ 375.567800] hid-generic 0005:005D:0001.0003: input,hidraw1: BLUETOOTH HID v0.00 Keyboard [alibaba] on
bt_btif : bta_ag_hdl_event: p_scb 0x69cda250
bt_btif : bta_ag_rfc_data: AT+IPHONEACCEV received, not coming out of sniff
bt_btif : bta_ag_rfc_data: AT+IPHONEACCEV received, not setting idle
bt_btif : btif_hf_upstreams_evt: event=BTA_AG_AT_UNAT_EVT
bt_btif : HAL bt_hf_callbacks->UnknownAtCallback
HFP(Hands-free Profile)和HSP(Headset Profile)
HSP仅实现了最基本的通话操作:接听电话、挂断电话、调节音量、声音在手机/蓝牙耳机之间切换。
HFP在功能上是对HSP的扩展,除了上述功能以外,还包括控制三方通话、来电拒接、耳机端来电显示等高级功能,不过实现的方式,如用于控制的AT CMD完全不一样。
btif_hf_get_interface //BT_PROFILE_HANDSFREE_ID
BLE分为三部分:Service,Characteristic,Descriptor。这三部分都用UUID作为唯一标识符。UUID为这种格式:00002a19-0000-1000-8000-00805f9b34fb。比如有3个Service,那么就有三个不同的UUID与Service对应。这些UUID都写在硬件里,我们通过BLE提供的API可以读取到。
Service
一个设备包含很多service,类似多个功能模块,每个service下面有多个characteristic,
Characteristic
特征值,一个特征值包含一个value和多个Descriptor。它其实就相当于一个bundle。我们读取数据和写入数据都依靠它来传递内容。
Descriptor
描述,用来描述charateristic的属性。
二、代码
1.连接
//mBluetoothDevice: 具体要连接的蓝牙设备对象,基类是BluetoothDevice。
BluetoothGatt mBluetoothGatt = mBluetoothDevice.connectGatt(context, false, mGattCallback);//设置回调函数
2.断开
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
//这些是回调函数
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override// status为变化前状态,newState为变化后状态,由connect()和disconnect()方法引起
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
//当GATT客户端与服务端连接状态发生改变时触发,执行连接状态相关业务
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "Connected to GATT server.");
mBluetoothGatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disconnected from GATT server.");
}
}
@Override // status为是否发现成功,由discoverServices()方法引起
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
//当GATT客户端从服务端发现新的支持服务时触发,执行GATT数据解析,为读写更新提供对象
if (status == BluetoothGatt.GATT_SUCCESS) {
displayGattServices(mBluetoothGatt.getServices());
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
//蓝牙设备端数据被读的事件 // characteristic读取的特征,status读取状态,由readCharacteristic()方法引起
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
//当GATT客户端读取指定特征时触发,判断并执行显示或处理业务
if (status == BluetoothGatt.GATT_SUCCESS){
//获取 蓝牙设备端的电量
int batteryLevel = (int)(characteristic.getValue()[0]);
Log.w(TAG, "onCharacteristicRead batteryLevel: " + batteryLevel);
}
}
@Override // characteristic发生改变的特征,由setCharacteristicNotification()方法设置
public void onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic
characteristic) {
//当GATT服务端被指定的特征发生改变而发送通知时触发,更新UI或执行处理业务
}
};
private void displayGattServices(List
if (gattServices == null) return;
for (BluetoothGattService gattService : gattServices) {
List
for (final BluetoothGattCharacteristic gattCharacteristic: gattCharacteristics) {
if(gattCharacteristic.getUuid().toString().equals("00002a19-0000-1000-8000-00805f9b34fb")) {
mBluetoothGatt.setCharacteristicNotification(gattCharacteristic, true);
mBluetoothGatt.readCharacteristic(gattCharacteristic);//读蓝牙设备端电量
}
}
}
}