Add configurability of the log Tag value on Android

PiperOrigin-RevId: 525178448
Change-Id: I0f35a38f23316b25621148b7fe59becf72bafeff
diff --git a/absl/log/BUILD.bazel b/absl/log/BUILD.bazel
index 378e1f3..4813111 100644
--- a/absl/log/BUILD.bazel
+++ b/absl/log/BUILD.bazel
@@ -109,6 +109,7 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:log_severity",
+        "//absl/base:raw_logging_internal",
         "//absl/hash",
         "//absl/strings",
     ],
diff --git a/absl/log/CMakeLists.txt b/absl/log/CMakeLists.txt
index 78adbf1..4cba008 100644
--- a/absl/log/CMakeLists.txt
+++ b/absl/log/CMakeLists.txt
@@ -501,6 +501,7 @@
     absl::core_headers
     absl::hash
     absl::log_severity
+    absl::raw_logging_internal
     absl::strings
 )
 
diff --git a/absl/log/globals.cc b/absl/log/globals.cc
index f7c2ec4..cc85438 100644
--- a/absl/log/globals.cc
+++ b/absl/log/globals.cc
@@ -14,14 +14,17 @@
 
 #include "absl/log/globals.h"
 
-#include <stddef.h>
-#include <stdint.h>
-
 #include <atomic>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <string>
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/atomic_hook.h"
+#include "absl/base/internal/raw_logging.h"
 #include "absl/base/log_severity.h"
 #include "absl/hash/hash.h"
 #include "absl/strings/string_view.h"
@@ -43,6 +46,9 @@
 ABSL_CONST_INIT std::atomic<size_t> log_backtrace_at_hash{0};
 ABSL_CONST_INIT std::atomic<bool> prepend_log_prefix{true};
 
+constexpr char kDefaultAndroidTag[] = "native";
+ABSL_CONST_INIT std::atomic<const char*> android_log_tag{kDefaultAndroidTag};
+
 ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
 absl::base_internal::AtomicHook<log_internal::LoggingGlobalsListener>
     logging_globals_listener;
@@ -121,6 +127,26 @@
 
 namespace log_internal {
 
+const char* GetAndroidNativeTag() {
+  return android_log_tag.load(std::memory_order_acquire);
+}
+
+}  // namespace log_internal
+
+void SetAndroidNativeTag(const char* tag) {
+  ABSL_CONST_INIT static std::atomic<const std::string*> user_log_tag(nullptr);
+  ABSL_INTERNAL_CHECK(tag, "tag must be non-null.");
+
+  const std::string* tag_str = new std::string(tag);
+  ABSL_INTERNAL_CHECK(
+      android_log_tag.exchange(tag_str->c_str(), std::memory_order_acq_rel) ==
+          kDefaultAndroidTag,
+      "SetAndroidNativeTag() must only be called once per process!");
+  user_log_tag.store(tag_str, std::memory_order_relaxed);
+}
+
+namespace log_internal {
+
 bool ShouldLogBacktraceAt(absl::string_view file, int line) {
   const size_t flag_hash =
       log_backtrace_at_hash.load(std::memory_order_relaxed);
diff --git a/absl/log/globals.h b/absl/log/globals.h
index d56622a..bc3864c 100644
--- a/absl/log/globals.h
+++ b/absl/log/globals.h
@@ -152,6 +152,29 @@
 // This function is async-signal-safe.
 void EnableLogPrefix(bool on_off);
 
+//------------------------------------------------------------------------------
+// Configure Android Native Log Tag
+//------------------------------------------------------------------------------
+//
+// The logging library forwards to the Android system log API when built for
+// Android.  That API takes a string "tag" value in addition to a message and
+// severity level.  The tag is used to identify the source of messages and to
+// filter them.  This library uses the tag "native" by default.
+
+// SetAndroidNativeTag()
+//
+// Stores a copy of the string pointed to by `tag` and uses it as the Android
+// logging tag thereafter. `tag` must not be null.
+// This function must not be called more than once!
+void SetAndroidNativeTag(const char* tag);
+
+namespace log_internal {
+// GetAndroidNativeTag()
+//
+// Returns the configured Android logging tag.
+const char* GetAndroidNativeTag();
+}  // namespace log_internal
+
 namespace log_internal {
 
 using LoggingGlobalsListener = void (*)();
diff --git a/absl/log/globals_test.cc b/absl/log/globals_test.cc
index 6710c5a..f7af47c 100644
--- a/absl/log/globals_test.cc
+++ b/absl/log/globals_test.cc
@@ -15,8 +15,6 @@
 
 #include "absl/log/globals.h"
 
-#include <string>
-
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/base/attributes.h"
@@ -27,6 +25,8 @@
 #include "absl/log/scoped_mock_log.h"
 
 namespace {
+using ::testing::_;
+using ::testing::StrEq;
 
 auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
     new absl::log_internal::LogTestEnvironment);
@@ -88,4 +88,17 @@
   EXPECT_TRUE(absl::ShouldPrependLogPrefix());
 }
 
+TEST(TestGlobals, AndroidLogTag) {
+  // Verify invalid tags result in a check failure.
+  EXPECT_DEATH_IF_SUPPORTED(absl::SetAndroidNativeTag(nullptr), ".*");
+
+  // Verify valid tags applied.
+  EXPECT_THAT(absl::log_internal::GetAndroidNativeTag(), StrEq("native"));
+  absl::SetAndroidNativeTag("test_tag");
+  EXPECT_THAT(absl::log_internal::GetAndroidNativeTag(), StrEq("test_tag"));
+
+  // Verify that additional calls (more than 1) result in a check failure.
+  EXPECT_DEATH_IF_SUPPORTED(absl::SetAndroidNativeTag("test_tag_fail"), ".*");
+}
+
 }  // namespace
diff --git a/absl/log/internal/log_sink_set.cc b/absl/log/internal/log_sink_set.cc
index f9d030a..b7cbe36 100644
--- a/absl/log/internal/log_sink_set.cc
+++ b/absl/log/internal/log_sink_set.cc
@@ -122,11 +122,11 @@
 
   void Send(const absl::LogEntry& entry) override {
     const int level = AndroidLogLevel(entry);
-    // TODO(b/37587197): make the tag ("native") configurable.
-    __android_log_write(level, "native",
+    const char* const tag = GetAndroidNativeTag();
+    __android_log_write(level, tag,
                         entry.text_message_with_prefix_and_newline_c_str());
     if (entry.log_severity() == absl::LogSeverity::kFatal)
-      __android_log_write(ANDROID_LOG_FATAL, "native", "terminating.\n");
+      __android_log_write(ANDROID_LOG_FATAL, tag, "terminating.\n");
   }
 
  private: