diff --git a/system/gd/common/init_flags.h b/system/gd/common/init_flags.h
index 9f0f12a1238c96c079fb29dd22cecb48787cdb3d..764ced5797380cfc25af1e29d5ec81ceb7959adb 100644
--- a/system/gd/common/init_flags.h
+++ b/system/gd/common/init_flags.h
@@ -34,14 +34,6 @@ class InitFlags final {
     init_flags::load(std::move(rusted_flags));
   }
 
-  inline static int GetLogLevelForTag(const std::string& tag) {
-    return init_flags::get_log_level_for_tag(tag);
-  }
-
-  inline static int GetDefaultLogLevel() {
-    return init_flags::get_default_log_level();
-  }
-
   inline static bool IsDeviceIotConfigLoggingEnabled() {
     return init_flags::device_iot_config_logging_is_enabled();
   }
diff --git a/system/gd/common/init_flags_test.cc b/system/gd/common/init_flags_test.cc
index 8c4e357fcd310264ceed8e68248e6cbdd94cdd05..ea0019fdb433b834348c1f499b0f3316a6266024 100644
--- a/system/gd/common/init_flags_test.cc
+++ b/system/gd/common/init_flags_test.cc
@@ -20,8 +20,6 @@
 
 #include <gtest/gtest.h>
 
-#include "os/log_tags.h"
-
 using bluetooth::common::InitFlags;
 
 TEST(InitFlagsTest, test_enable_btm_flush_discovery_queue_on_search_cancel) {
@@ -36,51 +34,6 @@ TEST(InitFlagsTest, test_leaudio_targeted_announcement_reconnection_mode) {
   ASSERT_TRUE(InitFlags::IsTargetedAnnouncementReconnectionMode());
 }
 
-TEST(InitFlagsTest, test_enable_debug_logging_for_all) {
-  const char* input[] = {"INIT_default_log_level=5", nullptr};
-  InitFlags::Load(input);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("foo"), LOG_TAG_DEBUG);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("bar"), LOG_TAG_DEBUG);
-  ASSERT_EQ(InitFlags::GetDefaultLogLevel(), LOG_TAG_DEBUG);
-}
-
-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_EQ(InitFlags::GetLogLevelForTag("foo"), LOG_TAG_VERBOSE);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("bar"), LOG_TAG_VERBOSE);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("hello"), LOG_TAG_VERBOSE);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("Foo"), LOG_TAG_INFO);
-  ASSERT_EQ(InitFlags::GetDefaultLogLevel(), LOG_TAG_INFO);
-}
-
-TEST(InitFlagsTest, test_disable_debug_logging_for_tags) {
-  const char* input[] = {
-      "INIT_logging_debug_disabled_for_tags=foo,bar,hello",
-      "INIT_default_log_level_str=LOG_DEBUG",
-      nullptr};
-  InitFlags::Load(input);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("foo"), LOG_TAG_INFO);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("bar"), LOG_TAG_INFO);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("hello"), LOG_TAG_INFO);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("Foo"), LOG_TAG_DEBUG);
-  ASSERT_EQ(InitFlags::GetDefaultLogLevel(), LOG_TAG_DEBUG);
-}
-
-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_default_log_level_str=LOG_WARN",
-      nullptr};
-  InitFlags::Load(input);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("foo"), LOG_TAG_INFO);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("bar"), LOG_TAG_INFO);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("hello"), LOG_TAG_VERBOSE);
-  ASSERT_EQ(InitFlags::GetLogLevelForTag("Foo"), LOG_TAG_WARN);
-  ASSERT_EQ(InitFlags::GetDefaultLogLevel(), LOG_TAG_WARN);
-}
-
 TEST(InitFlagsTest, test_device_iot_config_logging_is_enabled) {
   const char* input[] = {"INIT_device_iot_config_logging=true", nullptr};
   InitFlags::Load(input);
diff --git a/system/gd/os/log.h b/system/gd/os/log.h
index e07ce1c434583698f970128d99355fe1d045d929..437cba5af525c6da7c8c90f6ad8c5713f2c04348 100644
--- a/system/gd/os/log.h
+++ b/system/gd/os/log.h
@@ -57,24 +57,21 @@ static_assert(LOG_TAG != nullptr, "LOG_TAG should never be NULL");
 #include <log/log.h>
 #include <log/log_event_list.h>
 
-#if __has_include("src/init_flags.rs.h")
-
-#include "common/init_flags.h"
-
-#define LOG_VERBOSE_INT(fmt, args...)                                                  \
-  do {                                                                                 \
-    if (bluetooth::common::InitFlags::GetLogLevelForTag(LOG_TAG) >= LOG_TAG_VERBOSE) { \
-      ALOGV(fmt, ##args);                                                              \
-    }                                                                                  \
+#define LOG_VERBOSE_INT(fmt, args...)                                                     \
+  do {                                                                                    \
+    if (!__android_log_is_loggable(ANDROID_LOG_VERBOSE, LOG_TAG, ANDROID_LOG_INFO) &&     \
+        !__android_log_is_loggable(ANDROID_LOG_VERBOSE, "bluetooth", ANDROID_LOG_INFO)) { \
+      ALOGV(fmt, ##args);                                                                 \
+    }                                                                                     \
   } while (false)
 
-#define LOG_DEBUG_INT(fmt, args...)                                                  \
-  do {                                                                               \
-    if (bluetooth::common::InitFlags::GetLogLevelForTag(LOG_TAG) >= LOG_TAG_DEBUG) { \
-      ALOGD(fmt, ##args);                                                            \
-    }                                                                                \
+#define LOG_DEBUG_INT(fmt, args...)                                                     \
+  do {                                                                                  \
+    if (!__android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO) &&     \
+        !__android_log_is_loggable(ANDROID_LOG_DEBUG, "bluetooth", ANDROID_LOG_INFO)) { \
+      ALOGD(fmt, ##args);                                                               \
+    }                                                                                   \
   } while (false)
-#endif /* __has_include("src/init_flags.rs.h") */
 
 #define LOG_INFO_INT(fmt, args...) ALOGI(fmt, ##args)
 #define LOG_WARN_INT(fmt, args...) ALOGW(fmt, ##args)
@@ -102,25 +99,13 @@ static_assert(LOG_TAG != nullptr, "LOG_TAG should never be NULL");
     abort();                                                                        \
   } while (false)
 #elif defined(TARGET_FLOSS) /* end of defined (ANDROID_EMULATOR) */
-#include "common/init_flags.h"
 #include "os/syslog.h"
 
 // Prefix the log with tag, file, line and function
-#define LOGWRAPPER(tag, fmt, args...) \
-  write_syslog(tag, "%s: " fmt, LOG_TAG, ##args)
-
-#define LOG_VERBOSE_INT(...)                                                           \
-  do {                                                                                 \
-    if (bluetooth::common::InitFlags::GetLogLevelForTag(LOG_TAG) >= LOG_TAG_VERBOSE) { \
-      LOGWRAPPER(LOG_TAG_VERBOSE, __VA_ARGS__);                                        \
-    }                                                                                  \
-  } while (false)
-#define LOG_DEBUG_INT(...)                                                           \
-  do {                                                                               \
-    if (bluetooth::common::InitFlags::GetLogLevelForTag(LOG_TAG) >= LOG_TAG_DEBUG) { \
-      LOGWRAPPER(LOG_TAG_DEBUG, __VA_ARGS__);                                        \
-    }                                                                                \
-  } while (false)
+#define LOGWRAPPER(tag, fmt, args...) write_syslog(tag, LOG_TAG, "%s: " fmt, LOG_TAG, ##args)
+
+#define LOG_VERBOSE_INT(...) LOGWRAPPER(LOG_TAG_VERBOSE, __VA_ARGS__)
+#define LOG_DEBUG_INT(...) LOGWRAPPER(LOG_TAG_DEBUG, __VA_ARGS__)
 #define LOG_INFO_INT(...) LOGWRAPPER(LOG_TAG_INFO, __VA_ARGS__)
 #define LOG_WARN_INT(...) LOGWRAPPER(LOG_TAG_WARN, __VA_ARGS__)
 #define LOG_ERROR_INT(...) LOGWRAPPER(LOG_TAG_ERROR, __VA_ARGS__)
diff --git a/system/gd/os/log_tags.h b/system/gd/os/log_tags.h
index ac94a7f8402178c0bfe2ce8d87e848925d1f34e3..437fb120f25efe31df81d22da6e9ee42a5089451 100644
--- a/system/gd/os/log_tags.h
+++ b/system/gd/os/log_tags.h
@@ -15,14 +15,15 @@
  */
 #pragma once
 
+// TODO(b/305066880) - Deprecate once replaced with fmtlib implementation.
 // These log levels may need to be mapped to system values. These values are
-// used to control the log level via init flags.
+// used to control the log level and should match
+// `bluetooth::log_internal::Level`.
 enum LogLevels {
-  LOG_TAG_FATAL = 0,
-  LOG_TAG_ERROR,
-  LOG_TAG_WARN,
-  LOG_TAG_NOTICE,
-  LOG_TAG_INFO,
-  LOG_TAG_DEBUG,
-  LOG_TAG_VERBOSE
+  LOG_TAG_VERBOSE = 2,
+  LOG_TAG_DEBUG = 3,
+  LOG_TAG_INFO = 4,
+  LOG_TAG_WARN = 5,
+  LOG_TAG_ERROR = 6,
+  LOG_TAG_FATAL = 7,
 };
diff --git a/system/gd/os/syslog.cc b/system/gd/os/syslog.cc
index f0a4f74d343c5b4bb7f3b08bfc378e5c0c04d22f..1f223dd2ec21737f0a502911280788a51adbb99f 100644
--- a/system/gd/os/syslog.cc
+++ b/system/gd/os/syslog.cc
@@ -23,23 +23,31 @@
 
 #include "os/log_tags.h"
 
+// TODO(b/305066880) - This implementation will replace this syslog
+// implementation. Remove this file once everything is moved over to the new
+// logging macros.
+#include "bluetooth/log.h"
+
+namespace bluetooth::log_internal {
+extern Level GetLogLevelForTag(char const* tag);
+}
+
 namespace {
 #define SYSLOG_IDENT "btadapterd"
 
 const char kSyslogIdent[] = SYSLOG_IDENT;
 
 // Map LOG_TAG_* to syslog mappings
-const int kTagMap[] = {
-    /*LOG_TAG_FATAL=*/LOG_CRIT,
-    /*LOG_TAG_ERROR=*/LOG_ERR,
-    /*LOG_TAG_WARN=*/LOG_WARNING,
-    /*LOG_TAG_NOTICE=*/LOG_NOTICE,
-    /*LOG_TAG_INFO=*/LOG_INFO,
-    /*LOG_TAG_DEBUG=*/LOG_DEBUG,
+const int kLevelMap[] = {
     /*LOG_TAG_VERBOSE=*/LOG_DEBUG,
+    /*LOG_TAG_DEBUG=*/LOG_DEBUG,
+    /*LOG_TAG_INFO=*/LOG_INFO,
+    /*LOG_TAG_WARN=*/LOG_WARNING,
+    /*LOG_TAG_ERROR=*/LOG_ERR,
+    /*LOG_TAG_FATAL=*/LOG_CRIT,
 };
 
-static_assert(sizeof(kTagMap) / sizeof(kTagMap[0]) == LOG_TAG_VERBOSE + 1);
+static_assert(sizeof(kLevelMap) / sizeof(kLevelMap[0]) == (LOG_TAG_FATAL - LOG_TAG_VERBOSE) + 1);
 
 class SyslogWrapper {
  public:
@@ -55,18 +63,28 @@ class SyslogWrapper {
 std::unique_ptr<SyslogWrapper> gSyslog;
 }  // namespace
 
-void write_syslog(int tag, const char* format, ...) {
+void write_syslog(int level, const char* tag, const char* format, ...) {
   if (!gSyslog) {
     gSyslog = std::make_unique<SyslogWrapper>();
   }
 
-  // I don't expect to see incorrect tags but making the check anyway so we
+  // Filter out logs that don't meet level requirement.
+  bluetooth::log_internal::Level current_level = bluetooth::log_internal::GetLogLevelForTag(tag);
+  if (static_cast<bluetooth::log_internal::Level>(level) < current_level) {
+    return;
+  }
+
+  // I don't expect to see incorrect levels but making the check anyway so we
   // don't go out of bounds in the array above.
-  tag = tag <= LOG_TAG_VERBOSE ? tag : LOG_TAG_ERROR;
-  int level = kTagMap[tag];
+  if (level > LOG_TAG_FATAL) {
+    level = LOG_TAG_ERROR;
+  } else if (level < LOG_TAG_VERBOSE) {
+    level = LOG_TAG_VERBOSE;
+  }
+  int syslog_level = kLevelMap[level - LOG_TAG_VERBOSE];
 
   va_list args;
   va_start(args, format);
-  vsyslog(level, format, args);
+  vsyslog(syslog_level, format, args);
   va_end(args);
 }
diff --git a/system/gd/os/syslog.h b/system/gd/os/syslog.h
index 63411a26200a4c026e460d4e06fe23b7404dc088..aed9bc60e772079b8b19e025abe18b1a95d0ce3b 100644
--- a/system/gd/os/syslog.h
+++ b/system/gd/os/syslog.h
@@ -26,4 +26,4 @@
 /**
  * Write log to syslog.
  */
-void write_syslog(int tag, const char* format, ...);
+void write_syslog(int level, const char* tag, const char* format, ...);
diff --git a/system/gd/rust/common/src/init_flags.rs b/system/gd/rust/common/src/init_flags.rs
index dca345161cb295606a9ce7f7ebc279b608af344a..e1376a4a186c5d98f003d7e18f76e5883822761c 100644
--- a/system/gd/rust/common/src/init_flags.rs
+++ b/system/gd/rust/common/src/init_flags.rs
@@ -2,7 +2,6 @@ use lazy_static::lazy_static;
 use log::{error, info};
 use paste::paste;
 use std::collections::{BTreeMap, HashMap};
-use std::convert::TryFrom;
 use std::fmt;
 use std::sync::Mutex;
 
@@ -70,25 +69,6 @@ macro_rules! create_getter_fn {
     };
 }
 
-macro_rules! create_setter_fn {
-    ($flag:ident) => {
-        paste! {
-            #[doc = concat!(" Update value of ", stringify!($flag), " at runtime")]
-            pub fn [<update_ $flag>](value: bool) {
-                FLAGS.lock().unwrap().$flag = value;
-            }
-        }
-    };
-    ($flag:ident $type:ty) => {
-        paste! {
-            #[doc = concat!(" Update value of ", stringify!($flag), " at runtime")]
-            pub fn [<update_ $flag>](value: $type) {
-                FLAGS.lock().unwrap().$flag = value;
-            }
-        }
-    };
-}
-
 macro_rules! init_flags {
     (
         name: $name:ident
@@ -116,23 +96,17 @@ macro_rules! init_flags_struct {
     (
      name: $name:ident
      flags: { $($flag:ident $(: $type:ty)? $(= $default:tt)?,)* }
-     dynamic_flags: { $($dy_flag:ident $(: $dy_type:ty)? $(= $dy_default:tt)?,)* }
-     extra_fields: { $($extra_field:ident : $extra_field_type:ty $(= $extra_default:tt)?,)* }
      extra_parsed_flags: { $($extra_flag:tt => $extra_flag_fn:ident(_, _ $(,$extra_args:tt)*),)*}
      dependencies: { $($parent:ident => $child:ident),* }) => {
 
         struct $name {
             $($flag : type_expand!($($type)?),)*
-            $($dy_flag : type_expand!($($dy_type)?),)*
-            $($extra_field : $extra_field_type,)*
         }
 
         impl Default for $name {
             fn default() -> Self {
                 Self {
                     $($flag : default_value!($($type)? $(= $default)?),)*
-                    $($dy_flag : default_value!($($dy_type)? $(= $dy_default)?),)*
-                    $($extra_field : default_value!($extra_field_type $(= $extra_default)?),)*
                 }
             }
         }
@@ -141,16 +115,12 @@ macro_rules! init_flags_struct {
             fn get_defaults_for_test() -> Self {
                 Self {
                     $($flag: test_value!($($type)?),)*
-                    $($dy_flag: test_value!($($dy_type)?),)*
-                    $($extra_field: test_value!($extra_field_type),)*
                 }
             }
 
             fn dump(&self) -> BTreeMap<&'static str, String> {
                 [
                     $((stringify!($flag), format!("{}", self.$flag)),)*
-                    $((stringify!($dy_flag), format!("{}", self.$dy_flag)),)*
-                    $((stringify!($extra_field), format!("{}", self.$extra_field)),)*
                 ].into()
             }
 
@@ -169,10 +139,6 @@ macro_rules! init_flags_struct {
                             init_flags.$flag = values[1].parse().unwrap_or_else(|e| {
                                 error!("Parse failure on '{}': {}", flag, e);
                                 default_value!($($type)? $(= $default)?)}),)*
-                        $(concat!("INIT_", stringify!($dy_flag)) =>
-                            init_flags.$dy_flag = values[1].parse().unwrap_or_else(|e| {
-                                error!("Parse failure on '{}': {}", flag, e);
-                                default_value!($($dy_type)? $(= $dy_default)?)}),)*
                         $($extra_flag => $extra_flag_fn(&mut init_flags, values $(, $extra_args)*),)*
                         _ => error!("Unsaved flag: {} = {}", values[0], values[1])
                     }
@@ -197,13 +163,9 @@ macro_rules! init_flags_struct {
 
         impl fmt::Display for $name {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-                write!(f, concat!(
+                write!(f,
                     concat!($(concat!(stringify!($flag), "={}")),*),
-                    concat!($(concat!(stringify!($dy_flag), "={}")),*),
-                    $(concat!(stringify!($extra_field), "={}")),*),
-                    $(self.$flag),*,
-                    $(self.$dy_flag),*,
-                    $(self.$extra_field),*)
+                    $(self.$flag),*)
             }
         }
 
@@ -213,16 +175,11 @@ macro_rules! init_flags_struct {
 macro_rules! init_flags_getters {
     (
      flags: { $($flag:ident $(: $type:ty)? $(= $default:tt)?,)* }
-     dynamic_flags: { $($dy_flag:ident $(: $dy_type:ty)? $(= $dy_default:tt)?,)* }
-     extra_fields: { $($extra_field:ident : $extra_field_type:ty $(= $extra_default:tt)?,)* }
      extra_parsed_flags: { $($extra_flag:tt => $extra_flag_fn:ident(_, _ $(,$extra_args:tt)*),)*}
      dependencies: { $($parent:ident => $child:ident),* }) => {
 
         $(create_getter_fn!($flag $($type)?);)*
 
-        $(create_getter_fn!($dy_flag $($dy_type)?);)*
-        $(create_setter_fn!($dy_flag $($dy_type)?);)*
-
         #[cfg(test)]
         mod tests_autogenerated {
             use super::*;
@@ -238,19 +195,6 @@ macro_rules! init_flags_getters {
                     assert_eq!(get_value, test_value!($($type)?));
                 }
             })*
-
-            $(paste! {
-                #[test]
-                pub fn [<test_dynamic_get_ $dy_flag>]() {
-                    let _guard = tests::ASYNC_LOCK.lock().unwrap();
-                    tests::test_load(vec![
-                        &*format!(concat!(concat!("INIT_", stringify!($dy_flag)), "={}"), test_value!($($dy_type)?))
-                    ]);
-                    let get_value = call_getter_fn!($dy_flag $($dy_type)?);
-                    drop(_guard); // Prevent poisonning other tests if a panic occurs
-                    assert_eq!(get_value, test_value!($($dy_type)?));
-                }
-            })*
         }
     }
 }
@@ -266,95 +210,16 @@ impl fmt::Display for ExplicitTagSettings {
     }
 }
 
-struct LogLevel(i32);
-
-impl TryFrom<&str> for LogLevel {
-    type Error = &'static str;
-
-    fn try_from(tag_value: &str) -> Result<Self, Self::Error> {
-        match tag_value {
-            "LOG_FATAL" => Ok(LogLevel(LOG_TAG_FATAL)),
-            "LOG_ERROR" => Ok(LogLevel(LOG_TAG_ERROR)),
-            "LOG_WARN" => Ok(LogLevel(LOG_TAG_WARN)),
-            "LOG_NOTICE" => Ok(LogLevel(LOG_TAG_NOTICE)),
-            "LOG_INFO" => Ok(LogLevel(LOG_TAG_INFO)),
-            "LOG_DEBUG" => Ok(LogLevel(LOG_TAG_DEBUG)),
-            "LOG_VERBOSE" => Ok(LogLevel(LOG_TAG_VERBOSE)),
-            _ => Err("Invalid tag value"),
-        }
-    }
-}
-
-fn deprecated_set_debug_logging_enabled_for_all(flags: &mut InitFlags, values: Vec<&str>) {
-    let truthy: bool = values[1].parse().unwrap_or(false);
-    flags.default_log_level = if truthy { LOG_TAG_VERBOSE } else { LOG_TAG_INFO };
-
-    // Leave a note that this flag is deprecated in the logs.
-    log::error!(
-        "DEPRECATED flag used: INIT_logging_debug_enabled_for_all. Use INIT_default_log_level_str=LOG_VERBOSE instead.",
-    );
-}
-
-fn parse_log_level(flags: &mut InitFlags, values: Vec<&str>) {
-    if let Ok(v) = LogLevel::try_from(values[1]) {
-        flags.default_log_level = v.0;
-    }
-}
-
-fn parse_logging_tag(flags: &mut InitFlags, values: Vec<&str>) {
-    for tag in values[1].split(',') {
-        let tagstr = tag.to_string();
-        let pair = tagstr.split(':').collect::<Vec<&str>>();
-        if pair.len() == 2 {
-            if let Ok(v) = LogLevel::try_from(pair[1]) {
-                flags.logging_explicit_tag_settings.map.insert(pair[0].into(), v.0);
-            }
-        }
-    }
-}
-
-fn parse_debug_logging_tag(flags: &mut InitFlags, values: Vec<&str>, enabled: bool) {
-    let log_level: i32 = if enabled { LOG_TAG_VERBOSE } else { LOG_TAG_INFO };
-
-    for tag in values[1].split(',') {
-        flags.logging_explicit_tag_settings.map.insert(tag.to_string(), log_level);
-    }
-}
-
 fn parse_hci_adapter(flags: &mut InitFlags, values: Vec<&str>) {
     flags.hci_adapter = values[1].parse().unwrap_or(0);
 }
 
-/// Returns the log level for given flag.
-pub fn get_log_level_for_tag(tag: &str) -> i32 {
-    let guard = FLAGS.lock().unwrap();
-    *guard.logging_explicit_tag_settings.map.get(tag).unwrap_or(&guard.default_log_level)
-}
-
 /// Sets all bool flags to true
 /// Set all other flags and extra fields to their default type value
 pub fn set_all_for_testing() {
     *FLAGS.lock().unwrap() = InitFlags::get_defaults_for_test();
 }
 
-// Keep these values in sync with the values in gd/os/log_tags.h
-// They are used to control the log level for each tag.
-
-/// Fatal log level.
-pub const LOG_TAG_FATAL: i32 = 0;
-/// Error log level.
-pub const LOG_TAG_ERROR: i32 = 1;
-/// Warning log level.
-pub const LOG_TAG_WARN: i32 = 2;
-/// Notice log level.
-pub const LOG_TAG_NOTICE: i32 = 3;
-/// Info log level. This is usually the default log level on most systems.
-pub const LOG_TAG_INFO: i32 = 4;
-/// Debug log level.
-pub const LOG_TAG_DEBUG: i32 = 5;
-/// Verbose log level.
-pub const LOG_TAG_VERBOSE: i32 = 6;
-
 init_flags!(
     name: InitFlags
     flags: {
@@ -394,21 +259,7 @@ init_flags!(
         att_mtu_default: i32 = 517,
         encryption_in_busy_state = true,
     }
-    // dynamic flags can be updated at runtime and should be accessed directly
-    // to check.
-    dynamic_flags: {
-        default_log_level : i32 = LOG_TAG_INFO,
-    }
-    // extra_fields are not a 1 to 1 match with "INIT_*" flags
-    extra_fields: {
-        logging_explicit_tag_settings: ExplicitTagSettings,
-    }
     extra_parsed_flags: {
-        "INIT_default_log_level_str" => parse_log_level(_, _),
-        "INIT_log_level_for_tags" => parse_logging_tag(_, _),
-        "INIT_logging_debug_enabled_for_all" => deprecated_set_debug_logging_enabled_for_all(_, _),
-        "INIT_logging_debug_enabled_for_tags" => parse_debug_logging_tag(_, _, true),
-        "INIT_logging_debug_disabled_for_tags" => parse_debug_logging_tag(_, _, false),
         "--hci" => parse_hci_adapter(_, _),
     }
     dependencies: {
@@ -433,9 +284,6 @@ pub fn load(raw_flags: Vec<String>) {
     let flags = InitFlags::parse(raw_flags);
     info!("Flags loaded: {}", flags);
     *FLAGS.lock().unwrap() = flags;
-
-    // re-init to respect log levels set by flags
-    crate::init_logging();
 }
 
 /// Dumps all flag K-V pairs, storing values as strings
@@ -486,29 +334,6 @@ mod tests {
         assert_eq!(get_hci_adapter(), 2);
     }
     #[test]
-    fn explicit_flag() {
-        let _guard = ASYNC_LOCK.lock().unwrap();
-        test_load(vec![
-            "INIT_default_log_level_str=LOG_VERBOSE",
-            "INIT_logging_debug_enabled_for_tags=foo,bar",
-            "INIT_logging_debug_disabled_for_tags=foo,bar2,fizz",
-            "INIT_logging_debug_enabled_for_tags=bar2",
-            "INIT_log_level_for_tags=fizz:LOG_WARN,buzz:LOG_NOTICE",
-        ]);
-
-        assert!(get_log_level_for_tag("foo") == LOG_TAG_INFO);
-        assert!(get_log_level_for_tag("bar") == LOG_TAG_VERBOSE);
-        assert!(get_log_level_for_tag("bar2") == LOG_TAG_VERBOSE);
-        assert!(get_log_level_for_tag("unknown_flag") == LOG_TAG_VERBOSE);
-        assert!(get_default_log_level() == LOG_TAG_VERBOSE);
-        FLAGS.lock().unwrap().default_log_level = LOG_TAG_INFO;
-        assert!(get_log_level_for_tag("foo") == LOG_TAG_INFO);
-        assert!(get_log_level_for_tag("bar") == LOG_TAG_VERBOSE);
-        assert!(get_log_level_for_tag("bar2") == LOG_TAG_VERBOSE);
-        assert!(get_log_level_for_tag("unknown_flag") == LOG_TAG_INFO);
-        assert!(get_default_log_level() == LOG_TAG_INFO);
-    }
-    #[test]
     fn test_redact_logging() {
         let _guard = ASYNC_LOCK.lock().unwrap();
         assert!(redact_log_is_enabled()); // default is true
@@ -519,63 +344,23 @@ mod tests {
         test_load(vec!["INIT_redact_log=true"]);
         assert!(redact_log_is_enabled()); // turned on
     }
-    #[test]
-    fn test_runtime_update() {
-        let _guard = ASYNC_LOCK.lock().unwrap();
-        test_load(vec!["INIT_private_gatt=true", "INIT_default_log_level_str=LOG_WARN"]);
-        assert!(private_gatt_is_enabled());
-        assert!(get_default_log_level() == LOG_TAG_WARN);
-
-        update_default_log_level(LOG_TAG_DEBUG);
-        assert!(get_default_log_level() == LOG_TAG_DEBUG);
-        update_default_log_level(LOG_TAG_ERROR);
-        assert!(get_default_log_level() == LOG_TAG_ERROR);
-    }
-    #[test]
-    fn test_default_log_level() {
-        // Default log level can be provided via int value or string.
-        // The string version is just for ease-of-use.
-        let _guard = ASYNC_LOCK.lock().unwrap();
-        test_load(vec!["INIT_default_log_level=1"]);
-        assert!(get_default_log_level() == LOG_TAG_ERROR);
-        test_load(vec!["INIT_default_log_level_str=LOG_VERBOSE"]);
-        assert!(get_default_log_level() == LOG_TAG_VERBOSE);
-        test_load(vec!["INIT_default_log_level_str=LOG_VERBOSE", "INIT_default_log_level=0"]);
-        assert!(get_default_log_level() == LOG_TAG_FATAL);
-    }
-    #[test]
-    fn test_deprecated_logging_flag() {
-        let _guard = ASYNC_LOCK.lock().unwrap();
-        test_load(vec!["INIT_default_log_level_str=1", "INIT_logging_debug_enabled_for_all=true"]);
-        assert!(get_default_log_level() == LOG_TAG_VERBOSE);
-        test_load(vec!["INIT_logging_debug_enabled_for_all=false"]);
-        assert!(get_default_log_level() == LOG_TAG_INFO);
-    }
 
     init_flags_struct!(
         name: InitFlagsForTest
         flags: {
             cat,
         }
-        dynamic_flags: {
-            dog: i32 = 8,
-        }
-        extra_fields: {
-            elephant: String,
-        }
         extra_parsed_flags: {}
         dependencies: {}
     );
 
     #[test]
     fn test_dumpsys() {
-        let flags = InitFlagsForTest { dog: 3, elephant: "Go bears!".into(), ..Default::default() };
+        let flags = InitFlagsForTest { ..Default::default() };
 
         let out = flags.dump();
 
-        assert_eq!(out.len(), 3);
+        assert_eq!(out.len(), 1);
         assert_eq!(out["cat"], "false");
-        assert_eq!(out["dog"], "3");
-        assert_eq!(out["elephant"], "Go bears!");
     }
 }
diff --git a/system/gd/rust/common/src/logging.rs b/system/gd/rust/common/src/logging.rs
index 89577de902b8bc7ade7ffc4ef232fddb991bd320..4207114d92ac37fdf1f49928b853dda6c09b2377 100644
--- a/system/gd/rust/common/src/logging.rs
+++ b/system/gd/rust/common/src/logging.rs
@@ -1,33 +1,11 @@
-use crate::init_flags::{
-    get_log_level_for_tag, LOG_TAG_DEBUG, LOG_TAG_ERROR, LOG_TAG_FATAL, LOG_TAG_INFO,
-    LOG_TAG_NOTICE, LOG_TAG_VERBOSE, LOG_TAG_WARN,
-};
-
-fn get_log_level() -> log::LevelFilter {
-    match get_log_level_for_tag("bluetooth_core") {
-        LOG_TAG_FATAL => log::LevelFilter::Error,
-        LOG_TAG_ERROR => log::LevelFilter::Error,
-        LOG_TAG_WARN => log::LevelFilter::Warn,
-        LOG_TAG_NOTICE => log::LevelFilter::Info,
-        LOG_TAG_INFO => log::LevelFilter::Info,
-        LOG_TAG_DEBUG => log::LevelFilter::Debug,
-        LOG_TAG_VERBOSE => log::LevelFilter::Trace,
-        _ => log::LevelFilter::Info, // default level
-    }
-}
-
 /// Inits logging for Android
 #[cfg(target_os = "android")]
 pub fn init_logging() {
-    android_logger::init_once(
-        android_logger::Config::default().with_tag("bt").with_max_level(get_log_level()),
-    );
-    log::set_max_level(get_log_level())
+    android_logger::init_once(android_logger::Config::default().with_tag("bt"));
 }
 
 /// Inits logging for host
 #[cfg(not(target_os = "android"))]
 pub fn init_logging() {
-    env_logger::Builder::new().filter(None, get_log_level()).parse_default_env().try_init().ok();
-    log::set_max_level(get_log_level())
+    env_logger::Builder::new().parse_default_env().try_init().ok();
 }
diff --git a/system/gd/rust/linux/service/src/main.rs b/system/gd/rust/linux/service/src/main.rs
index a35f789f98f3fce337557a3cd03a8a6fd9ff77d0..22a49044ece5d24e2cba0fd33bb461efa22f573f 100644
--- a/system/gd/rust/linux/service/src/main.rs
+++ b/system/gd/rust/linux/service/src/main.rs
@@ -50,15 +50,6 @@ const STACK_TURN_OFF_TIMEOUT_MS: Duration = Duration::from_millis(4000);
 // Time bt_stack_manager waits for cleanup
 const STACK_CLEANUP_TIMEOUT_MS: Duration = Duration::from_millis(1000);
 
-const VERBOSE_ONLY_LOG_TAGS: &[&str] = &[
-    "bt_bta_av", // AV apis
-    "btm_sco",   // SCO data path logs
-    "l2c_csm",   // L2CAP state machine
-    "l2c_link",  // L2CAP link layer logs
-    "sco_hci",   // SCO over HCI
-    "uipc",      // Userspace IPC implementation
-];
-
 const INIT_LOGGING_MAX_RETRY: u8 = 3;
 
 /// Runs the Bluetooth daemon serving D-Bus IPC.
@@ -111,24 +102,14 @@ fn main() -> Result<(), Box<dyn Error>> {
         None => vec![],
     };
 
-    // Set GD debug flag if debug is enabled.
-    if is_debug {
-        // Limit tags if verbose debug logging isn't enabled.
-        if !is_verbose_debug {
-            init_flags.push(format!(
-                "INIT_logging_debug_disabled_for_tags={}",
-                VERBOSE_ONLY_LOG_TAGS.join(",")
-            ));
-            init_flags.push(String::from("INIT_default_log_level_str=LOG_DEBUG"));
-        } else {
-            init_flags.push(String::from("INIT_default_log_level_str=LOG_VERBOSE"));
-        }
-    }
-
     // Forward --hci to Fluoride.
     init_flags.push(format!("--hci={}", hci_index));
 
-    let logging = Arc::new(Mutex::new(Box::new(BluetoothLogging::new(is_debug, log_output))));
+    let logging = Arc::new(Mutex::new(Box::new(BluetoothLogging::new(
+        is_debug,
+        is_verbose_debug,
+        log_output,
+    ))));
     // TODO(b/307171804): Investigate why connecting to unix syslog might fail.
     // Retry it a few times. Ignore the failure if fails too many times.
     for _ in 0..INIT_LOGGING_MAX_RETRY {
diff --git a/system/gd/rust/linux/stack/src/bluetooth_logging.rs b/system/gd/rust/linux/stack/src/bluetooth_logging.rs
index 2fbd181d5e1c83361820f4afdfc314fee235c8f8..aa2a0c0e189b832ca933ff742c9be142f4969a78 100644
--- a/system/gd/rust/linux/stack/src/bluetooth_logging.rs
+++ b/system/gd/rust/linux/stack/src/bluetooth_logging.rs
@@ -1,10 +1,16 @@
-use bt_common::init_flags;
+//! Modify the Bluetooth logging configuration to enable debug logging.
+//!
+//! There are two logging implementations depending on whether the log is
+//! emitted from Rust or C/C++. In order to keep log levels in sync between the
+//! two, the |BluetoothLogging| struct will configure both the Rust logging and
+//! the C/C++ logging (via topshim).
+use bt_topshim::syslog::{set_default_log_level, set_log_level_for_tag, Level};
 use log::LevelFilter;
 use syslog::{BasicLogger, Error, Facility, Formatter3164};
 
 use log_panics;
 
-/// API to modify log levels.
+/// API to modify log levels that is exposed via RPC.
 pub trait IBluetoothLogging {
     /// Check whether debug logging is enabled.
     fn is_debug_enabled(&self) -> bool;
@@ -15,15 +21,34 @@ pub trait IBluetoothLogging {
 
 /// Logging related implementation.
 pub struct BluetoothLogging {
+    /// Should debug logs be emitted?
     is_debug: bool,
+
+    /// If this flag is not set, we will not emit debug logs for all tags.
+    /// `VERBOSE_ONLY_LOG_TAGS` will be set to emit up to `INFO` only. This
+    /// can only be configured in the constructor (not modifiable at runtime).
+    is_verbose_debug: bool,
+
+    /// Log to stderr?
     is_stderr: bool,
+
+    /// Is logging already initialized?
     is_initialized: bool,
 }
 
+const VERBOSE_ONLY_LOG_TAGS: &[&str] = &[
+    "bt_bta_av", // AV apis
+    "btm_sco",   // SCO data path logs
+    "l2c_csm",   // L2CAP state machine
+    "l2c_link",  // L2CAP link layer logs
+    "sco_hci",   // SCO over HCI
+    "uipc",      // Userspace IPC implementation
+];
+
 impl BluetoothLogging {
-    pub fn new(is_debug: bool, log_output: &str) -> Self {
+    pub fn new(is_debug: bool, is_verbose_debug: bool, log_output: &str) -> Self {
         let is_stderr = log_output == "stderr";
-        Self { is_debug, is_stderr, is_initialized: false }
+        Self { is_debug, is_verbose_debug, is_stderr, is_initialized: false }
     }
 
     pub fn initialize(&mut self) -> Result<(), Error> {
@@ -44,9 +69,31 @@ impl BluetoothLogging {
                 .map(|()| log::set_max_level(level));
             log_panics::init();
         }
+
+        // Set initial log levels and filter out tags if not verbose debug.
+        set_default_log_level(self.get_libbluetooth_level());
+        if self.is_debug && !self.is_verbose_debug {
+            for tag in VERBOSE_ONLY_LOG_TAGS {
+                set_log_level_for_tag(tag, Level::Info);
+            }
+        }
+
+        // Initialize the underlying system as well.
         self.is_initialized = true;
         Ok(())
     }
+
+    fn get_libbluetooth_level(&self) -> Level {
+        if self.is_debug {
+            if self.is_verbose_debug {
+                Level::Verbose
+            } else {
+                Level::Debug
+            }
+        } else {
+            Level::Info
+        }
+    }
 }
 
 impl IBluetoothLogging for BluetoothLogging {
@@ -66,9 +113,8 @@ impl IBluetoothLogging for BluetoothLogging {
         log::set_max_level(level);
 
         // Update log level in libbluetooth.
-        let level =
-            if self.is_debug { init_flags::LOG_TAG_DEBUG } else { init_flags::LOG_TAG_INFO };
-        init_flags::update_default_log_level(level);
+        let level = self.get_libbluetooth_level();
+        set_default_log_level(level);
 
         // Mark the start of debug logging with a debug print.
         if self.is_debug {
diff --git a/system/gd/rust/shim/src/init_flags.rs b/system/gd/rust/shim/src/init_flags.rs
index 69ce71182b0eded4889986732fd6b6ca437a69dd..4017057fb164c9cd8e9940737e5c229bef0fe026 100644
--- a/system/gd/rust/shim/src/init_flags.rs
+++ b/system/gd/rust/shim/src/init_flags.rs
@@ -25,9 +25,7 @@ mod ffi {
         fn dynamic_avrcp_version_enhancement_is_enabled() -> bool;
         fn gatt_robust_caching_client_is_enabled() -> bool;
         fn gatt_robust_caching_server_is_enabled() -> bool;
-        fn get_default_log_level() -> i32;
         fn get_hci_adapter() -> i32;
-        fn get_log_level_for_tag(tag: &str) -> i32;
         fn get_asha_packet_drop_frequency_threshold() -> i32;
         fn get_asha_phy_update_retry_limit() -> i32;
         fn hfp_dynamic_version_is_enabled() -> bool;
diff --git a/system/gd/rust/topshim/src/lib.rs b/system/gd/rust/topshim/src/lib.rs
index 27772b3eb1e6ab6846c0ca7390e91f9ac142dad4..6d7bb3b5b4b56399367f0077abb19326fed16743 100644
--- a/system/gd/rust/topshim/src/lib.rs
+++ b/system/gd/rust/topshim/src/lib.rs
@@ -20,6 +20,7 @@ pub mod btif;
 pub mod controller;
 pub mod metrics;
 pub mod profiles;
+pub mod syslog;
 pub mod sysprop;
 pub mod topstack;
 
diff --git a/system/gd/rust/topshim/src/syslog.rs b/system/gd/rust/topshim/src/syslog.rs
new file mode 100644
index 0000000000000000000000000000000000000000..fd575ba485614fd6f1e5da3224901b7cc20bae06
--- /dev/null
+++ b/system/gd/rust/topshim/src/syslog.rs
@@ -0,0 +1,56 @@
+//! Expose some internal methods to set the log level for system syslog.
+//!
+//! On systems that use syslog (i.e. `vlog_syslog.cc`), there is support
+//! to filter out logs before they go to syslog. This module provides Rust apis
+//! to tune log levels for syslog.
+
+use num_derive::ToPrimitive;
+use num_traits::cast::ToPrimitive;
+use std::ffi::CString;
+use std::os::raw::c_char;
+
+#[derive(ToPrimitive)]
+#[repr(u8)]
+/// Android framework log priority levels.
+/// They are defined in system/logging/liblog/include/android/log.h by
+/// the Android Framework code.
+pub enum Level {
+    Verbose = 2,
+    Debug = 3,
+    Info = 4,
+    Warn = 5,
+    Error = 6,
+    Fatal = 7,
+}
+
+// Defined in syslog linkage. See |vlog_syslog.cc|.
+extern "C" {
+    fn SetLogLevelForTag(tag: *const c_char, level: u8);
+    fn SetDefaultLogLevel(level: u8);
+}
+
+/// Set a default level value for failed |level.to_u8()| of |Level::Info|.
+const DEFAULT_LEVEL: u8 = 4;
+
+/// Set the level of logs which will get printed for the given tag.
+///
+/// Args:
+///     tag - LOG_TAG for the system module that's logging.
+///     level - Minimum log level that will be sent to syslog.
+pub fn set_log_level_for_tag(tag: &str, level: Level) {
+    let cstr: CString = CString::new(tag).expect("CString::new failed on log tag");
+
+    unsafe {
+        SetLogLevelForTag(cstr.as_ptr(), level.to_u8().unwrap_or(DEFAULT_LEVEL));
+    }
+}
+
+/// Set the default log level for log tags. Will be overridden by any tag specific levels.
+///
+/// Args:
+///     level - Minimum log level that will be sent to syslog.
+pub fn set_default_log_level(level: Level) {
+    unsafe {
+        SetDefaultLogLevel(level.to_u8().unwrap_or(DEFAULT_LEVEL));
+    }
+}
diff --git a/system/log/src/vlog_syslog.cc b/system/log/src/vlog_syslog.cc
index 9d7dad1a965c0e1674a8fc0b7c6ee349336cc72c..d119ca13396d5f12ebf3cae21baed73451d4b4a7 100644
--- a/system/log/src/vlog_syslog.cc
+++ b/system/log/src/vlog_syslog.cc
@@ -16,17 +16,47 @@
 
 #include <syslog.h>
 
+#include <string>
+#include <unordered_map>
+
 #include "bluetooth/log.h"
 #include "truncating_buffer.h"
 
 namespace bluetooth::log_internal {
 
+// Map of tags with custom levels.
+std::unordered_map<std::string, Level>& GetTagMap() {
+  static std::unordered_map<std::string, Level> tag_level_map;
+  return tag_level_map;
+}
+
+// Default log level.
+Level gDefaultLogLevel = Level::kInfo;
+
+Level GetLogLevelForTag(char const* tag) {
+  auto tag_map = GetTagMap();
+  auto find = tag_map.find(tag);
+  if (find != tag_map.end()) {
+    return find->second;
+  } else {
+    return gDefaultLogLevel;
+  }
+}
+
+Level GetDefaultLogLevel() { return gDefaultLogLevel; }
+
 // Default value for $MaxMessageSize for rsyslog.
 static constexpr size_t kBufferSize = 8192;
 
 void vlog(Level level, char const* tag, char const* file_name, int line,
           char const* function_name, fmt::string_view fmt,
           fmt::format_args vargs) {
+  // Filter out logs that don't meet level requirement.
+  Level current_level = GetLogLevelForTag(tag);
+  if (level < current_level) {
+    return;
+  }
+
   // Convert the level to syslog severity.
   int severity = LOG_DEBUG;
   switch (level) {
@@ -64,3 +94,26 @@ void vlog(Level level, char const* tag, char const* file_name, int line,
 }
 
 }  // namespace bluetooth::log_internal
+
+// These apis will be exposed in topshim to allow control of syslog log levels.
+extern "C" {
+void SetLogLevelForTag(char const* tag, uint8_t level) {
+  if (level < bluetooth::log_internal::Level::kVerbose ||
+      level > bluetooth::log_internal::Level::kFatal) {
+    level = bluetooth::log_internal::GetDefaultLogLevel();
+  }
+
+  bluetooth::log_internal::GetTagMap().emplace(
+      tag, static_cast<bluetooth::log_internal::Level>(level));
+}
+
+void SetDefaultLogLevel(uint8_t level) {
+  if (level < bluetooth::log_internal::Level::kVerbose ||
+      level > bluetooth::log_internal::Level::kFatal) {
+    return;
+  }
+
+  bluetooth::log_internal::gDefaultLogLevel =
+      static_cast<bluetooth::log_internal::Level>(level);
+}
+}