项目中涉及低功耗蓝牙手柄的开发,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蓝牙连接通信的架构
————————————————
版权声明:本文为CSDN博主「疾风细语」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jasonwang18/article/details/73312283

Android 从源码分析BLE连接错误分析相关推荐

  1. 【Android SDM660源码分析】- 02 - UEFI XBL QcomChargerApp充电流程代码分析

    [Android SDM660源码分析]- 02 - UEFI XBL QcomChargerApp充电流程代码分析 一.加载 UEFI 默认应用程序 1.1 LaunchDefaultBDSApps ...

  2. Android wpa_supplicant源码分析---nl80211内核通信Generic Netlink

    代码位置: kernel/net/netlink/genetlink.c kernel/include/net/genetlink.h GENL简介 netlink仅支持32种协议类型,这在实际应用中 ...

  3. Android HandlerThread 源码分析

    HandlerThread 简介: 我们知道Thread线程是一次性消费品,当Thread线程执行完一个耗时的任务之后,线程就会被自动销毁了.如果此时我们又有一 个耗时任务需要执行,我们不得不重新创建 ...

  4. Android ADB 源码分析(三)

    前言 之前分析的两篇文章 Android Adb 源码分析(一) 嵌入式Linux:Android root破解原理(二) 写完之后,都没有写到相关的实现代码,这篇文章写下ADB的通信流程的一些细节 ...

  5. 【Android SDM660源码分析】- 03 - UEFI XBL GraphicsOutput BMP图片显示流程

    [Android SDM660源码分析]- 03 - UEFI XBL GraphicsOutput BMP图片显示流程 1. GraphicsOutput.h 2. 显示驱动初化 DisplayDx ...

  6. 【Android SDM660源码分析】- 01 - 如何创建 UEFI XBL Protocol DXE_DRIVER 驱动及UEFI_APPLICATION 应用程序

    [Android SDM660源码分析]- 01 - 如何创建 UEFI XBL Protocol DXE_DRIVER 驱动及UEFI_APPLICATION 应用程序 一.创建DXE_DRIVER ...

  7. 【Android SDM660源码分析】- 04 - UEFI ABL LinuxLoader 代码分析

    [Android SDM660源码分析]- 04 - UEFI ABL LinuxLoader 代码分析 1. LinuxLoader.c 系列文章: <[Android SDM660开机流程] ...

  8. Android 音频源码分析——AndroidRecord录音(一)

    Android 音频源码分析--AndroidRecord录音(一) Android 音频源码分析--AndroidRecord录音(二) Android 音频源码分析--AndroidRecord音 ...

  9. Android框架源码分析——从设计模式角度看 Retrofit 核心源码

    Android框架源码分析--从设计模式角度看 Retrofit 核心源码 Retrofit中用到了许多常见的设计模式:代理模式.外观模式.构建者模式等.我们将从这三种设计模式入手,分析 Retrof ...

最新文章

  1. sybase 数据库恢复
  2. 如何应对货期延迟(转自索菲外贸笔记)
  3. 彻底理解cookie、session、token
  4. Java ClassLoader findSystemClass()方法与示例
  5. Django开发中问题和报错集合
  6. python 换页_Python之路【第十九篇】自定义分页实现(模块化)
  7. 小时光扫地机器人圆圆_小时光:圆圆录像功能已开启,无死角录制林一霸道总裁一面,超甜...
  8. HashMap之HashMap中hashSeed(hash种子)的作用分析
  9. bcdedit无法打开启
  10. # 安卓手机启动黑阈服务
  11. sqlParameter的使用------七个构造函数
  12. 计算机无法登陆提示rpc服务器不可用,电脑rpc服务器不可用,教你电脑rpc服务器不可用怎么解决...
  13. linux 龙芯cpu 测试,龙芯CPU实测!对比赛扬 没想到会这样
  14. NEURAL MACHINE TRANSLATION BY JOINTLY LEARNING TO ALIGN AND TRANSLATE-论文翻译
  15. 计算机主板清理,电脑主板脏了如何清洗电脑主板才是正确
  16. PyQt(Python+Qt)学习随笔:QTreeWidgetItem项列图标的访问方法
  17. 手机新闻网站,手持移动新闻,手机报client,jQuery Mobile手机新闻网站,手机新闻网站demo,新闻阅读器开发...
  18. 量子计算(二):为什么需要量子计算
  19. Jackknife,Bootstrap, bagging, boosting, AdaBoost, Rand forest 和 gradient boosting的区别
  20. linux计划任务1

热门文章

  1. css控制文本超出省略...
  2. Python3网络爬虫开发实战,Scrapy 爬取新浪微博
  3. JAVA多线程基础篇-join方法的使用
  4. 经典人生感悟(慢慢更新)
  5. 创建简单的银行账户类,包括开户人、账号、和存款余额3个属性,以及查询余额、存款、取款等方法。创建两个账户验证类的设计。
  6. 自动驾驶代客泊车架构设计说明书
  7. 想买oppo find n的朋友 劝你等一等
  8. Python学习笔记-编写程序,输出所有由1、2、3、4这4个数字组成的素数,要求在每个素数中每个数字最多只能使用一次。
  9. 安装Mycat-eye对mycat进行监控
  10. Nginx 配置参数详解