class BluetoothGatt

  • discoverServices()。把连接时存储在HAL层的gatt db存储到GattService、BluetoothGatt,并通过回调onServicesDiscovered,告知app这个过程完成了。会依次回调JNI注册的两个函数:btgattc_search_complete_cb、btgattc_get_gatt_db_cb。当HAL已从peripheral读出gatt db后,会回调第一个btgattc_search_complete_cb,JNI会在新建线程反向调用HAL的btif_gattc_get_gatt_db。在此函数,HAL把gatt db复制到自开辟的内存块db_ptr,复制完后,以这内存块地址为参数回调第二个btgattc_get_gatt_db_cb。在此回调中,JNI从db_ptr读gatt db。完成btgattc_get_gatt_db_cb后,HAL、GattService、BluetoothGatt,都各自存储了gatt db。另外,btgattc_get_gatt_db_cb在各自存储gatt db后,会回调app层的onServicesDiscovered。
  • disconnect()。如果调用了该方法后可以调用connect()进行重连,这样还可以继续进行断开前的操作。
  • close()。一但调用了该方法,如果想再次连接,必须调用BluetoothDevice.connectGatt()。因为close()方法将释放BluetootheGatt的所有资源。
  • 当你需要手动断开时,调用disconnect(),此时断开成功后会回调onConnectionStateChange。在这个函数中再调用close()释放资源。如果在disconnect后立即调用close,会导致无法回调onConnectionStateChange。
  • 对同一个periperal,disconnect()后、close()之前,不要调用BluetoothDevice.connectGatt。否则app可能会收到一个不是由connectGatt导致的“带外”newState == BluetoothProfile.STATE_CONNECTED的onConnectionStateChange,于是程序混乱。
<aosp>/frameworks/base/core/java/android/bluetooth/BluetoothGatt.java
------
public final class BluetoothGatt implements BluetoothProfile {
    public void close() {
        if (DBG) Log.d(TAG, "close()");

        // unregisterApp()会调用mService.unregisterClient(mClientIf, mAttributionSource);
        unregisterApp();
        mConnState = CONN_STATE_CLOSED;
        mAuthRetryState = AUTH_RETRY_STATE_IDLE;
    }

    public void disconnect() {
        if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
        if (mService == null || mClientIf == 0) return;

        try {
            mService.clientDisconnect(mClientIf, mDevice.getAddress(), mAttributionSource);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
    }

    public boolean connect() {
        try {
            // autoConnect is inverse of "isDirect"
            mService.clientConnect(mClientIf, mDevice.getAddress(), false, mTransport,
                    mOpportunistic, mPhy, mAttributionSource);
            return true;
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
            return false;
        }
    }

    public boolean discoverServices() {
        if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
        if (mService == null || mClientIf == 0) return false;

        mServices.clear();

        try {
            mService.discoverServices(mClientIf, mDevice.getAddress(), mAttributionSource);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
            return false;
        }

        return true;
    }

    public boolean refresh() {
        if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
        if (mService == null || mClientIf == 0) return false;

        try {
            mService.refreshDevice(mClientIf, mDevice.getAddress(), mAttributionSource);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
            return false;
        }

        return true;
    }
}

 

一、discoverServices()

discoverServices内中是调用mService.discoverServices(),该操作最终会调用bt协议栈的btif_gattc_search_service。它通过MessageLoopThread机制,切换到bt_jni_thread线程执行BTA_GATTC_ServiceSearchRequest。

<aosp>/system/bt/btif/src/btif_gatt_client.cc
------
static bt_status_t btif_gattc_search_service(int conn_id,
                                             const Uuid* filter_uuid) {
  CHECK_BTGATT_INIT();

  if (filter_uuid) {
    Uuid* uuid = new Uuid(*filter_uuid);
    return do_in_jni_thread(
        Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, base::Owned(uuid)));
  } else {
    return do_in_jni_thread(
        Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, nullptr));
  }
}

对BTA_GATTC_ServiceSearchRequest,如果只是想获取整个gatt数据库,参数p_srvc_uuid会填nullptr。

<aosp>/system/bt/bta/gatt/bta_gattc_api.cc
------
void BTA_GATTC_ServiceSearchRequest(uint16_t conn_id, const Uuid* p_srvc_uuid) {
  const size_t len = sizeof(tBTA_GATTC_API_SEARCH) + sizeof(Uuid);
  tBTA_GATTC_API_SEARCH* p_buf = (tBTA_GATTC_API_SEARCH*)osi_calloc(len);

  p_buf->hdr.event = BTA_GATTC_API_SEARCH_EVT;
  p_buf->hdr.layer_specific = conn_id;
  if (p_srvc_uuid) {
    p_buf->p_srvc_uuid = (Uuid*)(p_buf + 1);
    *p_buf->p_srvc_uuid = *p_srvc_uuid;
  } else {
    p_buf->p_srvc_uuid = NULL;
  }

  bta_sys_sendmsg(p_buf);
}

接下查看event=BTA_GATTC_API_SEARCH_EVT时的bta_gattc_hdl_event,它进入“default”入口。

<aosp>/system/bt/bta/gatt/bta_gattc_main.c
------
bool bta_gattc_hdl_event(BT_HDR_RIGID* p_msg) {
  tBTA_GATTC_CLCB* p_clcb = NULL;
  bool rt = true;

  switch (p_msg->event) {

    ...

    default:
      if (p_msg->event == BTA_GATTC_INT_CONN_EVT)
        p_clcb = bta_gattc_find_int_conn_clcb((tBTA_GATTC_DATA*)p_msg);
      else if (p_msg->event == BTA_GATTC_INT_DISCONN_EVT)
        p_clcb = bta_gattc_find_int_disconn_clcb((tBTA_GATTC_DATA*)p_msg);
      else
        p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->layer_specific);

      if (p_clcb != NULL) {
        // 此时有效状态或是BTA_GATTC_DISCOVER_ST,或是BTA_GATTC_CONN_ST
        // hdr.event是BTA_GATTC_API_SEARCH_EVT。
        rt = bta_gattc_sm_execute(p_clcb, p_msg->event,
                                  (const tBTA_GATTC_DATA*)p_msg);
      } else {
        VLOG(1) << "Ignore unknown conn ID: " << +p_msg->layer_specific;
      }

      break;
  }

  return rt;
}

执行bta_gattc_sm_execute时,当前有效状态可能或是BTA_GATTC_DISCOVER_ST,或是BTA_GATTC_CONN_ST。先分析第一种:BTA_GATTC_DISCOVER_ST。

如果处于这种,通常发生在bt协议栈回调到app注册的BluetoothGattCallback.onConnectionStateChange(status==STATE_CONNECTED)时,app立即在这里调用了discoverServices()。由于bta从peripheral读取gatt数据库需要点时间,于是discoverServices执行这里时,状态机还处在BTA_GATTC_DISCOVER_ST。

针对此刻的状态转换,bta_gattc_sm_execute要使用的状态表是bta_gattc_st_discover,收到BTA_GATTC_API_SEARCH_EVT事件,查表可知action是BTA_GATTC_Q_CMD,下一个状态依旧是BTA_GATTC_DISCOVER_ST。action是BTA_GATTC_Q_CMD时执行的函数是bta_gattc_q_cmd。

<aosp>/system/bt/bta/gatt/bta_gattc_act.cc
------
void bta_gattc_q_cmd(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) {
  bta_gattc_enqueue(p_clcb, p_data);
}

<aosp>/system/bt/bta/gatt/bta_gattc_utils.cc
------
bool bta_gattc_enqueue(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) {
  if (p_clcb->p_q_cmd == NULL) {
    p_clcb->p_q_cmd = p_data;
    return true;
  }

  LOG(ERROR) << __func__ << ": already has a pending command";
  /* skip the callback now. ----- need to send callback ? */
  return false;
}

bta_gattc_q_cmd只是简单地把BTA_GATTC_API_SEARCH_EVT命令放到p_clcb->p_q_cmd。放完之后会发生什么?——回看“BLE(4/6):连接之bta_gattc_start_discover”末尾,在生成完整gatt数据库,状态进入BTA_GATTC_CONN_ST后,会调用bta_gattc_disc_cmpl。它会检查p_clcb->p_q_cmd,如果发现不是nullptr,那它会以这个p_q_cmd执行bta_gattc_sm_execute,而这也正是上面提到的执行bta_gattc_sm_execute时的第二种情况:当状态处于BTA_GATTC_CONN_ST时。

状态是BTA_GATTC_CONN_ST时。针对此刻的状态转换,bta_gattc_sm_execute使用的状态表是bta_gattc_st_connected,收到BTA_GATTC_API_SEARCH_EVT事件,查表可知action是BTA_GATTC_SEARCH,下一个状态依旧是BTA_GATTC_CONN_ST。action是BTA_GATTC_SEARCH时执行的函数是bta_gattc_search。

<aosp>/system/bt/bta/gatt/bta_gattc_cache.cc
------
void bta_gattc_search_service(tBTA_GATTC_CLCB* p_clcb, Uuid* p_uuid) {
  for (const Service& service : p_clcb->p_srcb->gatt_database.Services()) {
    if (p_uuid && *p_uuid != service.uuid) continue;

    if (!p_clcb->p_rcb->p_cback) continue;

    tBTA_GATTC cb_data;
    memset(&cb_data, 0, sizeof(tBTA_GATTC));
    cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
    cb_data.srvc_res.service_uuid.inst_id = service.handle;
    cb_data.srvc_res.service_uuid.uuid = service.uuid;

    (*p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
  }
}

<aosp>/system/bt/bta/gatt/bta_gattc_act.cc
------
void bta_gattc_search(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) {
  tGATT_STATUS status = GATT_INTERNAL_ERROR;
  tBTA_GATTC cb_data;

  if (p_clcb->p_srcb && !p_clcb->p_srcb->gatt_database.IsEmpty()) {
    status = GATT_SUCCESS;
    /* search the local cache of a server device */
    bta_gattc_search_service(p_clcb, p_data->api_search.p_srvc_uuid);
  }
  cb_data.search_cmpl.status = status;
  cb_data.search_cmpl.conn_id = p_clcb->bta_conn_id;

  /* end of search or no server cache available */
  (*p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_CMPL_EVT, &cb_data);
}

bta_gattc_search会用p_clcb->p_rcb->p_cback依次执行两类回调。

  1. BTA_GATTC_SEARCH_RES_EVT。这发生在bta_gattc_search_service,如果p_srvc_uuid是nullptr,那它不会发生。
  2. BTA_GATTC_SEARCH_CMPL_EVT。向上层报告此次gatt数据库的发现结果。

这里不深入BTA_GATTC_SEARCH_RES_EVT,让看肯定会上报的BTA_GATTC_SEARCH_CMPL_EVT。

p_clcb->p_rcb->p_cback指向来自registerClient时调用BTA_GATTC_AppRegister传入的参数bta_gattc_cback,关于它的描述在“BLE(2/6):连接之BluetoothDevice.connectGatt”搜“bta_gattc_cback”。bta_gattc_cback会使用fixed_queue_enqueus机制实现在bt_jni_workqueue_thread线程执行btif_gattc_upstreams_evt。这里发送的event是BTA_GATTC_SEARCH_CMPL_EVT。

<aosp>/system/bt/btif/src/btif_gatt_client.c
------
static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
{
  ALOGD("%s: Event %d", __FUNCTION__, event);

  tBTA_GATTC *p_data = (tBTA_GATTC*)p_param;
  switch (event)
  {
    case BTA_GATTC_SEARCH_CMPL_EVT:
    {
      HAL_CBACK(bt_gatt_callbacks, client->search_complete_cb
              , p_data->search_cmpl.conn_id, p_data->search_cmpl.status);
      break;
    }
  }

  btapp_gattc_free_req_data(event, p_data);
}

client->search_complete_cb对应JNI层的btgattc_search_complete_cb。它将一路向上回调:GattService.onSearchCompleted。和其它回调有不一样,它没继续向上,而是又向下了。

<aosp>\packages\apps\Bluetooth\src\com\android\bluetooth\gatt\GattService.java
------
public class GattService extends ProfileService {
    void onSearchCompleted(int connId, int status) throws RemoteException {
        if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status);
        // Gatt DB is ready!

        // This callback was called from the jni_workqueue thread. If we make request to the stack
        // on the same thread, it might cause deadlock. Schedule request on a new thread instead.
        Thread t = new Thread(new Runnable() {
            public void run() {
                gattClientGetGattDbNative(connId);
            }
        });
        t.start();
    }
}

将在一个新线程执行JNI操作:gattClientGetGattDbNative。

static void gattClientGetGattDbNative(JNIEnv* env, jobject object,
    jint conn_id)
{
    if (!sGattIf) return;

    sGattIf->client->get_gatt_db(conn_id);
}

在HAL层,get_gatt_db对应btif_gattc_get_gatt_db。类似btif_gattc_register_app、btif_gattc_open,btif_gattc_get_gatt_db也是调用btif_transfer_context,通过fixed_queue_enqueus机制,切换到bt_jni_workqueue_thread线程执行btgattc_handle_event,参数event值BTIF_GATTC_GET_GATT_DB。

<aosp>/system/bt/btif/src/btif_gatt_client.c
------
static void btgattc_handle_event(uint16_t event, char* p_param)
{
  tBTA_GATT_STATUS           status;
  tBT_UUID                   uuid;
  ...

  btif_gattc_cb_t* p_cb = (btif_gattc_cb_t*)p_param;
  if (!p_cb) return;

  switch (event)
  {
  case BTIF_GATTC_GET_GATT_DB:
  {
    btgatt_db_element_t *db = NULL;
    int count = 0;
    BTA_GATTC_GetGattDb(p_cb->conn_id, 0x0000, 0xFFFF, &db, &count);

    HAL_CBACK(bt_gatt_callbacks, client->get_gatt_db_cb,
      p_cb->conn_id, db, count);
    osi_free(db);
    break;
  }
  ...
  }
}

BTIF_GATTC_GET_GATT_DB执行两个操人。一是BTA_GATTC_GetGattDb,把之前discover出的gatt放入新建变量db。二是回调client->get_gatt_db_cb,它对应JNI层的btgattc_get_gatt_db_cb。btgattc_get_gatt_db_cb解析HAL上传的db,把它放入Java层Ljava/util/ArrayList变量,并以它为参数调用method_onGetGattDb,即GattService.onGetGattDb。

<aosp>\packages\apps\Bluetooth\src\com\android\bluetooth\gatt\GattService.java
------
public class GattService extends ProfileService {
    void onGetGattDb(int connId, ArrayList<GattDbElement> db) throws RemoteException {
        String address = mClientMap.addressByConnId(connId);

        if (DBG) Log.d(TAG, "onGetGattDb() - address=" + address);

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app == null || app.callback == null) {
            Log.e(TAG, "app or callback is null");
            return;
        }

        List<BluetoothGattService> db_out = new ArrayList<BluetoothGattService>();

        BluetoothGattService currSrvc = null;
        BluetoothGattCharacteristic currChar = null;

        for (GattDbElement el: db) {
            // 枚举db中单元,把它们放入db_out
        }

        // Search is complete when there was error, or nothing more to process
        gattClientDatabases.put(connId, db_out);
        app.callback.onSearchComplete(address, db_out, 0 /* status */);
    }
}

至此,discover出的db放入了GattService内的成员gattClientDatabases。之后一路向上回调BluetoothGatt.onSearchComplete --> app层的onServicesDiscovered。

BluetoothGatt.onSearchComplete在回调app层的onServicesDiscovered之前,会把gatt db存储成员mServices,也就是说,discover后,HAL、GattService、BluetoothGatt,都各自存储了gatt db。

二、disconnect()、close()

想明白这两个函数有什么区别,抄下“BLE(2/6):连接之BluetoothDevice.connectGatt”中写的。

BluetoothDevice.connectGatt会执行的两个函数。mService.registerClient()和mService.clientConnect()。对mService.registerClient(),主要两个操作。1)向GATT协议栈注册,并获得新的client_if。此过程只是在gatt_cb.cl_rcb得到一个可用位置,不会触发蓝牙数据传输。2)调用JNI注册的回调函数:btgattc_register_app_cb,进而回调BluetoothGatt.mBluetoothGattCallback.onClientRegistered。onClientRegistered不会回调到app,而是“向下”执行connectGatt的第二个函数:mService.clientConnect()。

disconnect()。断开连接,对应着mService.clientConnect()的逆操作。BluetoothDevice.connect()就是调用mService.clientConnect(),因而调用disconnect()之后可以调用connect()进行重连。此操作会回调bt_gatt_callbacks->client->close_cb、bt_hal_cbacks->acl_state_changed_cb。第一个close_cb会回调app的onConnectionStateChange,第二个acl_state_changed_cb则表示,销毁了btif_gattc_open时用L2CA_ConnectFixedChnl()在l2cap层分配的channel。

I/bt_btif: HAL bt_gatt_callbacks->client->close_cb
I/bt_btif: btif_dm_upstreams_evt: ev: BTA_DM_LINK_DOWN_EVT
D/bt_btif: BTA_DM_LINK_DOWN_EVT. Sending BT_ACL_STATE_DISCONNECTED
I/bt_btif: HAL bt_hal_cbacks->acl_state_changed_cb
------
虽然第二个是bt_hal_cbacks,和其它的bt_gatt_callbacks不一样,但回调运行在一样的线程。

close()。对应着mService.registerClient()逆操作。它会向GATT协议栈注销此次申请到的client_if。因为close()已将registerClient()时申请到的clint_if还给GATT协议栈,一但调用了该方法,想再次连接必须调用BluetoothDevice.connectGatt()。

类似BluetoothDevice.connectGatt一个函数就包括mService.registerClient()、mService.clientConnect(),建议app“一个函数”凋用disconnect、close。“一个函数”加引号,是因为中间必须处理参数newState是 BluetoothProfile.STATE_DISCONNECTED的onConnectionStateChange。必须在onConnectionStateChange处理完私有任务后,再调用close。于是disconnect、close会这么个流程。

  1. 想断开连接了,app调用disconnect()。
  2. 某个时刻,app层的onConnectionStateChange被调用。函数首先处理私有操作,像告知主线程此次连接已安全断开,然后调用close(),释放client_if。

如果在disconnect后立即调用close,即不等onConnectionStateChange,会导致无法回调onConnectionStateChange。

三、mService.unregisterClient(mClientIf)

disconnect后,虽然已没了L2CAP通道,但clientIf还是有效,unregisterClient目的是要回收这个clientIf。依据之前的mServier分析方法,很容就能定位到它会执行JNI层的gattClientUnregisterAppNative。

<aosp>/packages/apps/Bluetooth/jni/com_android_bluetooth_gatt.cpp
------
static void gattClientUnregisterAppNative(JNIEnv* env, jobject object, jint clientIf)
{
    if (!sGattIf) return;
    sGattIf->client->unregister_client(clientIf);
}

针对JNI层中的“sGattIf->client->unregister_client(clientIf)”,sGattIf对应着HAL中的btgattInterface,sGattIf->client对应着btgattClientInterface,unregister_client是btif_gattc_unregister_app。

类似btif_gattc_register_app,btif_gattc_unregister_app也是调用btif_transfer_context,通过fixed_queue_enqueus机制,切换到bt_jni_workqueue_thread线程执行btgattc_handle_event,参数event值BTIF_GATTC_UNREGISTER_APP。

<aosp>/system/bt/btif/src/btif_gatt_client.c
------
static void btgattc_handle_event(uint16_t event, char* p_param)
{
  tBTA_GATT_STATUS           status;
  tBT_UUID                   uuid;
  ...

  btif_gattc_cb_t* p_cb = (btif_gattc_cb_t*)p_param;
  if (!p_cb) return;

  switch (event)
  {
  case BTIF_GATTC_UNREGISTER_APP:
      btif_gattc_clear_clientif(p_cb->client_if, TRUE);
      btif_gattc_decr_app_count();
      BTA_GATTC_AppDeregister(p_cb->client_if);
      break;
  ...
  }
}

进入BTA_GATTC_AppDeregister。

<aosp>\system\bt\bta\gatt\bta_gattc_api.c
------
void BTA_GATTC_AppDeregister(tBTA_GATTC_IF client_if)
{
    tBTA_GATTC_API_DEREG *p_buf =
        (tBTA_GATTC_API_DEREG *)osi_malloc(sizeof(tBTA_GATTC_API_DEREG));

    p_buf->hdr.event = BTA_GATTC_API_DEREG_EVT;
    p_buf->client_if = client_if;

    bta_sys_sendmsg(p_buf);
}

bta_sys_sendmsg使用fixed_queue_enqueus机制,触发在bt_workqueue_thread线程执行之前注册的bta_gattc_hdl_event。

<aosp>/system/bt/bta/gatt/bta_gattc_main.c
------
BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
{
    tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
    tBTA_GATTC_CLCB *p_clcb = NULL;
    tBTA_GATTC_RCB      *p_clreg;

    switch (p_msg->event)
    {
        case BTA_GATTC_API_DEREG_EVT:
            p_clreg = bta_gattc_cl_get_regcb(((tBTA_GATTC_DATA *)p_msg)->api_dereg.client_if);
            bta_gattc_deregister(p_cb, p_clreg);
            break;
        ...
    }

    return rt;
}

进入bta_gattc_deregister。

<aosp>/system/bt/bta/gatt/bta_gattc_act.c
------
void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_RCB  *p_clreg)
{
    UINT8               i;
    BT_HDR              buf;

    if (p_clreg != NULL) {
        if (p_clreg->num_clcb > 0) {
            ...
        } else {
            // p_clreg->num_clcb值是0,进这个入口
            bta_gattc_deregister_cmpl(p_clreg);
        }
    } else {
        APPL_TRACE_ERROR("bta_gattc_deregister Deregister Failedm unknown client cif");
    }
}

p_clreg->num_clcb值是0,执行bta_gattc_deregister_cmpl。

<aosp>/system/bt/bta/gatt/bta_gattc_act.c
------
static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg)
{
    ...
    GATT_Deregister(p_clreg->client_if);
    ...
}

bta_gattc_deregister_cmpl会调用mService.registerClient()中GATT_Register的逆操作:GATT_Deregister。

<aosp>/system/bt/stack/gatt/gatt_api.c
------
void GATT_Deregister (tGATT_IF gatt_if)
{
    tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
    ...

    // 此个memset会把p_reg->in_use置为false。
    memset (p_reg, 0, sizeof(tGATT_REG));
}

GATT_Deregister末尾执行的memset会把p_reg->in_use置为false,至此此个tGATT_REG变成空闲,后绪BluetoothDevice.connectGatt可再次使用它了。

 

四、refresh()

refresh用于删除连接过程中生成的、存储着gatt db的cache文件。主要应用场景是针对配置了OAD升级功能的BLE设备以及平常的开发调试。

BluetoothGatt.refresh -[HAL]-> btif_gattc_refresh --> BTA_GATTC_Refresh --> bta_gattc_process_api_refresh --> bta_gattc_cache_reset
<aosp>/system/bt/bta/gatt/bta_gattc_cache.c
------
void bta_gattc_cache_reset(BD_ADDR server_bda)
{
    BTIF_TRACE_DEBUG("%s", __func__);
    char fname[255] = {0};
    bta_gattc_generate_cache_file_name(fname, server_bda);
    unlink(fname);
}

在连接连过程中,如果有把gatt db存储在cache文件,bta_gattc_cache_reset将删除这文件。

 

五、为免麻烦,“一次性”调用disocnnect()、close()

对同一个periperal,disconnect()后、close()之前,不要调用BluetoothDevice.connectGatt。否则app可能会收到一个不是由connectGatt导致的“带外”newState == BluetoothProfile.STATE_CONNECTED的onConnectionStateChange,于是程序混乱。

假设disconnect()的client_if=5,新connectGatt申请出的client_if=6。若该peripheral触发notification,由于存在个处于GATTC_IDLE_ST状态的client_if=5,android认为它应该接收此个notification,会自动进行重联让进入GATTC_CONN_ST,相应地,app会收到一个“莫名其妙”newState == BluetoothProfile.STATE_CONNECTED的onConnectionStateChange。下面分析这个过程。

peripernal发来ACL数据后,client会回调gatt_client_handle_server_rsp。此时op_code值是GATT_HANDLE_VALUE_NOTIF(0x1B),“case GATT_HANDLE_VALUE_NOTIF”时,调用gatt_process_notification。

<aosp>/system/bt/stack/gatt/gatt_cl.c
------
void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
                               UINT16 len, UINT8 *p_data)
{
    ...
    for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
    {
        if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb)
        {
            conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
            (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
        }
    }
}

gatt_process_notification为确定应该由哪个/些conn_id(client_if)处理这个notification,于是检查所有(GATT_MAX_APPS)conn_if。对conn_id=5或6,p_cmpl_cb指向bta_gattc_cmpl_cback。此时op==GATTC_OPTYPE_NOTIFICATION,调用bta_gattc_process_indicate。

<aosp>/system/bt/bta/gatt/bta_gattc_act.c
------
void bta_gattc_process_indicate(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPLETE *p_data)
{
    ...
    /* if non-service change indication/notification, forward to application */
    if (!bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, &notify, &p_data->att_value))
    {
        /* if app registered for the notification */
        if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, &notify))
        {
            /* connection not open yet */
            // conn_id=5或6都会进入这里。
            if (p_clcb == NULL)
            {
                // 对于5,由于已经被BluetoothGatt.disconnect,p_clcb值是null,要重新得到这值。
                p_clcb = bta_gattc_clcb_alloc(gatt_if, remote_bda, transport);

                if (p_clcb == NULL) {
                    APPL_TRACE_ERROR("No resources");
                    return;
                }

                p_clcb->bta_conn_id = conn_id;
                p_clcb->transport   = transport;
                // 此时gattc状态是GATTC_IDLE_ST,收到BTA_GATTC_INT_CONN_EVT后,进入GATTC_CONN_ST。这里会回调JNI的open_cb。
                // GATTC State Change: [GATTC_IDLE_ST] -> [GATTC_CONN_ST] after Event [BTA_GATTC_INT_CONN_EVT]
                bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, NULL);
            }

            if (p_clcb != NULL)
                bta_gattc_proc_other_indication(p_clcb, op, p_data, &notify);
        }
        /* no one intersted and need ack? */
        else if (op == GATTC_OPTYPE_INDICATION)
        {
            APPL_TRACE_DEBUG("%s no one interested, ack now", __func__);
            GATTC_SendHandleValueConfirm(conn_id, handle);
        }
    }
}

对于5,由于已经被BluetoothGatt.disconnect,p_clcb值是null,于是要调用bta_gattc_clcb_alloc重新得到这值。此时gattc状态是GATTC_IDLE_ST,收到BTA_GATTC_INT_CONN_EVT后,进入GATTC_CONN_ST。当中会回调JNI的open_cb,进而回调app中newState == BluetoothProfile.STATE_CONNECTED的onConnectionStateChange。

全部评论: 0

    写评论: