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

Commit 11639945 authored by Bidhya Sharma's avatar Bidhya Sharma Committed by Gerrit Code Review
Browse files

Merge "GD: Delete snooz log files older than 12 hrs"

parents 6cb289a9 32bdbdd8
Loading
Loading
Loading
Loading
+35 −5
Original line number Diff line number Diff line
@@ -77,6 +77,10 @@ constexpr size_t kDefaultBtSnoozMaxPayloadBytesPerPacket =
constexpr size_t kDefaultBtSnoozMaxPacketsPerBuffer =
    kDefaultBtsnoozMaxMemoryUsageBytes / kDefaultBtSnoozMaxBytesPerPacket;

using namespace std::chrono_literals;
constexpr std::chrono::hours kBtSnoozLogLifeTime = 12h;
constexpr std::chrono::hours kBtSnoozLogDeleteRepeatingAlarmInterval = 1h;

std::string get_btsnoop_log_path(std::string log_dir, bool filtered) {
  if (filtered) {
    log_dir.append(".filtered");
@@ -107,6 +111,20 @@ void delete_btsnoop_files(const std::string& log_path) {
  }
}

void delete_old_btsnooz_files(const std::string& log_path, const std::chrono::milliseconds log_life_time) {
  auto opt_created_ts = os::FileCreatedTime(log_path);
  if (!opt_created_ts) return;

  using namespace std::chrono;
  auto created_tp = opt_created_ts.value();
  auto current_tp = std::chrono::system_clock::now();

  auto diff = duration_cast<milliseconds>(current_tp - created_tp);
  if (diff >= log_life_time) {
    delete_btsnoop_files(log_path);
  }
}

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;
@@ -172,11 +190,15 @@ SnoopLogger::SnoopLogger(
    std::string snoop_log_path,
    std::string snooz_log_path,
    size_t max_packets_per_file,
    const std::string& btsnoop_mode)
    const std::string& btsnoop_mode,
    const std::chrono::milliseconds snooz_log_life_time,
    const std::chrono::milliseconds snooz_log_delete_alarm_interval)
    : 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) {
      btsnooz_buffer_(kDefaultBtSnoozMaxPacketsPerBuffer),
      snooz_log_life_time_(snooz_log_life_time),
      snooz_log_delete_alarm_interval_(snooz_log_delete_alarm_interval) {
  if (false && btsnoop_mode == kBtSnoopLogModeFiltered) {
    // TODO(b/163733538): implement filtered snoop log in GD, currently filtered == disabled
    LOG_INFO("Filtered Snoop Logs enabled");
@@ -360,14 +382,20 @@ void SnoopLogger::Start() {
  if (is_enabled_) {
    OpenNextSnoopLogFile();
  }
  alarm_ = std::make_unique<os::RepeatingAlarm>(GetHandler());
  alarm_->Schedule(
      common::Bind(&delete_old_btsnooz_files, snooz_log_path_, snooz_log_life_time_), snooz_log_delete_alarm_interval_);
}

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();
  // Cancel the alarm
  alarm_->Cancel();
  alarm_.reset();
  // delete any existing snooz logs
  delete_btsnoop_files(snooz_log_path_);
}

DumpsysDataFinisher SnoopLogger::GetDumpsysData(flatbuffers::FlatBufferBuilder* builder) const {
@@ -421,7 +449,9 @@ const ModuleFactory SnoopLogger::Factory = ModuleFactory([]() {
      os::ParameterProvider::SnoopLogFilePath(),
      os::ParameterProvider::SnoozLogFilePath(),
      GetMaxPacketsPerFile(),
      GetBtSnoopMode());
      GetBtSnoopMode(),
      kBtSnoozLogLifeTime,
      kBtSnoozLogDeleteRepeatingAlarmInterval);
});

}  // namespace hal
+7 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "common/circular_buffer.h"
#include "hal/hci_hal.h"
#include "module.h"
#include "os/repeating_alarm.h"

namespace bluetooth {
namespace hal {
@@ -96,7 +97,9 @@ class SnoopLogger : public ::bluetooth::Module {
      std::string snoop_log_path,
      std::string snooz_log_path,
      size_t max_packets_per_file,
      const std::string& btsnoop_mode);
      const std::string& btsnoop_mode,
      const std::chrono::milliseconds snooz_log_life_time,
      const std::chrono::milliseconds snooz_log_delete_alarm_interval);
  void CloseCurrentSnoopLogFile();
  void OpenNextSnoopLogFile();
  void DumpSnoozLogToFile(const std::vector<std::string>& data) const;
@@ -111,6 +114,9 @@ class SnoopLogger : public ::bluetooth::Module {
  common::CircularBuffer<std::string> btsnooz_buffer_;
  size_t packet_counter_ = 0;
  mutable std::recursive_mutex file_mutex_;
  std::unique_ptr<os::RepeatingAlarm> alarm_;
  std::chrono::milliseconds snooz_log_life_time_;
  std::chrono::milliseconds snooz_log_delete_alarm_interval_;
};

}  // namespace hal
+58 −17
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ std::vector<uint8_t> kHfpAtNrec0 = {0x02, 0x02, 0x20, 0x13, 0x00, 0x0f, 0x00, 0x

using bluetooth::TestModuleRegistry;
using bluetooth::hal::SnoopLogger;
using namespace std::chrono_literals;

// Expose protected constructor for test
class TestSnoopLoggerModule : public SnoopLogger {
@@ -60,14 +61,22 @@ class TestSnoopLoggerModule : public SnoopLogger {
      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) {}
      : SnoopLogger(
            std::move(snoop_log_path), std::move(snooz_log_path), max_packets_per_file, btsnoop_mode, 20ms, 5ms) {}

  std::string ToString() const override {
    return std::string("TestSnoopLoggerModule");
  }

  void CallGetDumpsysData(flatbuffers::FlatBufferBuilder* builder) {
    GetDumpsysData(builder);
  }
};

class SnoopLoggerModuleTest : public Test {
 public:
  flatbuffers::FlatBufferBuilder* builder_;

 protected:
  void SetUp() override {
    temp_dir_ = std::filesystem::temp_directory_path();
@@ -75,6 +84,8 @@ class SnoopLoggerModuleTest : public Test {
    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";
    builder_ = new flatbuffers::FlatBufferBuilder();

    DeleteSnoopLogFiles();
    ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_));
    ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_));
@@ -84,6 +95,7 @@ class SnoopLoggerModuleTest : public Test {

  void TearDown() override {
    DeleteSnoopLogFiles();
    delete builder_;
  }

  void DeleteSnoopLogFiles() {
@@ -133,7 +145,7 @@ TEST_F(SnoopLoggerModuleTest, disable_snoop_log_test) {
  // 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_FALSE(std::filesystem::exists(temp_snooz_log_));
}

TEST_F(SnoopLoggerModuleTest, capture_one_packet_test) {
@@ -163,16 +175,19 @@ TEST_F(SnoopLoggerModuleTest, capture_hci_cmd_btsnooz_test) {
  test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);

  snoop_looger->Capture(kInformationRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
  snoop_looger->CallGetDumpsysData(builder_);

  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_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());
  ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
}

TEST_F(SnoopLoggerModuleTest, capture_l2cap_signal_packet_btsnooz_test) {
@@ -183,16 +198,19 @@ TEST_F(SnoopLoggerModuleTest, capture_l2cap_signal_packet_btsnooz_test) {
  test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);

  snoop_looger->Capture(kSdpConnectionRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
  snoop_looger->CallGetDumpsysData(builder_);

  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_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());
  ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
}

TEST_F(SnoopLoggerModuleTest, capture_l2cap_short_data_packet_btsnooz_test) {
@@ -203,16 +221,19 @@ TEST_F(SnoopLoggerModuleTest, capture_l2cap_short_data_packet_btsnooz_test) {
  test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);

  snoop_looger->Capture(kAvdtpSuspend, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
  snoop_looger->CallGetDumpsysData(builder_);

  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_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());
  ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
}

TEST_F(SnoopLoggerModuleTest, capture_l2cap_long_data_packet_btsnooz_test) {
@@ -223,16 +244,36 @@ TEST_F(SnoopLoggerModuleTest, capture_l2cap_long_data_packet_btsnooz_test) {
  test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger);

  snoop_looger->Capture(kHfpAtNrec0, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
  snoop_looger->CallGetDumpsysData(builder_);

  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_registry.StopAll();

  // Verify states after test
  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_));
}

TEST_F(SnoopLoggerModuleTest, delete_old_snooz_log_files) {
  // 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);

  std::filesystem::create_directories(temp_snooz_log_);

  ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
  ASSERT_EQ(
      std::filesystem::file_size(temp_snooz_log_),
      sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + 14);
  std::this_thread::sleep_for(10ms);
  ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_));
  std::this_thread::sleep_for(15ms);
  ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_));
  test_registry.StopAll();
}

TEST_F(SnoopLoggerModuleTest, rotate_file_at_new_session_test) {
+5 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#pragma once

#include <chrono>
#include <iterator>
#include <optional>

@@ -45,5 +46,9 @@ bool WriteToFile(const std::string& path, const std::string& data);
// Return true on success, false on failure (e.g. file not exist, failed to remove, etc)
bool RemoveFile(const std::string& path);

// Returns created time_point of given file, return std::nullopt on failure
std::optional<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> FileCreatedTime(
    const std::string& path);

}  // namespace os
}  // namespace bluetooth
 No newline at end of file
+14 −0
Original line number Diff line number Diff line
@@ -195,5 +195,19 @@ bool RemoveFile(const std::string& path) {
  return true;
}

std::optional<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> FileCreatedTime(
    const std::string& path) {
  struct stat file_info;
  if (stat(path.c_str(), &file_info) != 0) {
    LOG_ERROR("unable to read '%s' file metadata, error: %s", path.c_str(), strerror(errno));
    return std::nullopt;
  }
  using namespace std::chrono;
  using namespace std::chrono_literals;
  auto created_ts = file_info.st_ctim;
  auto d = seconds{created_ts.tv_sec} + nanoseconds{created_ts.tv_nsec};
  return time_point<system_clock>(duration_cast<system_clock::duration>(d));
}

}  // namespace os
}  // namespace bluetooth
 No newline at end of file