Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5b8923f0 authored by Krzysztof Kopyscinski (xWF)'s avatar Krzysztof Kopyscinski (xWF) Committed by Gerrit Code Review
Browse files

Merge "has_client.cc: cleanup device when GATT operations may be pending" into main

parents 9e163431 90315261
Loading
Loading
Loading
Loading
+25 −8
Original line number Diff line number Diff line
@@ -429,7 +429,7 @@ public:
      ClearDeviceInformationAndStartSearch(device);
    } else {
      log::error("Devices {}: Control point not usable. Disconnecting!", device->addr);
      BTA_GATTC_Close(device->conn_id);
      CleanAndDisconnectByConnId(conn_id);
    }
  }

@@ -475,7 +475,7 @@ public:
      ClearDeviceInformationAndStartSearch(device);
    } else {
      log::error("Devices {}: Control point not usable. Disconnecting!", device->addr);
      BTA_GATTC_Close(device->conn_id);
      CleanAndDisconnectByConnId(conn_id);
    }
  }

@@ -1137,7 +1137,7 @@ private:
      /* Both of these CCC are mandatory */
      if (enabling_ntf && (status != GATT_SUCCESS)) {
        log::error("Failed to register for notifications on handle=0x{:x}", handle);
        BTA_GATTC_Close(conn_id);
        CleanAndDisconnectByConnId(conn_id);
        return;
      }
    }
@@ -1189,20 +1189,22 @@ private:
      return;
    }

    tCONN_ID conn_id = device->conn_id;

    if (status != GATT_SUCCESS) {
      if (status == GATT_DATABASE_OUT_OF_SYNC) {
        log::info("Database out of sync for {}", device->addr);
        ClearDeviceInformationAndStartSearch(device);
      } else {
        log::error("Could not read characteristic at handle=0x{:04x}", handle);
        BTA_GATTC_Close(device->conn_id);
        CleanAndDisconnectByConnId(conn_id);
      }
      return;
    }

    if (len != 1) {
      log::error("Invalid features value length={} at handle=0x{:x}", len, handle);
      BTA_GATTC_Close(device->conn_id);
      CleanAndDisconnectByConnId(conn_id);
      return;
    }

@@ -1565,9 +1567,11 @@ private:

  void OnHasCtpValueNotification(HasDevice* device, uint16_t len, const uint8_t* value) {
    auto ntf_opt = HasCtpNtf::FromCharacteristicValue(len, value);
    tCONN_ID conn_id = device->conn_id;

    if (!ntf_opt.has_value()) {
      log::error("Unhandled notification for device: {}", *device);
      BTA_GATTC_Close(device->conn_id);
      CleanAndDisconnectByConnId(conn_id);
      return;
    }

@@ -1591,19 +1595,22 @@ private:
      return;
    }

    tCONN_ID conn_id = device->conn_id;

    if (status != GATT_SUCCESS) {
      if (status == GATT_DATABASE_OUT_OF_SYNC) {
        log::info("Database out of sync for {}", device->addr);
        ClearDeviceInformationAndStartSearch(device);
      } else {
        log::error("Could not read characteristic at handle=0x{:04x}", handle);
        BTA_GATTC_Close(device->conn_id);
        CleanAndDisconnectByConnId(conn_id);
        return;
      }
    }

    if (len != 1) {
      log::error("Invalid preset value length={} at handle=0x{:x}", len, handle);
      BTA_GATTC_Close(device->conn_id);
      CleanAndDisconnectByConnId(conn_id);
      return;
    }

@@ -1717,6 +1724,16 @@ private:
    device.ConnectionCleanUp();
  }

  void CleanAndDisconnectByConnId(tCONN_ID conn_id) {
    auto device_iter =
            std::find_if(devices_.begin(), devices_.end(), HasDevice::MatchConnId(conn_id));
    if (device_iter != devices_.end()) {
      DoDisconnectCleanUp(*device_iter);
      devices_.erase(device_iter);
    }
    BTA_GATTC_Close(conn_id);
  }

  /* These below are all GATT service discovery, validation, cache & storage */
  bool CacheAttributeHandles(const gatt::Service& service, HasDevice* device) {
    log::debug("device={}", device->addr);
+35 −0
Original line number Diff line number Diff line
@@ -1602,6 +1602,41 @@ TEST_F(HasClientTest, test_discovery_has_broken_no_active_preset_ntf) {
  TestConnect(test_address);
}

TEST_F(HasClientTest, test_cp_not_usable_read_all_presets) {
  osi_property_set_bool("persist.bluetooth.has.always_use_preset_cache", false);

  const RawAddress test_address = GetTestAddress(1);
  std::set<HasPreset, HasPreset::ComparatorDesc> has_presets = {{
          HasPreset(1, HasPreset::kPropertyAvailable, "Universal"),
          HasPreset(2, HasPreset::kPropertyAvailable | HasPreset::kPropertyWritable, "Preset2"),
  }};

  SetSampleDatabaseHasPresetsNtf(test_address,
                                 bluetooth::has::kFeatureBitHearingAidTypeBanded |
                                         bluetooth::has::kFeatureBitWritablePresets |
                                         bluetooth::has::kFeatureBitDynamicPresets,
                                 has_presets);

  ON_CALL(gatt_queue, ReadCharacteristic(_, HasDbBuilder::kActivePresetIndexValHdl, _, _))
          .WillByDefault(Invoke([&](uint16_t conn_id, uint16_t handle, GATT_READ_OP_CB cb,
                                    void* cb_data) -> void {
            std::vector<uint8_t> value;

            tGATT_STATUS status = GATT_ERROR;
            if (cb) {
              cb(conn_id, status, handle, value.size(), value.data(), cb_data);
            }
          }));

  EXPECT_CALL(*callbacks,
              OnDeviceAvailable(test_address, bluetooth::has::kFeatureBitHearingAidTypeBanded |
                                                      bluetooth::has::kFeatureBitWritablePresets |
                                                      bluetooth::has::kFeatureBitDynamicPresets));
  EXPECT_CALL(gatt_queue, Clean(1)).Times(1);

  TestConnect(test_address);
}

TEST_F(HasClientTest, test_discovery_has_features_ntf) {
  const RawAddress test_address = GetTestAddress(1);
  auto test_conn_id = GetTestConnId(test_address);