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

Commit fa94c14d authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Automerger Merge Worker
Browse files

Merge changes Ieaa26a0b,I177268b2,Ib324a3ec,I7eedc84c am: 32b81cf9

parents 783cd988 32b81cf9
Loading
Loading
Loading
Loading
+78 −32
Original line number Diff line number Diff line
@@ -343,11 +343,16 @@ class CsisClientImpl : public CsisClient {
      }

      /* In case of GATT ERROR */
      LOG(ERROR) << __func__ << " Incorrect write status "
                 << loghex((int)(status));
      LOG_ERROR("Incorrect write status=0x%02x", (int)(status));

      /* Unlock previous devices */
      HandleCsisLockProcedureError(csis_group, device);

      if (status == GATT_DATABASE_OUT_OF_SYNC) {
        LOG_INFO("Database out of sync for %s",
                 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
        ClearDeviceInformationAndStartSearch(device);
      }
      return;
    }

@@ -848,6 +853,12 @@ class CsisClientImpl : public CsisClient {
      BtaGattQueue::Clean(conn_id);
      return;
    }

    if (status == GATT_DATABASE_OUT_OF_SYNC) {
      LOG_INFO("Database out of sync for %s",
               ADDRESS_TO_LOGGABLE_CSTR(device->addr));
      ClearDeviceInformationAndStartSearch(device);
    }
  }

  void OnCsisNotification(uint16_t conn_id, uint16_t handle, uint16_t len,
@@ -964,13 +975,18 @@ class CsisClientImpl : public CsisClient {
      return;
    }

    DLOG(INFO) << __func__ << " " << ADDRESS_TO_LOGGABLE_STR(device->addr)
               << " status: " << loghex(+status);
    LOG_DEBUG("%s, status: 0x%02x", ADDRESS_TO_LOGGABLE_CSTR(device->addr),
              status);

    if (status != GATT_SUCCESS) {
      LOG(ERROR) << __func__ << " Could not read characteristic at handle="
                 << loghex(handle);
      if (status == GATT_DATABASE_OUT_OF_SYNC) {
        LOG_INFO("Database out of sync for %s",
                 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
        ClearDeviceInformationAndStartSearch(device);
      } else {
        LOG_ERROR("Could not read characteristic at handle=0x%04x", handle);
        BTA_GATTC_Close(device->conn_id);
      }
      return;
    }

@@ -1008,13 +1024,18 @@ class CsisClientImpl : public CsisClient {
      return;
    }

    LOG(INFO) << __func__ << " " << ADDRESS_TO_LOGGABLE_STR(device->addr)
              << " status: " << loghex(+status);
    LOG_INFO("%s, status 0x%02x", ADDRESS_TO_LOGGABLE_CSTR(device->addr),
             status);

    if (status != GATT_SUCCESS) {
      LOG(ERROR) << __func__ << " Could not read characteristic at handle="
                 << loghex(handle);
      if (status == GATT_DATABASE_OUT_OF_SYNC) {
        LOG_INFO("Database out of sync for %s",
                 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
        ClearDeviceInformationAndStartSearch(device);
      } else {
        LOG_ERROR("Could not read characteristic at handle=0x%04x", handle);
        BTA_GATTC_Close(device->conn_id);
      }
      return;
    }

@@ -1043,13 +1064,18 @@ class CsisClientImpl : public CsisClient {
      return;
    }

    DLOG(INFO) << __func__ << " " << ADDRESS_TO_LOGGABLE_STR(device->addr)
               << " status: " << loghex(+status) << " rank:" << int(value[0]);
    LOG_DEBUG("%s, status: 0x%02x, rank: %d",
              ADDRESS_TO_LOGGABLE_CSTR(device->addr), status, value[0]);

    if (status != GATT_SUCCESS) {
      LOG(ERROR) << __func__ << " Could not read characteristic at handle="
                 << loghex(handle);
      if (status == GATT_DATABASE_OUT_OF_SYNC) {
        LOG_INFO("Database out of sync for %s",
                 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
        ClearDeviceInformationAndStartSearch(device);
      } else {
        LOG_ERROR("Could not read characteristic at handle=0x%04x", handle);
        BTA_GATTC_Close(device->conn_id);
      }
      return;
    }

@@ -1347,17 +1373,22 @@ class CsisClientImpl : public CsisClient {
      return;
    }

    DLOG(INFO) << __func__ << " " << ADDRESS_TO_LOGGABLE_STR(device->addr)
               << " status: " << loghex(+status);
    LOG_DEBUG("%s, status: 0x%02x", ADDRESS_TO_LOGGABLE_CSTR(device->addr),
              status);

    if (status != GATT_SUCCESS) {
      /* TODO handle error codes:
       * kCsisErrorCodeLockAccessSirkRejected
       * kCsisErrorCodeLockOobSirkOnly
       */
      LOG(ERROR) << __func__ << " Could not read characteristic at handle="
                 << loghex(handle);
      if (status == GATT_DATABASE_OUT_OF_SYNC) {
        LOG_INFO("Database out of sync for %s",
                 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
        ClearDeviceInformationAndStartSearch(device);
      } else {
        LOG_ERROR("Could not read characteristic at handle=0x%04x", handle);
        BTA_GATTC_Close(device->conn_id);
      }
      return;
    }

@@ -1452,9 +1483,7 @@ class CsisClientImpl : public CsisClient {
      CsisActiveDiscovery(csis_group);
  }

  void DoDisconnectCleanUp(std::shared_ptr<CsisDevice> device) {
    DLOG(INFO) << __func__ << ": device=" << ADDRESS_TO_LOGGABLE_STR(device->addr);

  void DeregisterNotifications(std::shared_ptr<CsisDevice> device) {
    device->ForEachCsisInstance(
        [&](const std::shared_ptr<CsisInstance>& csis_inst) {
          DisableGattNotification(device->conn_id, device->addr,
@@ -1464,6 +1493,12 @@ class CsisClientImpl : public CsisClient {
          DisableGattNotification(device->conn_id, device->addr,
                                  csis_inst->svc_data.size_handle.val_hdl);
        });
  }

  void DoDisconnectCleanUp(std::shared_ptr<CsisDevice> device) {
    LOG_INFO("%s", ADDRESS_TO_LOGGABLE_CSTR(device->addr));

    DeregisterNotifications(device);

    if (device->IsConnected()) {
      BtaGattQueue::Clean(device->conn_id);
@@ -1863,20 +1898,31 @@ class CsisClientImpl : public CsisClient {
    }
  }

  void OnGattServiceChangeEvent(const RawAddress& address) {
    auto device = FindDeviceByAddress(address);
    if (!device) {
      LOG(WARNING) << "Skipping unknown device"
                   << ADDRESS_TO_LOGGABLE_STR(address);
  void ClearDeviceInformationAndStartSearch(
      std::shared_ptr<CsisDevice> device) {
    LOG_INFO("%s ", ADDRESS_TO_LOGGABLE_CSTR(device->addr));
    if (device->is_gatt_service_valid == false) {
      LOG_DEBUG("Device database already invalidated.");
      return;
    }

    DLOG(INFO) << __func__ << ": address=" << ADDRESS_TO_LOGGABLE_STR(address);

    /* Invalidate service discovery results */
    BtaGattQueue::Clean(device->conn_id);
    device->first_connection = true;
    DeregisterNotifications(device);
    device->ClearSvcData();
    BTA_GATTC_ServiceSearchRequest(device->conn_id, &kCsisServiceUuid);
  }

  void OnGattServiceChangeEvent(const RawAddress& address) {
    auto device = FindDeviceByAddress(address);
    if (!device) {
      LOG(WARNING) << "Skipping unknown device" << address;
      return;
    }

    LOG_INFO("%s", ADDRESS_TO_LOGGABLE_CSTR(address));
    ClearDeviceInformationAndStartSearch(device);
  }

  void OnGattServiceDiscoveryDoneEvent(const RawAddress& address) {
+36 −0
Original line number Diff line number Diff line
@@ -1124,6 +1124,42 @@ TEST_F(CsisClientTest, test_storage_content) {
  TestAppUnregister();
}

TEST_F(CsisClientTest, test_database_out_of_sync) {
  auto test_address = GetTestAddress(0);
  auto conn_id = 1;

  TestAppRegister();
  SetSampleDatabaseCsis(conn_id, 1);
  TestConnect(test_address);
  InjectConnectedEvent(test_address, conn_id);
  GetSearchCompleteEvent(conn_id);
  ASSERT_EQ(1, CsisClient::Get()->GetGroupId(
                   test_address, bluetooth::Uuid::From16Bit(0x0000)));

  // Simulated database changed on the remote side.
  ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _))
      .WillByDefault(
          Invoke([this](uint16_t conn_id, uint16_t handle,
                        std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
                        GATT_WRITE_OP_CB cb, void* cb_data) {
            auto* svc = gatt::FindService(services_map[conn_id], handle);
            if (svc == nullptr) return;

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

  ON_CALL(gatt_interface, ServiceSearchRequest(_, _)).WillByDefault(Return());
  EXPECT_CALL(gatt_interface, ServiceSearchRequest(_, _));
  CsisClient::Get()->LockGroup(
      1, true,
      base::BindOnce([](int group_id, bool locked, CsisGroupLockStatus status) {
        csis_lock_callback_mock->CsisGroupLockCb(group_id, locked, status);
      }));
  TestAppUnregister();
}

}  // namespace
}  // namespace internal
}  // namespace csis
+86 −26
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ void btif_storage_set_leaudio_has_features(const RawAddress& address,
                                           uint8_t features);
void btif_storage_set_leaudio_has_active_preset(const RawAddress& address,
                                                uint8_t active_preset);
void btif_storage_remove_leaudio_has(const RawAddress& address);

extern bool gatt_profile_get_eatt_support(const RawAddress& remote_bda);

@@ -312,6 +313,12 @@ class HasClientImpl : public HasClient {
    auto op = op_opt.value();
    callbacks_->OnActivePresetSelectError(op.addr_or_group,
                                          GattStatus2SvcErrorCode(status));

    if (status == GATT_DATABASE_OUT_OF_SYNC) {
      LOG_INFO("Database out of sync for %s",
               ADDRESS_TO_LOGGABLE_CSTR(device->addr));
      ClearDeviceInformationAndStartSearch(device);
    }
  }

  void OnHasPresetNameSetStatus(uint16_t conn_id, tGATT_STATUS status,
@@ -342,6 +349,11 @@ class HasClientImpl : public HasClient {
    auto op = op_opt.value();
    callbacks_->OnSetPresetNameError(device->addr, op.index,
                                     GattStatus2SvcErrorCode(status));
    if (status == GATT_DATABASE_OUT_OF_SYNC) {
      LOG_INFO("Database out of sync for %s",
               ADDRESS_TO_LOGGABLE_CSTR(device->addr));
      ClearDeviceInformationAndStartSearch(device);
    }
  }

  void OnHasPresetNameGetStatus(uint16_t conn_id, tGATT_STATUS status,
@@ -370,9 +382,15 @@ class HasClientImpl : public HasClient {
    callbacks_->OnPresetInfoError(device->addr, op.index,
                                  GattStatus2SvcErrorCode(status));

    if (status == GATT_DATABASE_OUT_OF_SYNC) {
      LOG_INFO("Database out of sync for %s",
               ADDRESS_TO_LOGGABLE_CSTR(device->addr));
      ClearDeviceInformationAndStartSearch(device);
    } else {
      LOG_ERROR("Devices %s: Control point not usable. Disconnecting!",
                ADDRESS_TO_LOGGABLE_CSTR(device->addr));
    BTA_GATTC_Close(conn_id);
      BTA_GATTC_Close(device->conn_id);
    }
  }

  void OnHasPresetIndexOperation(uint16_t conn_id, tGATT_STATUS status,
@@ -412,9 +430,16 @@ class HasClientImpl : public HasClient {
      callbacks_->OnActivePresetSelectError(op.addr_or_group,
                                            GattStatus2SvcErrorCode(status));
    }

    if (status == GATT_DATABASE_OUT_OF_SYNC) {
      LOG_INFO("Database out of sync for %s",
               ADDRESS_TO_LOGGABLE_CSTR(device->addr));
      ClearDeviceInformationAndStartSearch(device);
    } else {
      LOG_ERROR("Devices %s: Control point not usable. Disconnecting!",
                ADDRESS_TO_LOGGABLE_CSTR(device->addr));
    BTA_GATTC_Close(conn_id);
      BTA_GATTC_Close(device->conn_id);
    }
  }

  void CpReadAllPresetsOperation(HasCtpOp operation) {
@@ -994,6 +1019,13 @@ class HasClientImpl : public HasClient {
      return;
    }

    if (status == GATT_DATABASE_OUT_OF_SYNC) {
      LOG_INFO("Database out of sync for %s",
               ADDRESS_TO_LOGGABLE_CSTR(device->addr));
      ClearDeviceInformationAndStartSearch(device);
      return;
    }

    HasGattOpContext context(user_data);
    bool enabling_ntf = context.context_flags &
                        HasGattOpContext::kContextFlagsEnableNotification;
@@ -1064,9 +1096,14 @@ class HasClientImpl : public HasClient {
    }

    if (status != GATT_SUCCESS) {
      LOG(ERROR) << __func__ << ": Could not read characteristic at handle="
                 << loghex(handle);
      if (status == GATT_DATABASE_OUT_OF_SYNC) {
        LOG_INFO("Database out of sync for %s",
                 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
        ClearDeviceInformationAndStartSearch(device);
      } else {
        LOG_ERROR("Could not read characteristic at handle=0x%04x", handle);
        BTA_GATTC_Close(device->conn_id);
      }
      return;
    }

@@ -1440,10 +1477,14 @@ class HasClientImpl : public HasClient {
    }

    if (status != GATT_SUCCESS) {
      LOG(ERROR) << __func__ << ": Could not read characteristic at handle="
                 << loghex(handle);
      if (status == GATT_DATABASE_OUT_OF_SYNC) {
        LOG_INFO("Database out of sync for %s",
                 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
        ClearDeviceInformationAndStartSearch(device);
      } else {
        LOG_ERROR("Could not read characteristic at handle=0x%04x", handle);
        BTA_GATTC_Close(device->conn_id);
      return;
      }
    }

    if (len != 1) {
@@ -1513,12 +1554,7 @@ class HasClientImpl : public HasClient {
    }
  }

  /* Cleans up after the device disconnection */
  void DoDisconnectCleanUp(HasDevice& device,
                           bool invalidate_gatt_service = true) {
    DLOG(INFO) << __func__ << ": device="
               << ADDRESS_TO_LOGGABLE_STR(device.addr);

  void DeregisterNotifications(HasDevice& device) {
    /* Deregister from optional features notifications */
    if (device.features_ccc_handle != GAP_INVALID_HANDLE) {
      BTA_GATTC_DeregisterForNotifications(gatt_if_, device.addr,
@@ -1536,6 +1572,14 @@ class HasClientImpl : public HasClient {
      BTA_GATTC_DeregisterForNotifications(gatt_if_, device.addr,
                                           device.cp_handle);
    }
  }

  /* Cleans up after the device disconnection */
  void DoDisconnectCleanUp(HasDevice& device,
                           bool invalidate_gatt_service = true) {
    LOG_DEBUG(": device=%s", ADDRESS_TO_LOGGABLE_CSTR(device.addr));

    DeregisterNotifications(device);

    if (device.conn_id != GATT_INVALID_CONN_ID) {
      BtaGattQueue::Clean(device.conn_id);
@@ -1954,20 +1998,36 @@ class HasClientImpl : public HasClient {
    }
  }

  void OnGattServiceChangeEvent(const RawAddress& address) {
    auto device = std::find_if(devices_.begin(), devices_.end(),
                               HasDevice::MatchAddress(address));
    if (device == devices_.end()) {
      LOG(WARNING) << "Skipping unknown device"
                   << ADDRESS_TO_LOGGABLE_STR(address);
  void ClearDeviceInformationAndStartSearch(HasDevice* device) {
    if (!device) {
      LOG_ERROR("Device is null");
      return;
    }

    DLOG(INFO) << __func__ << ": address=" << ADDRESS_TO_LOGGABLE_STR(address);
    LOG_INFO("%s", ADDRESS_TO_LOGGABLE_CSTR(device->addr));

    if (!device->isGattServiceValid()) {
      LOG_INFO("Service already invalidated");
      return;
    }

    /* Invalidate service discovery results */
    DeregisterNotifications(*device);
    BtaGattQueue::Clean(device->conn_id);
    device->ClearSvcData();
    btif_storage_remove_leaudio_has(device->addr);
    BTA_GATTC_ServiceSearchRequest(device->conn_id, &kUuidHearingAccessService);
  }

  void OnGattServiceChangeEvent(const RawAddress& address) {
    auto device = std::find_if(devices_.begin(), devices_.end(),
                               HasDevice::MatchAddress(address));
    if (device == devices_.end()) {
      LOG(WARNING) << "Skipping unknown device" << address;
      return;
    }
    LOG_INFO("%s", ADDRESS_TO_LOGGABLE_CSTR(address));
    ClearDeviceInformationAndStartSearch(&(*device));
  }

  void OnGattServiceDiscoveryDoneEvent(const RawAddress& address) {
+43 −0
Original line number Diff line number Diff line
@@ -2926,6 +2926,49 @@ TEST_F(HasClientTest, test_dumpsys) {
  ASSERT_TRUE(SimpleJsonValidator(sv[1], &dumpsys_byte_cnt));
}

TEST_F(HasClientTest, test_connect_database_out_of_sync) {
  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);

  EXPECT_CALL(*callbacks, OnDeviceAvailable(
                              test_address,
                              bluetooth::has::kFeatureBitHearingAidTypeBanded |
                                  bluetooth::has::kFeatureBitWritablePresets |
                                  bluetooth::has::kFeatureBitDynamicPresets));
  EXPECT_CALL(*callbacks,
              OnConnectionState(ConnectionState::CONNECTED, test_address));
  TestConnect(test_address);

  ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _))
      .WillByDefault(
          Invoke([this](uint16_t conn_id, uint16_t handle,
                        std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
                        GATT_WRITE_OP_CB cb, void* cb_data) {
            auto* svc = gatt::FindService(services_map[conn_id], handle);
            if (svc == nullptr) return;

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

  ON_CALL(gatt_interface, ServiceSearchRequest(_, _)).WillByDefault(Return());
  EXPECT_CALL(gatt_interface, ServiceSearchRequest(_, _));
  HasClient::Get()->GetPresetInfo(test_address, 1);
}

class HasTypesTest : public ::testing::Test {
 protected:
  void SetUp(void) override { mock_function_count_map.clear(); }
+43 −8
Original line number Diff line number Diff line
@@ -1926,20 +1926,44 @@ class LeAudioClientImpl : public LeAudioClient {
    return iter == charac.descriptors.end() ? 0 : (*iter).handle;
  }

  void OnServiceChangeEvent(const RawAddress& address) {
    LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
  void ClearDeviceInformationAndStartSearch(LeAudioDevice* leAudioDevice) {
    if (!leAudioDevice) {
      DLOG(ERROR) << __func__
                  << ", skipping unknown leAudioDevice, address: "
                  << ADDRESS_TO_LOGGABLE_STR(address);
      LOG_WARN("leAudioDevice is null");
      return;
    }

    LOG_INFO("%s", ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));

    if (leAudioDevice->known_service_handles_ == false) {
      LOG_DEBUG("Database already invalidated");
      return;
    }

    LOG(INFO) << __func__ << ": address=" << ADDRESS_TO_LOGGABLE_STR(address);
    leAudioDevice->known_service_handles_ = false;
    leAudioDevice->csis_member_ = false;
    BtaGattQueue::Clean(leAudioDevice->conn_id_);
    DeregisterNotifications(leAudioDevice);

    if (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTED) {
      leAudioDevice->SetConnectionState(
          DeviceConnectState::CONNECTED_BY_USER_GETTING_READY);
    }

    btif_storage_remove_leaudio(leAudioDevice->address_);

    BTA_GATTC_ServiceSearchRequest(
        leAudioDevice->conn_id_,
        &le_audio::uuid::kPublishedAudioCapabilityServiceUuid);
  }

  void OnServiceChangeEvent(const RawAddress& address) {
    LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
    if (!leAudioDevice) {
      LOG_WARN("Skipping unknown leAudioDevice %s",
               ADDRESS_TO_LOGGABLE_CSTR(address));
      return;
    }
    ClearDeviceInformationAndStartSearch(leAudioDevice);
  }

  void OnMtuChanged(uint16_t conn_id, uint16_t mtu) {
@@ -2343,6 +2367,13 @@ class LeAudioClientImpl : public LeAudioClient {
      return;
    }

    if (status == GATT_DATABASE_OUT_OF_SYNC) {
      LOG_INFO("Database out of sync for %s, conn_id: 0x%04x",
               ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_), conn_id);
      ClearDeviceInformationAndStartSearch(leAudioDevice);
      return;
    }

    if (status == GATT_SUCCESS) {
      LOG(INFO) << __func__
                << ", successfully registered on ccc: " << loghex(hdl);
@@ -3939,14 +3970,18 @@ class LeAudioClientImpl : public LeAudioClient {
                                  void* data) {
    if (!instance) return;

    LeAudioDevice* leAudioDevice =
        instance->leAudioDevices_.FindByConnId(conn_id);

    if (status == GATT_SUCCESS) {
      instance->LeAudioCharValueHandle(conn_id, hdl, len, value);
    } else if (status == GATT_DATABASE_OUT_OF_SYNC) {
      instance->ClearDeviceInformationAndStartSearch(leAudioDevice);
      return;
    }

    /* We use data to keep notify connected flag. */
    if (data && !!PTR_TO_INT(data)) {
      LeAudioDevice* leAudioDevice =
          instance->leAudioDevices_.FindByConnId(conn_id);
      leAudioDevice->notify_connected_after_read_ = false;

      /* Update PACs and ASEs when all is read.*/
Loading