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

Commit b689e850 authored by Andre Eisenbach's avatar Andre Eisenbach Committed by Android (Google) Code Review
Browse files

Merge "DO NOT MERGE Add ability to add interop entries dynamically (2/2)" into mnc-dr-dev

parents ca82af2f 7a9c4389
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -50,9 +50,10 @@
#include "btsnoop.h"
#include "btsnoop_mem.h"
#include "bt_utils.h"
#include "osi/include/osi.h"
#include "device/include/interop.h"
#include "osi/include/allocation_tracker.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
#include "stack_manager.h"
#include "btif_config.h"

@@ -456,7 +457,9 @@ static const bt_interface_t bluetoothInterface = {
    set_os_callouts,
    read_energy_info,
    dump,
    config_clear
    config_clear,
    interop_database_clear,
    interop_database_add,
};

const bt_interface_t* bluetooth__get_bluetooth_interface ()
+12 −2
Original line number Diff line number Diff line
@@ -22,11 +22,13 @@

#include "btcore/include/bdaddr.h"

static const char INTEROP_MODULE[] = "interop_module";

typedef enum {
  // Disable secure connections
  // This is for pre BT 4.1/2 devices that do not handle secure mode
  // very well.
  INTEROP_DISABLE_LE_SECURE_CONNECTIONS,
  INTEROP_DISABLE_LE_SECURE_CONNECTIONS = 0,

  // Some devices have proven problematic during the pairing process, often
  // requiring multiple retries to complete pairing. To avoid degrading the user
@@ -38,5 +40,13 @@ typedef enum {
// Check if a given |addr| matches a known interoperability workaround as identified
// by the |interop_feature_t| enum. This API is used for simple address based lookups
// where more information is not available. No look-ups or random address resolution
// is performed on |addr|.
// are performed on |addr|.
bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr);

// Add a dynamic interop database entry for a device matching the first |length| bytes
// of |addr|, implementing the workaround identified by |feature|. |addr| may not be
// null and |length| must be greater than 0 and less than sizeof(bt_bdaddr_t).
void interop_database_add(const interop_feature_t feature, const bt_bdaddr_t *addr, size_t length);

// Clear the dynamic portion of the interoperability workaround database.
void interop_database_clear(void);
+1 −1
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@

typedef struct {
  bt_bdaddr_t addr;
  uint8_t len;
  size_t length;
  interop_feature_t feature;
} interop_entry_t;

+96 −6
Original line number Diff line number Diff line
@@ -21,13 +21,78 @@
#include <assert.h>
#include <string.h> // For memcmp

#include "btcore/include/module.h"
#include "device/include/interop.h"
#include "device/include/interop_database.h"
#include "osi/include/allocator.h"
#include "osi/include/list.h"
#include "osi/include/log.h"

#define CASE_RETURN_STR(const) case const: return #const;

static const char* interop_feature_string(const interop_feature_t feature) {
static list_t *interop_list = NULL;

static const char* interop_feature_string_(const interop_feature_t feature);
static void interop_free_entry_(void *data);
static void interop_lazy_init_(void);
static bool interop_match_fixed_(const interop_feature_t feature, const bt_bdaddr_t *addr);
static bool interop_match_dynamic_(const interop_feature_t feature, const bt_bdaddr_t *addr);

// Interface functions

bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr) {
  assert(addr);

  if (interop_match_fixed_(feature, addr) || interop_match_dynamic_(feature, addr)) {
    char bdstr[20] = {0};
    LOG_WARN("%s() Device %s is a match for interop workaround %s.",
          __func__, bdaddr_to_string(addr, bdstr, sizeof(bdstr)),
                        interop_feature_string_(feature));
    return true;
  }

  return false;
}

void interop_database_add(const interop_feature_t feature, const bt_bdaddr_t *addr, size_t length) {
  assert(addr);
  assert(length > 0);
  assert(length < sizeof(bt_bdaddr_t));

  interop_entry_t *entry = osi_calloc(sizeof(interop_entry_t));
  memcpy(&entry->addr, addr, length);
  entry->feature = feature;
  entry->length = length;

  interop_lazy_init_();
  list_append(interop_list, entry);
}

void interop_database_clear() {
  if (interop_list)
    list_clear(interop_list);
}

// Module life-cycle functions

static future_t *interop_clean_up(void) {
  list_free(interop_list);
  interop_list = NULL;
  return future_new_immediate(FUTURE_SUCCESS);
}

const module_t interop_module = {
  .name = INTEROP_MODULE,
  .init = NULL,
  .start_up = NULL,
  .shut_down = NULL,
  .clean_up = interop_clean_up,
  .dependencies = {NULL},
};

// Local functions

static const char* interop_feature_string_(const interop_feature_t feature) {
  switch (feature) {
    CASE_RETURN_STR(INTEROP_DISABLE_LE_SECURE_CONNECTIONS)
    CASE_RETURN_STR(INTEROP_AUTO_RETRY_PAIRING)
@@ -36,19 +101,44 @@ static const char* interop_feature_string(const interop_feature_t feature) {
  return "UNKNOWN";
}

// Interface functions
static void interop_free_entry_(void *data) {
  interop_entry_t *entry = (interop_entry_t *)data;
  osi_free(entry);
}

bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr) {
static void interop_lazy_init_(void) {
  if (interop_list == NULL) {
    interop_list = list_new(interop_free_entry_);
  }
}

static bool interop_match_dynamic_(const interop_feature_t feature, const bt_bdaddr_t *addr) {
  if (interop_list == NULL || list_length(interop_list) == 0)
    return false;

  const list_node_t *node = list_begin(interop_list);
  while (node != list_end(interop_list)) {
    interop_entry_t *entry = list_node(node);
    assert(entry);

    if (feature == entry->feature && memcmp(addr, &entry->addr, entry->length) == 0)
      return true;

    node = list_next(node);
  }
  return false;
}

static bool interop_match_fixed_(const interop_feature_t feature, const bt_bdaddr_t *addr) {
  assert(addr);

  const size_t db_size = sizeof(interop_database) / sizeof(interop_entry_t);

  for (size_t i = 0; i != db_size; ++i) {
    if (feature == interop_database[i].feature &&
        memcmp(addr, &interop_database[i].addr, interop_database[i].len) == 0) {
        memcmp(addr, &interop_database[i].addr, interop_database[i].length) == 0) {
      char bdstr[20] = {0};
      LOG_WARN("%s() Device %s is a match for interop workaround %s", __func__,
          bdaddr_to_string(addr, bdstr, sizeof(bdstr)), interop_feature_string(feature));
          bdaddr_to_string(addr, bdstr, sizeof(bdstr)), interop_feature_string_(feature));
      return true;
    }
  }
+20 −0
Original line number Diff line number Diff line
@@ -42,3 +42,23 @@ TEST(InteropTest, test_lookup_miss) {
  EXPECT_FALSE(interop_match(INTEROP_AUTO_RETRY_PAIRING, &test_address));
}

TEST(InteropTest, test_dynamic) {
  bt_bdaddr_t test_address;

  string_to_bdaddr("11:22:33:44:55:66", &test_address);
  EXPECT_FALSE(interop_match(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address));

  interop_database_add(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address, 3);
  EXPECT_TRUE(interop_match(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address));
  EXPECT_FALSE(interop_match(INTEROP_AUTO_RETRY_PAIRING, &test_address));

  string_to_bdaddr("66:55:44:33:22:11", &test_address);
  EXPECT_FALSE(interop_match(INTEROP_AUTO_RETRY_PAIRING, &test_address));

  interop_database_add(INTEROP_AUTO_RETRY_PAIRING, &test_address, 3);
  EXPECT_TRUE(interop_match(INTEROP_AUTO_RETRY_PAIRING, &test_address));
  EXPECT_FALSE(interop_match(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address));

  interop_database_clear();
  EXPECT_FALSE(interop_match(INTEROP_AUTO_RETRY_PAIRING, &test_address));
}
Loading