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

Commit cd2e4182 authored by Himanshu Rawat's avatar Himanshu Rawat Committed by Automerger Merge Worker
Browse files

Merge "Disconnect before removing device" into main am: bf1f4c02

parents d28802b7 bf1f4c02
Loading
Loading
Loading
Loading
+176 −3
Original line number Original line Diff line number Diff line
@@ -205,6 +205,7 @@ static void bta_dm_deinit_cb(void) {
      alarm_free(bta_dm_cb.pm_timer[i].timer[j]);
      alarm_free(bta_dm_cb.pm_timer[i].timer[j]);
    }
    }
  }
  }
  bta_dm_cb.pending_removals.clear();
  bta_dm_cb = {};
  bta_dm_cb = {};
}
}


@@ -471,8 +472,8 @@ void bta_dm_process_remove_device(const RawAddress& bd_addr) {
  }
  }
}
}


/** Removes device, disconnects ACL link if required */
// TODO: Remove when flag wait_for_disconnect_before_unbond is shipped
void bta_dm_remove_device(const RawAddress& bd_addr) {
static void bta_dm_remove_device_(const RawAddress& bd_addr) {
  /* If ACL exists for the device in the remove_bond message*/
  /* If ACL exists for the device in the remove_bond message*/
  bool is_bd_addr_connected =
  bool is_bd_addr_connected =
          get_btm_client_interface().peer.BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE) ||
          get_btm_client_interface().peer.BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE) ||
@@ -564,6 +565,112 @@ void bta_dm_remove_device(const RawAddress& bd_addr) {
  }
  }
}
}


/** Removes device, disconnects ACL link if required */
void bta_dm_remove_device(const RawAddress& target) {
  if (!com::android::bluetooth::flags::wait_for_disconnect_before_unbond()) {
    bta_dm_remove_device_(target);
    return;
  }

  // Find all aliases and connection status on all transports
  RawAddress pseudo_addr = target;
  RawAddress identity_addr = target;
  bool le_connected = get_btm_client_interface().peer.BTM_ReadConnectedTransportAddress(
          &pseudo_addr, BT_TRANSPORT_LE);
  bool bredr_connected = get_btm_client_interface().peer.BTM_ReadConnectedTransportAddress(
          &identity_addr, BT_TRANSPORT_BR_EDR);
  /* If connection not found with identity address, check with pseudo address if different */
  if (!bredr_connected && identity_addr != pseudo_addr) {
    identity_addr = pseudo_addr;
    bredr_connected = get_btm_client_interface().peer.BTM_ReadConnectedTransportAddress(
            &identity_addr, BT_TRANSPORT_BR_EDR);
  }

  // Remove from LE allowlist
  if (!GATT_CancelConnect(0, pseudo_addr, false)) {
    if (identity_addr != pseudo_addr && !GATT_CancelConnect(0, identity_addr, false)) {
      log::warn("Unable to cancel GATT connect peer:{}", pseudo_addr);
    }
  }

  // Disconnect LE transport
  if (le_connected) {
    tBTM_STATUS status = btm_remove_acl(pseudo_addr, BT_TRANSPORT_LE);
    if (status != BTM_SUCCESS && identity_addr != pseudo_addr) {
      status = btm_remove_acl(identity_addr, BT_TRANSPORT_LE);
    }

    if (status != BTM_SUCCESS) {
      le_connected = false;
      log::error("Unable to disconnect LE connection {}", pseudo_addr);
    }
  }

  // Disconnect BR/EDR transport
  if (bredr_connected) {
    tBTM_STATUS status = btm_remove_acl(identity_addr, BT_TRANSPORT_BR_EDR);
    if (status != BTM_SUCCESS && identity_addr != pseudo_addr) {
      status = btm_remove_acl(pseudo_addr, BT_TRANSPORT_BR_EDR);
    }

    if (status != BTM_SUCCESS) {
      bredr_connected = false;
      log::error("Unable to disconnect BR/EDR connection {}", identity_addr);
    }
  }

  if (le_connected || bredr_connected) {
    // Wait for all transports to be disconnected
    tBTA_DM_REMOVE_PENDNIG node = {pseudo_addr, target, le_connected, bredr_connected};
    bta_dm_cb.pending_removals.push_back(node);
    log::info(
            "Waiting for disconnection over LE:{}, BR/EDR:{} for pseudo address: {}, identity "
            "address: {}",
            le_connected, bredr_connected, pseudo_addr, identity_addr);
  } else {
    // No existing connection, remove the device right away
    log::verbose("Not connected, remove the device {}", target);
    bta_dm_process_remove_device(identity_addr);
    if (identity_addr != pseudo_addr) {
      bta_dm_process_remove_device(pseudo_addr);
    }
  }
}

static void bta_dm_remove_on_disconnect(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
  for (auto it = bta_dm_cb.pending_removals.begin(); it != bta_dm_cb.pending_removals.end(); it++) {
    if (bd_addr == it->identity_addr || bd_addr == it->pseudo_addr) {
      if (transport == BT_TRANSPORT_BR_EDR) {
        it->bredr_connected = false;
      } else {
        it->le_connected = false;
      }

      if (!it->bredr_connected && !it->le_connected) {
        log::info("All transports disconnected, remove the device {}", bd_addr);
        bta_dm_process_remove_device(it->identity_addr);
        if (it->identity_addr != it->pseudo_addr) {
          bta_dm_process_remove_device(it->pseudo_addr);
        }
        bta_dm_cb.pending_removals.erase(it);
      } else {
        log::info("Awaiting {} disconnection over {}", it->le_connected ? "LE" : "BR/EDR", bd_addr);
      }
      break;
    }
  }
}

bool bta_dm_removal_pending(const RawAddress& bd_addr) {
  for (auto it : bta_dm_cb.pending_removals) {
    if (bd_addr == it.pseudo_addr || bd_addr == it.identity_addr) {
      return true;
    }
  }

  return false;
}

/*******************************************************************************
/*******************************************************************************
 *
 *
 * Function         bta_dm_local_name_cback
 * Function         bta_dm_local_name_cback
@@ -677,6 +784,23 @@ static tBTA_DM_PEER_DEVICE* allocate_device_for(const RawAddress& bd_addr,
}
}


static void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport, uint16_t acl_handle) {
static void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport, uint16_t acl_handle) {
  if (com::android::bluetooth::flags::wait_for_disconnect_before_unbond()) {
    // Disconnect if the device is being removed
    for (auto& it : bta_dm_cb.pending_removals) {
      if (bd_addr == it.identity_addr || bd_addr == it.pseudo_addr) {
        log::warn("ACL connected while removing the device {} transport: {}", bd_addr, transport);
        if (transport == BT_TRANSPORT_BR_EDR) {
          it.bredr_connected = true;
        } else {
          it.le_connected = true;
        }

        btm_remove_acl(bd_addr, transport);
        return;
      }
    }
  }

  auto device = allocate_device_for(bd_addr, transport);
  auto device = allocate_device_for(bd_addr, transport);
  if (device == nullptr) {
  if (device == nullptr) {
    log::warn("Unable to allocate device resources for new connection");
    log::warn("Unable to allocate device resources for new connection");
@@ -730,7 +854,8 @@ void BTA_dm_acl_up_failed(const RawAddress bd_addr, tBT_TRANSPORT transport, tHC
  do_in_main_thread(base::BindOnce(bta_dm_acl_up_failed, bd_addr, transport, status));
  do_in_main_thread(base::BindOnce(bta_dm_acl_up_failed, bd_addr, transport, status));
}
}


static void bta_dm_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
// TODO: Remove when flag wait_for_disconnect_before_unbond is shipped
static void bta_dm_acl_down_(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
  bool issue_unpair_cb = false;
  bool issue_unpair_cb = false;
  bool remove_device = false;
  bool remove_device = false;


@@ -810,6 +935,54 @@ static void bta_dm_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport)
  bta_dm_adjust_roles(true);
  bta_dm_adjust_roles(true);
}
}


static void bta_dm_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
  log::verbose("Device {} disconnected over transport {}", bd_addr, bt_transport_text(transport));
  if (!com::android::bluetooth::flags::wait_for_disconnect_before_unbond()) {
    bta_dm_acl_down_(bd_addr, transport);
    return;
  }

  for (uint8_t i = 0; i < bta_dm_cb.device_list.count; i++) {
    auto device = &bta_dm_cb.device_list.peer_device[i];
    if (device->peer_bdaddr == bd_addr && device->transport == transport) {
      // Move the last item into its place
      if (i + 1 < bta_dm_cb.device_list.count) {
        *device = bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count - 1];
      }
      bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count - 1] = {};
      break;
    }
  }

  if (bta_dm_cb.device_list.count > 0) {
    bta_dm_cb.device_list.count--;
  }
  if (transport == BT_TRANSPORT_LE && bta_dm_cb.device_list.le_count > 0) {
    bta_dm_cb.device_list.le_count--;
  }

  bta_dm_disc_acl_down(bd_addr, transport);
  if (bta_dm_cb.disabling && !BTM_GetNumAclLinks()) {
    /*
     * Start a timer to make sure that the profiles
     * get the disconnect event.
     */
    alarm_set_on_mloop(bta_dm_cb.disable_timer, BTA_DM_DISABLE_CONN_DOWN_TIMER_MS,
                       bta_dm_disable_conn_down_timer_cback, NULL);
  }

  if (bta_dm_acl_cb.p_acl_cback) {
    tBTA_DM_ACL conn{};
    conn.link_down.bd_addr = bd_addr;
    conn.link_down.transport_link_type = transport;

    bta_dm_acl_cb.p_acl_cback(BTA_DM_LINK_DOWN_EVT, &conn);
  }

  bta_dm_adjust_roles(true);
  bta_dm_remove_on_disconnect(bd_addr, transport);
}

void BTA_dm_acl_down(const RawAddress bd_addr, tBT_TRANSPORT transport) {
void BTA_dm_acl_down(const RawAddress bd_addr, tBT_TRANSPORT transport) {
  do_in_main_thread(base::BindOnce(bta_dm_acl_down, bd_addr, transport));
  do_in_main_thread(base::BindOnce(bta_dm_acl_down, bd_addr, transport));
}
}
+21 −0
Original line number Original line Diff line number Diff line
@@ -26,7 +26,9 @@


#include <base/strings/stringprintf.h>
#include <base/strings/stringprintf.h>
#include <bluetooth/log.h>
#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>


#include <list>
#include <string>
#include <string>
#include <vector>
#include <vector>


@@ -95,9 +97,21 @@ inline std::string device_info_text(tBTA_DM_DEV_INFO info) {
#define BTA_DM_PM_EXECUTE 3
#define BTA_DM_PM_EXECUTE 3
typedef uint8_t tBTA_DM_PM_REQ;
typedef uint8_t tBTA_DM_PM_REQ;


struct tBTA_DM_REMOVE_PENDNIG {
  RawAddress pseudo_addr;
  RawAddress identity_addr;
  bool le_connected;
  bool bredr_connected;
};

bool bta_dm_removal_pending(const RawAddress& bd_addr);

struct tBTA_DM_PEER_DEVICE {
struct tBTA_DM_PEER_DEVICE {
  RawAddress peer_bdaddr;
  RawAddress peer_bdaddr;

  // TODO: Remove when flag wait_for_disconnect_before_unbond is shipped
  tBTA_DM_CONN_STATE conn_state{tBTA_DM_CONN_STATE::BTA_DM_CONNECTED};
  tBTA_DM_CONN_STATE conn_state{tBTA_DM_CONN_STATE::BTA_DM_CONNECTED};

  tBTA_PREF_ROLES pref_role;
  tBTA_PREF_ROLES pref_role;
  bool in_use;
  bool in_use;


@@ -135,6 +149,11 @@ public:
  bool is_ssr_active() const { return info & BTA_DM_DI_USE_SSR; }
  bool is_ssr_active() const { return info & BTA_DM_DI_USE_SSR; }


  bool is_connected() const {
  bool is_connected() const {
    // Devices getting removed should be treated as disconnected
    if (com::android::bluetooth::flags::wait_for_disconnect_before_unbond() &&
        bta_dm_removal_pending(peer_bdaddr)) {
      return false;
    }
    return (conn_state == tBTA_DM_CONN_STATE::BTA_DM_CONNECTED);
    return (conn_state == tBTA_DM_CONN_STATE::BTA_DM_CONNECTED);
  }
  }


@@ -223,6 +242,8 @@ typedef struct {
  tBTA_CUSTOM_UUID bta_custom_uuid[BTA_EIR_SERVER_NUM_CUSTOM_UUID];
  tBTA_CUSTOM_UUID bta_custom_uuid[BTA_EIR_SERVER_NUM_CUSTOM_UUID];
#endif
#endif
  alarm_t* switch_delay_timer;
  alarm_t* switch_delay_timer;

  std::list<tBTA_DM_REMOVE_PENDNIG> pending_removals;
} tBTA_DM_CB;
} tBTA_DM_CB;


/* DI control block */
/* DI control block */