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

Commit 637ae941 authored by Jack He's avatar Jack He
Browse files

GD-Logging: Add INIT flags to configure debug logging

* Three flags:
 - INIT_logging_debug_enabled_for_all
 - INIT_logging_debug_enabled_for_tags
 - INIT_logging_debug_disabled_for_tags
* If a tag is explicitly disabled or enabled, we will follow that
  setting. Otherwise, we check the global enable flag
* This setup allows us to enable/disable individual tags as well as
  enable or disable debug logging for all tags
* This affects only DEBUG and VERBOSE level logs

Bug: 170163727
Test: atest bluetooth_test_gd
Tag: #gd-refactor
Change-Id: Idb99ef1ca0a2d14c73069fcba396ac76a61ee39d
parent 104838fb
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -88,6 +88,9 @@ fluoride_defaults {
    sanitize: {
        misc_undefined: ["bounds"],
    },
    static_libs: [
        "libbluetooth_gd",
    ],
}

// Enables code coverage for a set of source files. Must be combined with
+1 −0
Original line number Diff line number Diff line
@@ -328,6 +328,7 @@ cc_test {
    ],
    host_supported: true,
    srcs: [
        ":BluetoothCommonSources",
        ":BluetoothPacketSources",
        ":BluetoothPacketParserTestPacketTestSources",
    ],
+72 −29
Original line number Diff line number Diff line
@@ -20,50 +20,67 @@

#include <string>

#include "common/strings.h"
#include "os/log.h"

namespace bluetooth {
namespace common {

const std::string kGdAdvertisingFlag = "INIT_gd_advertising";
bool InitFlags::gd_core_enabled = false;
bool InitFlags::gd_advertising_enabled = false;

const std::string kGdSecurityFlag = "INIT_gd_security";
bool InitFlags::gd_security_enabled = false;

const std::string kGdAclFlag = "INIT_gd_acl";
bool InitFlags::gd_acl_enabled = false;

const std::string kGdHciFlag = "INIT_gd_hci";
bool InitFlags::gd_hci_enabled = false;

const std::string kGdControllerFlag = "INIT_gd_controller";
bool InitFlags::gd_controller_enabled = false;

const std::string kGdCoreFlag = "INIT_gd_core";
bool InitFlags::gd_core_enabled = false;

const std::string kGattRobustCachingFlag = "INIT_gatt_robust_caching";
bool InitFlags::gatt_robust_caching_enabled = false;
bool InitFlags::logging_debug_enabled_for_all = false;
std::unordered_map<std::string, bool> InitFlags::logging_debug_explicit_tag_settings = {};

bool ParseBoolFlag(const std::vector<std::string>& flag_pair, const std::string& flag, bool* variable) {
  if (flag != flag_pair[0]) {
    return false;
  }
  auto value = BoolFromString(flag_pair[1]);
  if (!value) {
    return false;
  }
  *variable = *value;
  return true;
}

void InitFlags::Load(const char** flags) {
  SetAll(false);
  while (flags != nullptr && *flags != nullptr) {
    if (kGdCoreFlag == *flags) {
      gd_core_enabled = true;
    } else if (kGdAdvertisingFlag == *flags) {
      // TODO enable when module ready
      // gd_advertising_enabled = true;
    } else if (kGdSecurityFlag == *flags) {
      gd_security_enabled = true;
    } else if (kGdAclFlag == *flags) {
      gd_acl_enabled = true;
    } else if (kGdHciFlag == *flags) {
      gd_hci_enabled = true;
    } else if (kGdControllerFlag == *flags) {
      gd_controller_enabled = true;
    } else if (kGattRobustCachingFlag == *flags) {
      gatt_robust_caching_enabled = true;
    std::string flag_element = *flags;
    auto flag_pair = StringSplit(flag_element, "=", 2);
    if (flag_pair.size() != 2) {
      LOG_ERROR("Bad flag %s, must be in <FLAG>=<VALUE> format", flag_element.c_str());
      flags++;
      continue;
    }

    ParseBoolFlag(flag_pair, "INIT_gd_core", &gd_core_enabled);
    ParseBoolFlag(flag_pair, "INIT_gd_advertising", &gd_advertising_enabled);
    ParseBoolFlag(flag_pair, "INIT_gd_security", &gd_security_enabled);
    ParseBoolFlag(flag_pair, "INIT_gd_acl", &gd_acl_enabled);
    ParseBoolFlag(flag_pair, "INIT_gd_hci", &gd_hci_enabled);
    ParseBoolFlag(flag_pair, "INIT_gd_controller", &gd_controller_enabled);
    ParseBoolFlag(flag_pair, "INIT_gatt_robust_caching", &gatt_robust_caching_enabled);
    ParseBoolFlag(flag_pair, "INIT_logging_debug_enabled_for_all", &logging_debug_enabled_for_all);
    if ("INIT_logging_debug_enabled_for_tags" == flag_pair[0]) {
      auto tags = StringSplit(flag_pair[1], ",");
      for (const auto& tag : tags) {
        auto setting = logging_debug_explicit_tag_settings.find(tag);
        if (setting == logging_debug_explicit_tag_settings.end()) {
          logging_debug_explicit_tag_settings.insert_or_assign(tag, true);
        }
      }
    }
    if ("INIT_logging_debug_disabled_for_tags" == flag_pair[0]) {
      auto tags = StringSplit(flag_pair[1], ",");
      for (const auto& tag : tags) {
        logging_debug_explicit_tag_settings.insert_or_assign(tag, false);
      }
    }
    flags++;
  }
@@ -80,6 +97,30 @@ void InitFlags::Load(const char** flags) {
  if (gd_controller_enabled && !gd_hci_enabled) {
    gd_hci_enabled = true;
  }

  std::vector<std::string> logging_debug_enabled_tags;
  std::vector<std::string> logging_debug_disabled_tags;
  for (const auto& tag_setting : logging_debug_explicit_tag_settings) {
    if (tag_setting.second) {
      logging_debug_enabled_tags.emplace_back(tag_setting.first);
    } else {
      logging_debug_disabled_tags.emplace_back(tag_setting.first);
    }
  }

  LOG_INFO(
      "Flags loaded: gd_advertising_enabled=%s, gd_security_enabled=%s, gd_acl_enabled=%s, gd_hci_enabled=%s, "
      "gd_controller_enabled=%s, gd_core_enabled=%s, logging_debug_enabled_for_all=%s, "
      "logging_debug_enabled_tags=%s, logging_debug_disabled_tags=%s",
      ToString(gd_advertising_enabled).c_str(),
      ToString(gd_security_enabled).c_str(),
      ToString(gd_acl_enabled).c_str(),
      ToString(gd_hci_enabled).c_str(),
      ToString(gd_controller_enabled).c_str(),
      ToString(gd_core_enabled).c_str(),
      ToString(logging_debug_enabled_for_all).c_str(),
      StringJoin(logging_debug_enabled_tags, ",").c_str(),
      StringJoin(logging_debug_disabled_tags, ",").c_str());
}

void InitFlags::SetAll(bool value) {
@@ -90,6 +131,8 @@ void InitFlags::SetAll(bool value) {
  gd_controller_enabled = value;
  gd_hci_enabled = value;
  gatt_robust_caching_enabled = value;
  logging_debug_enabled_for_all = value;
  logging_debug_explicit_tag_settings.clear();
}

void InitFlags::SetAllForTesting() {
+18 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

#pragma once

#include <string>
#include <unordered_map>

namespace bluetooth {
namespace common {

@@ -51,6 +54,18 @@ class InitFlags final {
    return gatt_robust_caching_enabled;
  }

  inline static bool IsDebugLoggingEnabledForTag(const std::string& tag) {
    auto tag_setting = logging_debug_explicit_tag_settings.find(tag);
    if (tag_setting != logging_debug_explicit_tag_settings.end()) {
      return tag_setting->second;
    }
    return logging_debug_enabled_for_all;
  }

  inline static bool IsDebugLoggingEnabledForAll() {
    return logging_debug_enabled_for_all;
  }

  static void SetAllForTesting();

 private:
@@ -62,6 +77,9 @@ class InitFlags final {
  static bool gd_controller_enabled;
  static bool gd_core_enabled;
  static bool gatt_robust_caching_enabled;
  static bool logging_debug_enabled_for_all;
  // save both log allow list and block list in the map to save hashing time
  static std::unordered_map<std::string, bool> logging_debug_explicit_tag_settings;
};

}  // namespace common
+58 −17
Original line number Diff line number Diff line
@@ -24,47 +24,88 @@ using bluetooth::common::InitFlags;

TEST(InitFlagsTest, test_load_nullptr) {
  InitFlags::Load(nullptr);
  ASSERT_EQ(false, InitFlags::GdCoreEnabled());
  ASSERT_FALSE(InitFlags::GdCoreEnabled());
}

TEST(InitFlagsTest, test_load_empty) {
  const char* input[] = {nullptr};
  InitFlags::Load(input);
  ASSERT_EQ(false, InitFlags::GdCoreEnabled());
  ASSERT_FALSE(InitFlags::GdCoreEnabled());
}

TEST(InitFlagsTest, test_load_garbage) {
  const char* input[] = {"some random non-existent flag", nullptr};
  InitFlags::Load(input);
  ASSERT_EQ(false, InitFlags::GdCoreEnabled());
  ASSERT_FALSE(InitFlags::GdCoreEnabled());
}

TEST(InitFlagsTest, test_load_core) {
  const char* input[] = {"INIT_gd_core", nullptr};
  const char* input[] = {"INIT_gd_core=true", nullptr};
  InitFlags::Load(input);
  ASSERT_EQ(true, InitFlags::GdCoreEnabled());
  ASSERT_EQ(true, InitFlags::GdControllerEnabled());
  ASSERT_EQ(true, InitFlags::GdHciEnabled());
  ASSERT_TRUE(InitFlags::GdCoreEnabled());
  ASSERT_TRUE(InitFlags::GdControllerEnabled());
  ASSERT_TRUE(InitFlags::GdHciEnabled());
}

TEST(InitFlagsTest, test_load_controller) {
  const char* input[] = {"INIT_gd_controller", nullptr};
  const char* input[] = {"INIT_gd_controller=true", nullptr};
  InitFlags::Load(input);
  ASSERT_EQ(false, InitFlags::GdCoreEnabled());
  ASSERT_EQ(true, InitFlags::GdControllerEnabled());
  ASSERT_EQ(true, InitFlags::GdHciEnabled());
  ASSERT_FALSE(InitFlags::GdCoreEnabled());
  ASSERT_TRUE(InitFlags::GdControllerEnabled());
  ASSERT_TRUE(InitFlags::GdHciEnabled());
}

TEST(InitFlagsTest, test_load_hci) {
  const char* input[] = {"INIT_gd_hci", nullptr};
  const char* input[] = {"INIT_gd_hci=true", nullptr};
  InitFlags::Load(input);
  ASSERT_EQ(false, InitFlags::GdCoreEnabled());
  ASSERT_EQ(false, InitFlags::GdControllerEnabled());
  ASSERT_EQ(true, InitFlags::GdHciEnabled());
  ASSERT_FALSE(InitFlags::GdCoreEnabled());
  ASSERT_FALSE(InitFlags::GdControllerEnabled());
  ASSERT_TRUE(InitFlags::GdHciEnabled());
}

TEST(InitFlagsTest, test_load_gatt_robust_caching) {
  const char* input[] = {"INIT_gatt_robust_caching", nullptr};
  const char* input[] = {"INIT_gatt_robust_caching=true", nullptr};
  InitFlags::Load(input);
  ASSERT_EQ(true, InitFlags::GattRobustCachingEnabled());
  ASSERT_TRUE(InitFlags::GattRobustCachingEnabled());
}

TEST(InitFlagsTest, test_enable_debug_logging_for_all) {
  const char* input[] = {"INIT_logging_debug_enabled_for_all=true", nullptr};
  InitFlags::Load(input);
  ASSERT_TRUE(InitFlags::IsDebugLoggingEnabledForTag("foo"));
  ASSERT_TRUE(InitFlags::IsDebugLoggingEnabledForTag("bar"));
  ASSERT_TRUE(InitFlags::IsDebugLoggingEnabledForAll());
}

TEST(InitFlagsTest, test_enable_debug_logging_for_tags) {
  const char* input[] = {"INIT_logging_debug_enabled_for_tags=foo,bar,hello", nullptr};
  InitFlags::Load(input);
  ASSERT_TRUE(InitFlags::IsDebugLoggingEnabledForTag("foo"));
  ASSERT_TRUE(InitFlags::IsDebugLoggingEnabledForTag("bar"));
  ASSERT_TRUE(InitFlags::IsDebugLoggingEnabledForTag("hello"));
  ASSERT_FALSE(InitFlags::IsDebugLoggingEnabledForTag("Foo"));
  ASSERT_FALSE(InitFlags::IsDebugLoggingEnabledForAll());
}

TEST(InitFlagsTest, test_disable_debug_logging_for_tags) {
  const char* input[] = {"INIT_logging_debug_disabled_for_tags=foo,bar,hello", nullptr};
  InitFlags::Load(input);
  ASSERT_FALSE(InitFlags::IsDebugLoggingEnabledForTag("foo"));
  ASSERT_FALSE(InitFlags::IsDebugLoggingEnabledForTag("bar"));
  ASSERT_FALSE(InitFlags::IsDebugLoggingEnabledForTag("hello"));
  ASSERT_FALSE(InitFlags::IsDebugLoggingEnabledForTag("Foo"));
  ASSERT_FALSE(InitFlags::IsDebugLoggingEnabledForAll());
}

TEST(InitFlagsTest, test_debug_logging_multiple_flags) {
  const char* input[] = {"INIT_logging_debug_enabled_for_tags=foo,hello",
                         "INIT_logging_debug_disabled_for_tags=foo,bar",
                         "INIT_logging_debug_enabled_for_all=false",
                         nullptr};
  InitFlags::Load(input);
  ASSERT_FALSE(InitFlags::IsDebugLoggingEnabledForTag("foo"));
  ASSERT_FALSE(InitFlags::IsDebugLoggingEnabledForTag("bar"));
  ASSERT_TRUE(InitFlags::IsDebugLoggingEnabledForTag("hello"));
  ASSERT_FALSE(InitFlags::IsDebugLoggingEnabledForTag("Foo"));
  ASSERT_FALSE(InitFlags::IsDebugLoggingEnabledForAll());
}
Loading