项目中涉及低功耗蓝牙手柄的开发,GattCallback onConnectionStateChange接口返回状态status值有多个
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;    }

继续看reigsterApp方法

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  */

status 133 GATT_ERROR,这个错误是Android源码的问题

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蓝牙连接通信的架构

更多相关文章

  1. 关于AlertDialog中EditText不能弹出输入法解决方法
  2. android实现圆角矩形背景的方法
  3. Android RadioButton【单选按钮】的点击事件的两种方法
  4. android 跳转到系统相关应用的方法
  5. Android源码快速查找文件、搜索字符串和编译
  6. Android中的Handler通信机制源码解析
  7. android仿iPhone滚轮控件实现及源码
  8. android屏幕信息获取的两种方法
  9. 开源Jamendo在线音乐播放器源码(二)

随机推荐

  1. Java和Javascript互调的例子 ---------(An
  2. 如何让Android屏幕只能上下翻转
  3. Android:控件GridView的使用实例
  4. android获取gps坐标
  5. android studio3.5.2打包,解决建议使用 "k
  6. [Android Pro] Android fastboot刷机和获
  7. android Theme使用四
  8. 仿照利用android系统源码资源文件,修改See
  9. Android 邮件发送(一键发送, 163邮箱)
  10. Android 文件读写 + sdcard + 文件的属性