private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { LogUtil.e("status :" +status +" ,newState :"+ newState); switch (status){ case BluetoothGatt.GATT_SUCCESS://0 break; case BluetoothGatt.GATT_FAILURE://257 break; case 133: case 8: case 22: break; } } }
其中GATT_SUCCESS和GATT_FAILURE(不常见)在BluetoothGatt源码中可以找到外,其他8、22、133等status状态值不知道其意义,对于断开连接的原因就不好判断了。
下面我们从framework源码追查这几个状态
_bluetoothGatt = device.connectGatt(_context, false, mGattCallback);BluetoothDevice connectGatt方法将mGattCallback传入
public BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport) { // TODO(Bluetooth) check whether platform support BLE // Do the check here or in GattServer? BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); IBluetoothManager managerService = adapter.getBluetoothManager(); try { IBluetoothGatt iGatt = managerService.getBluetoothGatt(); if (iGatt == null) { // BLE is not supported return null; } BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport); gatt.connect(autoConnect, callback); return gatt; } catch (RemoteException e) {Log.e(TAG, "", e);} return null; }connect方法中创建了BluetoothGatt对象,gatt connect方法将callback导入,我们继续看BluetoothGatt源码
/*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) { if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect); synchronized(mStateLock) { if (mConnState != CONN_STATE_IDLE) { throw new IllegalStateException("Not idle"); } mConnState = CONN_STATE_CONNECTING; } mAutoConnect = autoConnect; if (!registerApp(callback)) { synchronized(mStateLock) { mConnState = CONN_STATE_IDLE; } Log.e(TAG, "Failed to register callback"); return false; } // The connection will continue in the onClientRegistered callback return true; }
private boolean registerApp(BluetoothGattCallback callback) { if (DBG) Log.d(TAG, "registerApp()"); if (mService == null) return false; mCallback = callback; UUID uuid = UUID.randomUUID(); if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid); try { mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback); } catch (RemoteException e) { Log.e(TAG,"",e); return false; } return true; }mService是IBluetoothGatt接口的Proxy端
查找源码发现IBluetoothGatt的Stub端在GattService中实现,我们看GattService的registerClient方法
void registerClient(UUID uuid, IBluetoothGattCallback callback) { enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); mClientMap.add(uuid, callback, this); gattClientRegisterAppNative(uuid.getLeastSignificantBits(), uuid.getMostSignificantBits()); }mClientMap管理各个APP的callback对象
void onConnected(int clientIf, int connId, int status, String address) throws RemoteException { if (DBG) Log.d(TAG, "onConnected() - clientIf=" + clientIf + ", connId=" + connId + ", address=" + address); if (status == 0) mClientMap.addConnection(clientIf, connId, address); ClientMap.App app = mClientMap.getById(clientIf); if (app != null) { app.callback.onClientConnectionState(status, clientIf, (status==BluetoothGatt.GATT_SUCCESS), address); } } void onDisconnected(int clientIf, int connId, int status, String address) throws RemoteException { if (DBG) Log.d(TAG, "onDisconnected() - clientIf=" + clientIf + ", connId=" + connId + ", address=" + address); mClientMap.removeConnection(clientIf, connId); ClientMap.App app = mClientMap.getById(clientIf); if (app != null) { app.callback.onClientConnectionState(status, clientIf, false, address); } }在GattService的onConnected和onDisconnected方法中我们找到了callback.onClientConnectionState的调用,那么这两个方法是谁调用的,很显然这个调用者来自jni底层
method_onConnected = env->GetMethodID(clazz, "onConnected", "(IIILjava/lang/String;)V"); method_onDisconnected = env->GetMethodID(clazz, "onDisconnected", "(IIILjava/lang/String;)V");com_android_bluetooth_gatt.cpp中有关于这两个方法的反射调用
void btgattc_close_cb(int conn_id, int status, int clientIf, bt_bdaddr_t* bda) { CHECK_CALLBACK_ENV char c_address[32]; snprintf(c_address, sizeof(c_address),"%02X:%02X:%02X:%02X:%02X:%02X", bda->address[0], bda->address[1], bda->address[2], bda->address[3], bda->address[4], bda->address[5]); jstring address = sCallbackEnv->NewStringUTF(c_address); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDisconnected, clientIf, conn_id, status, address); sCallbackEnv->DeleteLocalRef(address); checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); }com_android_bluetooth_gatt的btgattc_close_cb方法中调用了onDisconnected,但是status依然是外部导入的,我们继续追。
btgattc_close_cb是BTA client callback,所以答案应该在BTA
BTA就是Bluetooth Application,所有蓝牙请求都必须进过它,我们看bta目录下的h文件,目录是system/bt/bta
最终,我们在bta_gatt_api.h中找到了status 8, 22, 133等错误
#define BTA_GATT_OK GATT_SUCCESS #define BTA_GATT_INVALID_HANDLE GATT_INVALID_HANDLE /* 0x0001 */ #define BTA_GATT_READ_NOT_PERMIT GATT_READ_NOT_PERMIT /* 0x0002 */ #define BTA_GATT_WRITE_NOT_PERMIT GATT_WRITE_NOT_PERMIT /* 0x0003 */ #define BTA_GATT_INVALID_PDU GATT_INVALID_PDU /* 0x0004 */ #define BTA_GATT_INSUF_AUTHENTICATION GATT_INSUF_AUTHENTICATION /* 0x0005 */ #define BTA_GATT_REQ_NOT_SUPPORTED GATT_REQ_NOT_SUPPORTED /* 0x0006 */ #define BTA_GATT_INVALID_OFFSET GATT_INVALID_OFFSET /* 0x0007 */ #define BTA_GATT_INSUF_AUTHORIZATION GATT_INSUF_AUTHORIZATION /* 0x0008 */ #define BTA_GATT_PREPARE_Q_FULL GATT_PREPARE_Q_FULL /* 0x0009 */ #define BTA_GATT_NOT_FOUND GATT_NOT_FOUND /* 0x000a */ #define BTA_GATT_NOT_LONG GATT_NOT_LONG /* 0x000b */ #define BTA_GATT_INSUF_KEY_SIZE GATT_INSUF_KEY_SIZE /* 0x000c */ #define BTA_GATT_INVALID_ATTR_LEN GATT_INVALID_ATTR_LEN /* 0x000d */ #define BTA_GATT_ERR_UNLIKELY GATT_ERR_UNLIKELY /* 0x000e */ #define BTA_GATT_INSUF_ENCRYPTION GATT_INSUF_ENCRYPTION /* 0x000f */ #define BTA_GATT_UNSUPPORT_GRP_TYPE GATT_UNSUPPORT_GRP_TYPE /* 0x0010 */ #define BTA_GATT_INSUF_RESOURCE GATT_INSUF_RESOURCE /* 0x0011 */ #define BTA_GATT_NO_RESOURCES GATT_NO_RESOURCES /* 0x80 */ #define BTA_GATT_INTERNAL_ERROR GATT_INTERNAL_ERROR /* 0x81 */ #define BTA_GATT_WRONG_STATE GATT_WRONG_STATE /* 0x82 */ #define BTA_GATT_DB_FULL GATT_DB_FULL /* 0x83 */ #define BTA_GATT_BUSY GATT_BUSY /* 0x84 */ #define BTA_GATT_ERROR GATT_ERROR /* 0x85 */ #define BTA_GATT_CMD_STARTED GATT_CMD_STARTED /* 0x86 */ #define BTA_GATT_ILLEGAL_PARAMETER GATT_ILLEGAL_PARAMETER /* 0x87 */ #define BTA_GATT_PENDING GATT_PENDING /* 0x88 */ #define BTA_GATT_AUTH_FAIL GATT_AUTH_FAIL /* 0x89 */ #define BTA_GATT_MORE GATT_MORE /* 0x8a */ #define BTA_GATT_INVALID_CFG GATT_INVALID_CFG /* 0x8b */ #define BTA_GATT_SERVICE_STARTED GATT_SERVICE_STARTED /* 0x8c */ #define BTA_GATT_ENCRYPED_MITM GATT_ENCRYPED_MITM /* GATT_SUCCESS */ #define BTA_GATT_ENCRYPED_NO_MITM GATT_ENCRYPED_NO_MITM /* 0x8d */ #define BTA_GATT_NOT_ENCRYPTED GATT_NOT_ENCRYPTED /* 0x8e */ #define BTA_GATT_CONGESTED GATT_CONGESTED /* 0x8f */ #define BTA_GATT_DUP_REG 0x90 /* 0x90 */ #define BTA_GATT_ALREADY_OPEN 0x91 /* 0x91 */ #define BTA_GATT_CANCEL 0x92 /* 0x92 */
#define BTA_GATT_CONN_UNKNOWN 0 #define BTA_GATT_CONN_L2C_FAILURE GATT_CONN_L2C_FAILURE /* general l2cap resource failure */ #define BTA_GATT_CONN_TIMEOUT GATT_CONN_TIMEOUT /* 0x08 connection timeout */ #define BTA_GATT_CONN_TERMINATE_PEER_USER GATT_CONN_TERMINATE_PEER_USER /* 0x13 connection terminate by peer user */ #define BTA_GATT_CONN_TERMINATE_LOCAL_HOST GATT_CONN_TERMINATE_LOCAL_HOST/* 0x16 connectionterminated by local host */ #define BTA_GATT_CONN_FAIL_ESTABLISH GATT_CONN_FAIL_ESTABLISH /* 0x03E connection fail to establish */ #define BTA_GATT_CONN_LMP_TIMEOUT GATT_CONN_LMP_TIMEOUT /* 0x22 connection fail for LMP response tout */ #define BTA_GATT_CONN_CANCEL GATT_CONN_CANCEL /* 0x0100 L2CAP connection cancelled */ #define BTA_GATT_CONN_NONE 0x0101 /* 0x0101 no connection to cancel */
https://stackoverflow.com/questions/27280402/every-connection-request-is-being-treated-as-direct-connect-request-android-bl
status 22 GATT_CONN_TERMINATE_LOCAL_HOST
https://stackoverflow.com/questions/40966104/how-to-solve-the-error-onclientconnectionstate-status-22-clientif-7-in-ble?noredirect=1
status 8 GATT_CONN_TIMEOUT
通过自上而下追踪status的轨迹,我们还间接了解了GATT蓝牙连接通信的架构