#include <base/location.h>
+#include <time.h>
#include <chrono>
#include <cstdint>
#include <functional>
#include <map>
#include <memory>
+#include <string>
#include "gd/common/bidi_queue.h"
#include "gd/common/bind.h"
+#include "gd/common/strings.h"
#include "gd/hci/acl_manager.h"
#include "gd/hci/acl_manager/acl_connection.h"
#include "gd/hci/acl_manager/classic_acl_connection.h"
#include "gd/hci/controller.h"
#include "gd/os/handler.h"
#include "gd/os/queue.h"
+#include "main/shim/dumpsys.h"
#include "main/shim/entry.h"
#include "main/shim/helpers.h"
+#include "stack/btm/btm_int_types.h"
#include "stack/include/acl_hci_link_interface.h"
#include "stack/include/ble_acl_interface.h"
#include "stack/include/btm_status.h"
#include "stack/include/sec_hci_link_interface.h"
+#include "stack/l2cap/l2c_int.h"
bt_status_t do_in_main_thread(const base::Location& from_here,
base::OnceClosure task);
}
};
+#define DUMPSYS_TAG "shim::legacy::l2cap"
+extern tL2C_CB l2cb;
+void DumpsysL2cap(int fd) {
+ LOG_DUMPSYS_TITLE(fd, DUMPSYS_TAG);
+ for (int i = 0; i < MAX_L2CAP_LINKS; i++) {
+ const tL2C_LCB& lcb = l2cb.lcb_pool[i];
+ if (!lcb.in_use) continue;
+ LOG_DUMPSYS(fd, "link_state:%s", link_state_text(lcb.link_state).c_str());
+ LOG_DUMPSYS(fd, "handle:0x%04x", lcb.Handle());
+
+ const tL2C_CCB* ccb = lcb.ccb_queue.p_first_ccb;
+ while (ccb != nullptr) {
+ LOG_DUMPSYS(
+ fd, " active channel lcid:0x%04x rcid:0x%04x is_ecoc:%s in_use:%s",
+ ccb->local_cid, ccb->remote_cid, common::ToString(ccb->ecoc).c_str(),
+ common::ToString(ccb->in_use).c_str());
+ ccb = ccb->p_next_ccb;
+ }
+ }
+}
+
+#undef DUMPSYS_TAG
+#define DUMPSYS_TAG "shim::legacy::acl"
+extern tBTM_CB btm_cb;
+void DumpsysAcl(int fd) {
+ const tACL_CB& acl_cb = btm_cb.acl_cb_;
+
+ LOG_DUMPSYS_TITLE(fd, DUMPSYS_TAG);
+
+ for (int i = 0; i < MAX_L2CAP_LINKS; i++) {
+ const tACL_CONN& acl_conn = acl_cb.acl_db[i];
+ const tBTM_PM_MCB& btm_pm_mcb = acl_cb.pm_mode_db[i];
+ if (!acl_conn.in_use) continue;
+
+ LOG_DUMPSYS(fd, " peer_le_features:%s",
+ bd_features_text(acl_conn.peer_le_features).c_str());
+ for (int j = 0; j < HCI_EXT_FEATURES_PAGE_MAX + 1; j++) {
+ LOG_DUMPSYS(fd, " peer_lmp_features[%d]:%s", j,
+ bd_features_text(acl_conn.peer_lmp_feature_pages[j]).c_str());
+ }
+ LOG_DUMPSYS(fd, "remote_addr:%s", acl_conn.remote_addr.ToString().c_str());
+ LOG_DUMPSYS(fd, " handle:0x%04x", acl_conn.hci_handle);
+ LOG_DUMPSYS(fd, " [le] active_remote_addr:%s",
+ acl_conn.active_remote_addr.ToString().c_str());
+ LOG_DUMPSYS(fd, " [le] conn_addr:%s",
+ acl_conn.conn_addr.ToString().c_str());
+ LOG_DUMPSYS(fd, " link_up_issued:%s",
+ (acl_conn.link_up_issued) ? "true" : "false");
+ LOG_DUMPSYS(fd, " transport:%s",
+ BtTransportText(acl_conn.transport).c_str());
+ LOG_DUMPSYS(fd, " flush_timeout:0x%04x",
+ acl_conn.flush_timeout_in_ticks);
+ LOG_DUMPSYS(fd, " [classic] link_policy:0x%x", acl_conn.link_policy);
+ LOG_DUMPSYS(fd, " link_super_tout:0x%04x", acl_conn.link_super_tout);
+ LOG_DUMPSYS(fd, " pkt_types_mask:0x%04x", acl_conn.pkt_types_mask);
+ LOG_DUMPSYS(fd, " disconnect_reason:0x%02x", acl_conn.disconnect_reason);
+ LOG_DUMPSYS(fd, " chg_ind:%s", (btm_pm_mcb.chg_ind) ? "true" : "false");
+ }
+}
+#undef DUMPSYS_TAG
+
+using Record = bluetooth::common::TimestampedEntry<std::string>;
+const std::string kTimeFormat("%Y-%m-%d %H:%M:%S");
+
+#define DUMPSYS_TAG "shim::legacy::btm"
+extern tBTM_CB btm_cb;
+void DumpsysBtm(int fd) {
+ LOG_DUMPSYS_TITLE(fd, DUMPSYS_TAG);
+ if (btm_cb.history_ != nullptr) {
+ std::vector<Record> history = btm_cb.history_->Pull();
+ for (auto& record : history) {
+ time_t then = record.timestamp / 1000;
+ struct tm tm;
+ localtime_r(&then, &tm);
+ auto s2 = common::StringFormatTime(kTimeFormat, tm);
+ LOG_DUMPSYS(fd, " %s.%03u %s", s2.c_str(),
+ static_cast<unsigned int>(record.timestamp % 1000),
+ record.entry.c_str());
+ }
+ }
+}
+#undef DUMPSYS_TAG
+
+void bluetooth::shim::legacy::Acl::Dump(int fd) const {
+ DumpsysAcl(fd);
+ DumpsysL2cap(fd);
+ DumpsysBtm(fd);
+}
+
bluetooth::shim::legacy::Acl::Acl(os::Handler* handler,
const acl_interface_t& acl_interface)
: handler_(handler), acl_interface_(acl_interface) {
LOG_DEBUG("Initiate the creation of a classic connection %s",
address.ToString().c_str());
GetAclManager()->CreateConnection(address);
+ btm_cb.history_->Push("%-32s: %s classic", "Initiated connection",
+ PRIVATE_ADDRESS(address));
}
void bluetooth::shim::legacy::Acl::CreateLeConnection(
GetAclManager()->CreateLeConnection(address_with_type);
LOG_DEBUG("Started Le device to connection %s",
address_with_type.ToString().c_str());
+ btm_cb.history_->Push("%-32s: %s le", "Initiated connection",
+ PRIVATE_ADDRESS(address_with_type));
}
void bluetooth::shim::legacy::Acl::CancelLeConnection(
const bluetooth::hci::AddressWithType& address_with_type) {
- LOG_DEBUG("Terminate and cancel a le connection %s",
- address_with_type.ToString().c_str());
GetAclManager()->CancelLeConnect(address_with_type);
+ LOG_DEBUG("Canceled le connection %s", address_with_type.ToString().c_str());
+ btm_cb.history_->Push("%-32s: %s le", "Cancelled connection",
+ PRIVATE_ADDRESS(address_with_type));
}
void bluetooth::shim::legacy::Acl::OnClassicLinkDisconnected(
HciHandle handle, hci::ErrorCode reason) {
LOG_DEBUG("Classic link disconnected handle:%hu reason:%s", handle,
ErrorCodeText(reason).c_str());
+ bluetooth::hci::Address remote_address =
+ pimpl_->handle_to_classic_connection_map_[handle]->GetRemoteAddress();
+ pimpl_->handle_to_classic_connection_map_.erase(handle);
TRY_POSTING_ON_MAIN(acl_interface_.connection.classic.on_disconnected,
ToLegacyHciErrorCode(hci::ErrorCode::SUCCESS), handle,
ToLegacyHciErrorCode(reason));
- pimpl_->handle_to_classic_connection_map_.erase(handle);
+ btm_cb.history_->Push("%-32s: %s classic reason:%s", "Disconnected",
+ PRIVATE_ADDRESS(remote_address),
+ ErrorCodeText(reason).c_str());
}
void bluetooth::shim::legacy::Acl::OnLeLinkDisconnected(HciHandle handle,
hci::ErrorCode reason) {
LOG_DEBUG("Le link disconnected handle:%hu reason:%s", handle,
ErrorCodeText(reason).c_str());
+ hci::AddressWithType remote_address_with_type =
+ pimpl_->handle_to_le_connection_map_[handle]->GetRemoteAddressWithType();
pimpl_->handle_to_le_connection_map_.erase(handle);
TRY_POSTING_ON_MAIN(acl_interface_.connection.le.on_disconnected,
ToLegacyHciErrorCode(hci::ErrorCode::SUCCESS), handle,
ToLegacyHciErrorCode(reason));
- pimpl_->handle_to_le_connection_map_.erase(handle);
+ btm_cb.history_->Push("%-32s: %s le reason:%s", "Disconnected",
+ PRIVATE_ADDRESS(remote_address_with_type),
+ ErrorCodeText(reason).c_str());
}
void bluetooth::shim::legacy::Acl::OnConnectSuccess(
std::unique_ptr<hci::acl_manager::ClassicAclConnection> connection) {
ASSERT(connection != nullptr);
auto handle = connection->GetHandle();
+ bool locally_initiated = connection->locally_initiated_;
const RawAddress bd_addr = ToRawAddress(connection->GetAddress());
pimpl_->handle_to_classic_connection_map_.emplace(
TRY_POSTING_ON_MAIN(acl_interface_.connection.classic.on_connected, bd_addr,
handle, HCI_SUCCESS, false);
+ btm_cb.history_->Push(
+ "%-32s: %s %s classic", "Connection successful", PRIVATE_ADDRESS(bd_addr),
+ (locally_initiated) ? "Local initiated" : "Remote initiated");
}
void bluetooth::shim::legacy::Acl::OnConnectFail(hci::Address address,
hci::ErrorCode reason) {
const RawAddress bd_addr = ToRawAddress(address);
- LOG_WARN("Classic ACL connection failed peer:%s reason:%s",
- address.ToString().c_str(), hci::ErrorCodeText(reason).c_str());
TRY_POSTING_ON_MAIN(acl_interface_.connection.classic.on_failed, bd_addr,
kInvalidHciHandle, HCI_SUCCESS, false);
+ LOG_WARN("Classic ACL connection failed peer:%s reason:%s",
+ address.ToString().c_str(), hci::ErrorCodeText(reason).c_str());
+ btm_cb.history_->Push("%-32s: %s classic reason:%s", "Connection failed",
+ PRIVATE_ADDRESS(address),
+ hci::ErrorCodeText(reason).c_str());
}
void bluetooth::shim::legacy::Acl::OnLeConnectSuccess(
auto handle = connection->GetHandle();
bluetooth::hci::Role connection_role = connection->GetRole();
+ bool locally_initiated = connection->locally_initiated_;
pimpl_->handle_to_le_connection_map_.emplace(
handle, std::make_unique<LeShimAclConnection>(
acl_interface_.connection.le.on_connected, legacy_address_with_type,
handle, static_cast<uint8_t>(connection_role), conn_interval,
conn_latency, conn_timeout, local_rpa, peer_rpa, peer_addr_type);
+
+ btm_cb.history_->Push(
+ "%-32s: %s %s le", "Connection successful",
+ PRIVATE_ADDRESS(address_with_type),
+ (locally_initiated) ? "Local Initiate" : "Remote initiate");
}
void bluetooth::shim::legacy::Acl::OnLeConnectFail(
hci::AddressWithType address_with_type, hci::ErrorCode reason) {
- LOG_WARN("Le ACL failed peer:%s", address_with_type.ToString().c_str());
-
tBLE_BD_ADDR legacy_address_with_type =
ToLegacyAddressWithType(address_with_type);
TRY_POSTING_ON_MAIN(acl_interface_.connection.le.on_failed,
legacy_address_with_type, handle, enhanced, status);
+ LOG_WARN("Le ACL failed peer:%s", address_with_type.ToString().c_str());
+ btm_cb.history_->Push("%-32s: %s le reason:%s", "Connection failed",
+ PRIVATE_ADDRESS(address_with_type),
+ hci::ErrorCodeText(reason).c_str());
}
void bluetooth::shim::legacy::Acl::ConfigureLePrivacy(