"--grpc-port=$(grpc_port)",
"--root-server-port=$(grpc_root_server_port)",
"--btsnoop=/data/misc/bluetooth/logs/btsnoop_hci.log",
+ "--btsnooz=/data/misc/bluetooth/logs/btsnooz_hci.log",
"--btconfig=/data/misc/bluedroid/bt_config.conf",
"--signal-port=$(signal_port)"
]
"--grpc-port=$(grpc_port)",
"--root-server-port=$(grpc_root_server_port)",
"--btsnoop=/data/misc/bluetooth/logs/btsnoop_hci.log",
+ "--btsnooz=/data/misc/bluetooth/logs/btsnooz_hci.log",
"--btconfig=/data/misc/bluedroid/bt_config.conf",
"--signal-port=$(signal_port)"
]
'%s_%s_backing_logs.txt' % (self.type_identifier, self.label))
if "--btsnoop=" not in " ".join(cmd):
cmd.append("--btsnoop=%s" % os.path.join(self.log_path_base, '%s_btsnoop_hci.log' % self.label))
+ if "--btsnooz=" not in " ".join(cmd):
+ cmd.append("--btsnooz=%s" % os.path.join(self.log_path_base, '%s_btsnooz_hci.log' % self.label))
if "--btconfig=" not in " ".join(cmd):
cmd.append("--btconfig=%s" % os.path.join(self.log_path_base, '%s_bt_config.conf' % self.label))
self.cmd = cmd
logging.error("Error during setup: " + str(error))
try:
+ self.adb.shell("rm /data/misc/bluetooth/logs/btsnooz_hci.log")
+ except AdbCommandError as error:
+ logging.error("Error during setup: " + str(error))
+
+ try:
self.adb.shell("rm /data/misc/bluedroid/bt_config.conf")
except AdbCommandError as error:
- logging.error("Error during cleanup: " + str(error))
+ logging.error("Error during setup: " + str(error))
try:
self.adb.shell("rm /data/misc/bluedroid/bt_config.bak")
except AdbCommandError as error:
- logging.error("Error during cleanup: " + str(error))
+ logging.error("Error during setup: " + str(error))
self.ensure_no_output(self.adb.shell("svc bluetooth disable"))
const std::string arg_rootcanal_port = "--rootcanal-port=";
const std::string arg_signal_port = "--signal-port=";
const std::string arg_btsnoop_path = "--btsnoop=";
+ const std::string arg_btsnooz_path = "--btsnooz=";
const std::string arg_btconfig_path = "--btconfig=";
for (int i = 1; i < argc; i++) {
std::string arg = argv[i];
CHECK(::bluetooth::os::SetSystemProperty(
::bluetooth::hal::SnoopLogger::kBtSnoopLogModeProperty, ::bluetooth::hal::SnoopLogger::kBtSnoopLogModeFull));
}
+ if (arg.find(arg_btsnooz_path) == 0) {
+ auto btsnooz_path = arg.substr(arg_btsnooz_path.size());
+ ::bluetooth::os::ParameterProvider::OverrideSnoozLogFilePath(btsnooz_path);
+ }
if (arg.find(arg_btconfig_path) == 0) {
auto btconfig_path = arg.substr(arg_btconfig_path.size());
::bluetooth::os::ParameterProvider::OverrideConfigFilePath(btconfig_path);
#include <arpa/inet.h>
#include <sys/stat.h>
+#include <algorithm>
#include <bitset>
#include <chrono>
+#include <sstream>
+#include "common/circular_buffer.h"
#include "common/strings.h"
#include "os/files.h"
#include "os/log.h"
// the relevant system property
constexpr size_t kDefaultBtSnoopMaxPacketsPerFile = 0xffff;
-std::string get_btsnoop_log_path(std::string btsnoop_path, bool filtered) {
+// We want to use at most 256 KB memory for btsnooz log
+constexpr size_t kDefaultBtsnoozMaxMemoryUsageBytes = 256 * 1024;
+// We restrict the maximum packet size to 150 bytes
+constexpr size_t kDefaultBtSnoozMaxBytesPerPacket = 150;
+constexpr size_t kDefaultBtSnoozMaxPayloadBytesPerPacket =
+ kDefaultBtSnoozMaxBytesPerPacket - sizeof(SnoopLogger::PacketHeaderType);
+// Calculate max number of packets based on max memory usage and max packet size
+constexpr size_t kDefaultBtSnoozMaxPacketsPerBuffer =
+ kDefaultBtsnoozMaxMemoryUsageBytes / kDefaultBtSnoozMaxBytesPerPacket;
+
+std::string get_btsnoop_log_path(std::string log_dir, bool filtered) {
if (filtered) {
- return btsnoop_path.append(".filtered");
+ log_dir.append(".filtered");
}
- return btsnoop_path;
+ return log_dir;
}
-std::string get_btsnoop_last_log_path(std::string btsnoop_path) {
- return btsnoop_path.append(".last");
+std::string get_last_log_path(std::string log_file_path) {
+ return log_file_path.append(".last");
}
void delete_btsnoop_files(const std::string& log_path) {
- LOG_INFO("Deleting snoop logs if they exist");
+ LOG_INFO("Deleting logs if they exist");
if (os::FileExists(log_path)) {
if (!os::RemoveFile(log_path)) {
- LOG_ERROR("Failed to remove main snoop log faile at \"%s\"", log_path.c_str());
+ LOG_ERROR("Failed to remove main log file at \"%s\"", log_path.c_str());
}
} else {
- LOG_INFO("Main snoop log file does not exist at \"%s\"", log_path.c_str());
+ LOG_INFO("Main log file does not exist at \"%s\"", log_path.c_str());
}
- auto last_log_path = get_btsnoop_last_log_path(log_path);
+ auto last_log_path = get_last_log_path(log_path);
if (os::FileExists(last_log_path)) {
if (!os::RemoveFile(last_log_path)) {
- LOG_ERROR("Failed to remove last snoop log faile at \"%s\"", log_path.c_str());
+ LOG_ERROR("Failed to remove last log file at \"%s\"", log_path.c_str());
}
} else {
- LOG_INFO("Last snoop log file does not exist at \"%s\"", log_path.c_str());
+ LOG_INFO("Last log file does not exist at \"%s\"", log_path.c_str());
}
}
+size_t get_btsnooz_packet_length_to_write(const HciPacket& packet, SnoopLogger::PacketType type) {
+ static const size_t kAclHeaderSize = 4;
+ static const size_t kL2capHeaderSize = 4;
+ static const size_t kL2capCidOffset = (kAclHeaderSize + 2);
+ static const uint16_t kL2capSignalingCid = 0x0001;
+
+ // Maximum amount of ACL data to log.
+ // Enough for an RFCOMM frame up to the frame check;
+ // not enough for a HID report or audio data.
+ static const size_t kMaxBtsnoozAclSize = 14;
+
+ // Calculate packet length to be included
+ size_t included_length = 0;
+ switch (type) {
+ case SnoopLogger::PacketType::CMD:
+ case SnoopLogger::PacketType::EVT:
+ included_length = packet.size();
+ break;
+
+ case SnoopLogger::PacketType::ACL: {
+ // Log ACL and L2CAP header by default
+ size_t len_hci_acl = kAclHeaderSize + kL2capHeaderSize;
+ // Check if we have enough data for an L2CAP header
+ if (packet.size() > len_hci_acl) {
+ uint16_t l2cap_cid =
+ static_cast<uint16_t>(packet[kL2capCidOffset]) |
+ static_cast<uint16_t>((static_cast<uint16_t>(packet[kL2capCidOffset + 1]) << static_cast<uint16_t>(8)));
+ if (l2cap_cid == kL2capSignalingCid) {
+ // For the signaling CID, take the full packet.
+ // That way, the PSM setup is captured, allowing decoding of PSMs down
+ // the road.
+ return packet.size();
+ } else {
+ // Otherwise, return as much as we reasonably can
+ len_hci_acl = kMaxBtsnoozAclSize;
+ }
+ }
+ included_length = std::min(len_hci_acl, packet.size());
+ break;
+ }
+
+ case SnoopLogger::PacketType::ISO:
+ case SnoopLogger::PacketType::SCO:
+ default:
+ // We are not logging SCO and ISO packets in snooz log as they may contain voice data
+ break;
+ }
+ return std::min(included_length, kDefaultBtSnoozMaxPayloadBytesPerPacket);
+}
+
} // namespace
const std::string SnoopLogger::kBtSnoopLogModeDisabled = "disabled";
const std::string SnoopLogger::kBtSnoopLogModeProperty = "persist.bluetooth.btsnooplogmode";
const std::string SnoopLogger::kBtSnoopDefaultLogModeProperty = "persist.bluetooth.btsnoopdefaultmode";
-SnoopLogger::SnoopLogger(std::string log_path, size_t max_packets_per_file, const std::string& btsnoop_mode)
- : file_path_(std::move(log_path)), max_packets_per_file_(max_packets_per_file) {
+SnoopLogger::SnoopLogger(
+ std::string snoop_log_path,
+ std::string snooz_log_path,
+ size_t max_packets_per_file,
+ const std::string& btsnoop_mode)
+ : snoop_log_path_(std::move(snoop_log_path)),
+ snooz_log_path_(std::move(snooz_log_path)),
+ max_packets_per_file_(max_packets_per_file),
+ btsnooz_buffer_(kDefaultBtSnoozMaxPacketsPerBuffer) {
if (false && btsnoop_mode == kBtSnoopLogModeFiltered) {
// TODO(b/163733538): implement filtered snoop log in GD, currently filtered == disabled
LOG_INFO("Filtered Snoop Logs enabled");
is_enabled_ = true;
is_filtered_ = true;
// delete unfiltered logs
- delete_btsnoop_files(get_btsnoop_log_path(file_path_, false));
+ delete_btsnoop_files(get_btsnoop_log_path(snoop_log_path_, false));
+ // delete snooz logs
+ delete_btsnoop_files(snooz_log_path_);
} else if (btsnoop_mode == kBtSnoopLogModeFull) {
LOG_INFO("Snoop Logs fully enabled");
is_enabled_ = true;
is_filtered_ = false;
// delete filtered logs
- delete_btsnoop_files(get_btsnoop_log_path(file_path_, true));
+ delete_btsnoop_files(get_btsnoop_log_path(snoop_log_path_, true));
+ // delete snooz logs
+ delete_btsnoop_files(snooz_log_path_);
} else {
LOG_INFO("Snoop Logs disabled");
is_enabled_ = false;
is_filtered_ = false;
// delete both filtered and unfiltered logs
- delete_btsnoop_files(get_btsnoop_log_path(file_path_, true));
- delete_btsnoop_files(get_btsnoop_log_path(file_path_, false));
+ delete_btsnoop_files(get_btsnoop_log_path(snoop_log_path_, true));
+ delete_btsnoop_files(get_btsnoop_log_path(snoop_log_path_, false));
}
// Add ".filtered" extension if necessary
- file_path_ = get_btsnoop_log_path(file_path_, is_filtered_);
+ snoop_log_path_ = get_btsnoop_log_path(snoop_log_path_, is_filtered_);
}
void SnoopLogger::CloseCurrentSnoopLogFile() {
std::lock_guard<std::recursive_mutex> lock(file_mutex_);
CloseCurrentSnoopLogFile();
- auto last_file_path = get_btsnoop_last_log_path(file_path_);
+ auto last_file_path = get_last_log_path(snoop_log_path_);
- if (os::FileExists(file_path_)) {
- if (!os::RenameFile(file_path_, last_file_path)) {
+ if (os::FileExists(snoop_log_path_)) {
+ if (!os::RenameFile(snoop_log_path_, last_file_path)) {
LOG_ERROR(
- "Unabled to rename existing snoop log from \"%s\" to \"%s\"", file_path_.c_str(), last_file_path.c_str());
+ "Unabled to rename existing snoop log from \"%s\" to \"%s\"",
+ snoop_log_path_.c_str(),
+ last_file_path.c_str());
}
} else {
- LOG_INFO("Previous log file \"%s\" does not exist, skip renaming", file_path_.c_str());
+ LOG_INFO("Previous log file \"%s\" does not exist, skip renaming", snoop_log_path_.c_str());
}
mode_t prevmask = umask(0);
// do not use std::ios::app as we want override the existing file
- btsnoop_ostream_.open(file_path_, std::ios::binary | std::ios::out);
+ btsnoop_ostream_.open(snoop_log_path_, std::ios::binary | std::ios::out);
if (!btsnoop_ostream_.good()) {
- LOG_ALWAYS_FATAL("Unable to open snoop log at \"%s\", error: \"%s\"", file_path_.c_str(), strerror(errno));
+ LOG_ALWAYS_FATAL("Unable to open snoop log at \"%s\", error: \"%s\"", snoop_log_path_.c_str(), strerror(errno));
}
umask(prevmask);
if (!btsnoop_ostream_.write(reinterpret_cast<const char*>(&kBtSnoopFileHeader), sizeof(FileHeaderType))) {
- LOG_ALWAYS_FATAL("Unable to write file header to \"%s\", error: \"%s\"", file_path_.c_str(), strerror(errno));
+ LOG_ALWAYS_FATAL("Unable to write file header to \"%s\", error: \"%s\"", snoop_log_path_.c_str(), strerror(errno));
}
if (!btsnoop_ostream_.flush()) {
LOG_ERROR("Failed to flush, error: \"%s\"", strerror(errno));
}
void SnoopLogger::Capture(const HciPacket& packet, Direction direction, PacketType type) {
- if (!is_enabled_) {
- // btsnoop disabled
- return;
- }
uint64_t timestamp_us =
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch())
.count();
.type = static_cast<uint8_t>(type)};
{
std::lock_guard<std::recursive_mutex> lock(file_mutex_);
+ if (!is_enabled_) {
+ // btsnoop disabled, log in-memory btsnooz log only
+ std::stringstream ss;
+ size_t included_length = get_btsnooz_packet_length_to_write(packet, type);
+ header.length_captured = htonl(included_length + /* type byte */ 1);
+ if (!ss.write(reinterpret_cast<const char*>(&header), sizeof(PacketHeaderType))) {
+ LOG_ERROR("Failed to write packet header for btsnooz, error: \"%s\"", strerror(errno));
+ }
+ if (!ss.write(reinterpret_cast<const char*>(packet.data()), included_length)) {
+ LOG_ERROR("Failed to write packet payload for btsnooz, error: \"%s\"", strerror(errno));
+ }
+ btsnooz_buffer_.Push(ss.str());
+ return;
+ }
packet_counter_++;
if (packet_counter_ > max_packets_per_file_) {
OpenNextSnoopLogFile();
}
if (!btsnoop_ostream_.write(reinterpret_cast<const char*>(&header), sizeof(PacketHeaderType))) {
- LOG_ERROR("Failed to write packet header, error: \"%s\"", strerror(errno));
+ LOG_ERROR("Failed to write packet header for btsnoop, error: \"%s\"", strerror(errno));
}
if (!btsnoop_ostream_.write(reinterpret_cast<const char*>(packet.data()), packet.size())) {
- LOG_ERROR("Failed to write packet payload, error: \"%s\"", strerror(errno));
+ LOG_ERROR("Failed to write packet payload for btsnoop, error: \"%s\"", strerror(errno));
}
// std::ofstream::flush() pushes user data into kernel memory. The data will be written even if this process
// crashes. However, data will be lost if there is a kernel panic, which is out of scope of BT snoop log.
}
}
+void SnoopLogger::DumpSnoozLogToFile(const std::vector<std::string>& data) const {
+ std::lock_guard<std::recursive_mutex> lock(file_mutex_);
+ if (is_enabled_) {
+ LOG_DEBUG("btsnoop log is enabled, skip dumping btsnooz log");
+ return;
+ }
+
+ auto last_file_path = get_last_log_path(snooz_log_path_);
+
+ if (os::FileExists(snooz_log_path_)) {
+ if (!os::RenameFile(snooz_log_path_, last_file_path)) {
+ LOG_ERROR(
+ "Unabled to rename existing snooz log from \"%s\" to \"%s\"",
+ snooz_log_path_.c_str(),
+ last_file_path.c_str());
+ }
+ } else {
+ LOG_INFO("Previous log file \"%s\" does not exist, skip renaming", snooz_log_path_.c_str());
+ }
+
+ mode_t prevmask = umask(0);
+ // do not use std::ios::app as we want override the existing file
+ std::ofstream btsnooz_ostream(snooz_log_path_, std::ios::binary | std::ios::out);
+ if (!btsnooz_ostream.good()) {
+ LOG_ALWAYS_FATAL("Unable to open snoop log at \"%s\", error: \"%s\"", snooz_log_path_.c_str(), strerror(errno));
+ }
+ umask(prevmask);
+ if (!btsnooz_ostream.write(reinterpret_cast<const char*>(&kBtSnoopFileHeader), sizeof(FileHeaderType))) {
+ LOG_ALWAYS_FATAL("Unable to write file header to \"%s\", error: \"%s\"", snooz_log_path_.c_str(), strerror(errno));
+ }
+ for (const auto& packet : data) {
+ if (!btsnooz_ostream.write(packet.data(), packet.size())) {
+ LOG_ERROR("Failed to write packet payload for btsnooz, error: \"%s\"", strerror(errno));
+ }
+ }
+ if (!btsnooz_ostream.flush()) {
+ LOG_ERROR("Failed to flush, error: \"%s\"", strerror(errno));
+ }
+}
+
void SnoopLogger::ListDependencies(ModuleList* list) {
// We have no dependencies
}
void SnoopLogger::Stop() {
std::lock_guard<std::recursive_mutex> lock(file_mutex_);
+ LOG_DEBUG("Dumping btsnooz log data to %s", snooz_log_path_.c_str());
+ DumpSnoozLogToFile(btsnooz_buffer_.Drain());
+ LOG_DEBUG("Closing btsnoop log data at %s", snoop_log_path_.c_str());
CloseCurrentSnoopLogFile();
}
+DumpsysDataFinisher SnoopLogger::GetDumpsysData(flatbuffers::FlatBufferBuilder* builder) const {
+ LOG_DEBUG("Dumping btsnooz log data to %s", snooz_log_path_.c_str());
+ DumpSnoozLogToFile(btsnooz_buffer_.Pull());
+ return Module::GetDumpsysData(builder);
+}
+
size_t SnoopLogger::GetMaxPacketsPerFile() {
// Allow override max packet per file via system property
auto max_packets_per_file = kDefaultBtSnoopMaxPacketsPerFile;
}
const ModuleFactory SnoopLogger::Factory = ModuleFactory([]() {
- return new SnoopLogger(os::ParameterProvider::SnoopLogFilePath(), GetMaxPacketsPerFile(), GetBtSnoopMode());
+ return new SnoopLogger(
+ os::ParameterProvider::SnoopLogFilePath(),
+ os::ParameterProvider::SnoozLogFilePath(),
+ GetMaxPacketsPerFile(),
+ GetBtSnoopMode());
});
} // namespace hal
#include <mutex>
#include <string>
+#include "common/circular_buffer.h"
#include "hal/hci_hal.h"
#include "module.h"
void ListDependencies(ModuleList* list) override;
void Start() override;
void Stop() override;
+ DumpsysDataFinisher GetDumpsysData(flatbuffers::FlatBufferBuilder* builder) const override;
// Visible for testing
- SnoopLogger(std::string log_path, size_t max_packets_per_file, const std::string& btsnoop_mode);
+ SnoopLogger(
+ std::string snoop_log_path,
+ std::string snooz_log_path,
+ size_t max_packets_per_file,
+ const std::string& btsnoop_mode);
void CloseCurrentSnoopLogFile();
void OpenNextSnoopLogFile();
+ void DumpSnoozLogToFile(const std::vector<std::string>& data) const;
private:
- std::string file_path_;
+ std::string snoop_log_path_;
+ std::string snooz_log_path_;
std::ofstream btsnoop_ostream_;
bool is_enabled_ = false;
bool is_filtered_ = false;
size_t max_packets_per_file_;
+ common::CircularBuffer<std::string> btsnooz_buffer_;
size_t packet_counter_ = 0;
- std::recursive_mutex file_mutex_;
+ mutable std::recursive_mutex file_mutex_;
};
} // namespace hal
0x02,
0x00,
};
-}
+
+std::vector<uint8_t> kSdpConnectionRequest = {
+ 0x08, 0x20, 0x0c, 0x00, 0x08, 0x00, 0x01, 0x00, 0x02, 0x0c, 0x04, 0x00, 0x01, 0x00, 0x44, 0x00};
+
+std::vector<uint8_t> kAvdtpSuspend = {0x02, 0x02, 0x00, 0x07, 0x00, 0x03, 0x00, 0x8d, 0x00, 0x90, 0x09, 0x04};
+
+std::vector<uint8_t> kHfpAtNrec0 = {0x02, 0x02, 0x20, 0x13, 0x00, 0x0f, 0x00, 0x41, 0x00, 0x09, 0xff, 0x15,
+ 0x01, 0x41, 0x54, 0x2b, 0x4e, 0x52, 0x45, 0x43, 0x3d, 0x30, 0x0d, 0x5c};
+
+} // namespace
using bluetooth::TestModuleRegistry;
using bluetooth::hal::SnoopLogger;
// Expose protected constructor for test
class TestSnoopLoggerModule : public SnoopLogger {
public:
- TestSnoopLoggerModule(std::string log_path, size_t max_packets_per_file, const std::string& btsnoop_mode)
- : SnoopLogger(std::move(log_path), max_packets_per_file, btsnoop_mode) {}
+ TestSnoopLoggerModule(
+ std::string snoop_log_path,
+ std::string snooz_log_path,
+ size_t max_packets_per_file,
+ const std::string& btsnoop_mode)
+ : SnoopLogger(std::move(snoop_log_path), std::move(snooz_log_path), max_packets_per_file, btsnoop_mode) {}
};
class SnoopLoggerModuleTest : public Test {
temp_dir_ = std::filesystem::temp_directory_path();
temp_snoop_log_ = temp_dir_ / "btsnoop_hci.log";
temp_snoop_log_last_ = temp_dir_ / "btsnoop_hci.log.last";
+ temp_snooz_log_ = temp_dir_ / "btsnooz_hci.log";
+ temp_snooz_log_last_ = temp_dir_ / "btsnooz_hci.log.last";
DeleteSnoopLogFiles();
ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
+ ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
+ ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_last_));
}
void TearDown() override {
if (std::filesystem::exists(temp_snoop_log_last_)) {
ASSERT_TRUE(std::filesystem::remove(temp_snoop_log_last_));
}
+ if (std::filesystem::exists(temp_snooz_log_)) {
+ ASSERT_TRUE(std::filesystem::remove(temp_snooz_log_));
+ }
+ if (std::filesystem::exists(temp_snooz_log_last_)) {
+ ASSERT_TRUE(std::filesystem::remove(temp_snooz_log_last_));
+ }
}
std::filesystem::path temp_dir_;
std::filesystem::path temp_snoop_log_;
std::filesystem::path temp_snoop_log_last_;
+ std::filesystem::path temp_snooz_log_;
+ std::filesystem::path temp_snooz_log_last_;
};
TEST_F(SnoopLoggerModuleTest, empty_snoop_log_test) {
// Actual test
- auto* snoop_looger = new TestSnoopLoggerModule(temp_snoop_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull);
+ auto* snoop_looger = new TestSnoopLoggerModule(
+ temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull);
TestModuleRegistry test_registry;
test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);
test_registry.StopAll();
TEST_F(SnoopLoggerModuleTest, disable_snoop_log_test) {
// Actual test
- auto* snoop_looger = new TestSnoopLoggerModule(temp_snoop_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled);
+ auto* snoop_looger = new TestSnoopLoggerModule(
+ temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled);
TestModuleRegistry test_registry;
test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);
test_registry.StopAll();
// Verify states after test
ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
+ ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
}
TEST_F(SnoopLoggerModuleTest, capture_one_packet_test) {
// Actual test
- auto* snoop_looger = new TestSnoopLoggerModule(temp_snoop_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull);
+ auto* snoop_looger = new TestSnoopLoggerModule(
+ temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull);
TestModuleRegistry test_registry;
test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);
sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kInformationRequest.size());
}
+TEST_F(SnoopLoggerModuleTest, capture_hci_cmd_btsnooz_test) {
+ // Actual test
+ auto* snoop_looger = new TestSnoopLoggerModule(
+ temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled);
+ TestModuleRegistry test_registry;
+ test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);
+
+ snoop_looger->Capture(kInformationRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
+
+ test_registry.StopAll();
+
+ // Verify states after test
+ ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
+ ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
+ ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
+ ASSERT_EQ(
+ std::filesystem::file_size(temp_snooz_log_),
+ sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kInformationRequest.size());
+}
+
+TEST_F(SnoopLoggerModuleTest, capture_l2cap_signal_packet_btsnooz_test) {
+ // Actual test
+ auto* snoop_looger = new TestSnoopLoggerModule(
+ temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled);
+ TestModuleRegistry test_registry;
+ test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);
+
+ snoop_looger->Capture(kSdpConnectionRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
+
+ test_registry.StopAll();
+
+ // Verify states after test
+ ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
+ ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
+ ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
+ ASSERT_EQ(
+ std::filesystem::file_size(temp_snooz_log_),
+ sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kSdpConnectionRequest.size());
+}
+
+TEST_F(SnoopLoggerModuleTest, capture_l2cap_short_data_packet_btsnooz_test) {
+ // Actual test
+ auto* snoop_looger = new TestSnoopLoggerModule(
+ temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled);
+ TestModuleRegistry test_registry;
+ test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);
+
+ snoop_looger->Capture(kAvdtpSuspend, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
+
+ test_registry.StopAll();
+
+ // Verify states after test
+ ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
+ ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
+ ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
+ ASSERT_EQ(
+ std::filesystem::file_size(temp_snooz_log_),
+ sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kAvdtpSuspend.size());
+}
+
+TEST_F(SnoopLoggerModuleTest, capture_l2cap_long_data_packet_btsnooz_test) {
+ // Actual test
+ auto* snoop_looger = new TestSnoopLoggerModule(
+ temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled);
+ TestModuleRegistry test_registry;
+ test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);
+
+ snoop_looger->Capture(kHfpAtNrec0, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
+
+ test_registry.StopAll();
+
+ // Verify states after test
+ ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
+ ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
+ ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
+ ASSERT_EQ(
+ std::filesystem::file_size(temp_snooz_log_),
+ sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + 14);
+}
+
TEST_F(SnoopLoggerModuleTest, rotate_file_at_new_session_test) {
// Start once
{
- auto* snoop_looger = new TestSnoopLoggerModule(temp_snoop_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull);
+ auto* snoop_looger = new TestSnoopLoggerModule(
+ temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull);
TestModuleRegistry test_registry;
test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);
snoop_looger->Capture(kInformationRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
// Start again
{
- auto* snoop_looger = new TestSnoopLoggerModule(temp_snoop_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull);
+ auto* snoop_looger = new TestSnoopLoggerModule(
+ temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull);
TestModuleRegistry test_registry;
test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);
snoop_looger->Capture(kInformationRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
TEST_F(SnoopLoggerModuleTest, rotate_file_after_full_test) {
// Actual test
- auto* snoop_looger = new TestSnoopLoggerModule(temp_snoop_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull);
+ auto* snoop_looger = new TestSnoopLoggerModule(
+ temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeFull);
TestModuleRegistry test_registry;
test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);
std::mutex parameter_mutex;
std::string config_file_path;
std::string snoop_log_file_path;
+std::string snooz_log_file_path;
} // namespace
// On Android we always write a single default location
snoop_log_file_path = path;
}
+// Return the path to the default snooz log file location
+std::string ParameterProvider::SnoozLogFilePath() {
+ {
+ std::lock_guard<std::mutex> lock(parameter_mutex);
+ if (!snooz_log_file_path.empty()) {
+ return snooz_log_file_path;
+ }
+ }
+ return "/data/misc/bluetooth/logs/btsnooz_hci.log";
+}
+
+void ParameterProvider::OverrideSnoozLogFilePath(const std::string& path) {
+ std::lock_guard<std::mutex> lock(parameter_mutex);
+ snooz_log_file_path = path;
+}
+
} // namespace os
} // namespace bluetooth
\ No newline at end of file
std::mutex parameter_mutex;
std::string config_file_path;
std::string snoop_log_file_path;
+std::string snooz_log_file_path;
} // namespace
// Write to $PWD/bt_stack.conf if $PWD can be found, otherwise, write to $HOME/bt_stack.conf
char cwd[PATH_MAX] = {};
if (getcwd(cwd, sizeof(cwd)) == nullptr) {
LOG_ERROR("Failed to get current working directory due to \"%s\", returning default", strerror(errno));
- return "bt_config.conf";
+ return "btsnoop_hci.log";
}
return std::string(cwd) + "/btsnoop_hci.log";
}
snoop_log_file_path = path;
}
+// Return the path to the default snooz log file location
+std::string ParameterProvider::SnoozLogFilePath() {
+ {
+ std::lock_guard<std::mutex> lock(parameter_mutex);
+ if (!snooz_log_file_path.empty()) {
+ return snooz_log_file_path;
+ }
+ }
+ char cwd[PATH_MAX] = {};
+ if (getcwd(cwd, sizeof(cwd)) == nullptr) {
+ LOG_ERROR("Failed to get current working directory due to \"%s\", returning default", strerror(errno));
+ return "bt_config.conf";
+ }
+ return std::string(cwd) + "/btsnooz_hci.log";
+}
+
+void ParameterProvider::OverrideSnoozLogFilePath(const std::string& path) {
+ std::lock_guard<std::mutex> lock(parameter_mutex);
+ snooz_log_file_path = path;
+}
+
} // namespace os
} // namespace bluetooth
\ No newline at end of file
static std::string SnoopLogFilePath();
static void OverrideSnoopLogFilePath(const std::string& path);
+
+ // Return the path to the default snooz log file location
+ static std::string SnoozLogFilePath();
+
+ static void OverrideSnoozLogFilePath(const std::string& path);
};
} // namespace os