Merge changes from topic "health2_passthru"

* changes:
  healthd: charger use health 2.0 HAL
  healthd: move healthd_board_init call to Health::Health() c-tor
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index d6b6d58..bd202ff 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -429,7 +429,12 @@
     abort_message = g_callbacks.get_abort_message();
   }
 
-  if (prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) == 1) {
+  // If sival_int is ~0, it means that the fallback handler has been called
+  // once before and this function is being called again to dump the stack
+  // of a specific thread. It is possible that the prctl call might return 1,
+  // then return 0 in subsequent calls, so check the sival_int to determine if
+  // the fallback handler should be called first.
+  if (info->si_value.sival_int == ~0 || prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) == 1) {
     // This check might be racy if another thread sets NO_NEW_PRIVS, but this should be unlikely,
     // you can only set NO_NEW_PRIVS to 1, and the effect should be at worst a single missing
     // ANR trace.
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index 85a593f..cbd8ffa 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -115,7 +115,9 @@
 
     std::string size_str = std::to_string(dev_sz / 4096);
     const char* const args[] = {
-        "/system/bin/make_f2fs", "-f", "-O", "encrypt", fs_blkdev, size_str.c_str(), nullptr};
+        "/system/bin/make_f2fs", "-d1", "-f",
+        "-O", "encrypt", "-O", "quota",
+        fs_blkdev, size_str.c_str(), nullptr};
 
     return android_fork_execvp_ext(arraysize(args), const_cast<char**>(args), NULL, true,
                                    LOG_KLOG, true, nullptr, nullptr, 0);
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index 61c8804..5781765 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -25,14 +25,15 @@
 #include <unistd.h>
 #include <memory>
 
+#include <android/security/IKeystoreService.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
 #include <gatekeeper/password_handle.h> // for password_handle_t
 #include <hardware/gatekeeper.h>
 #include <hardware/hw_auth_token.h>
-#include <keystore/IKeystoreService.h>
 #include <keystore/keystore.h> // For error code
+#include <keystore/keystore_return_types.h>
 #include <log/log.h>
 #include <utils/Log.h>
 #include <utils/String16.h>
@@ -315,11 +316,15 @@
             // TODO: cache service?
             sp<IServiceManager> sm = defaultServiceManager();
             sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
-            sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+            sp<security::IKeystoreService> service =
+                interface_cast<security::IKeystoreService>(binder);
             if (service != NULL) {
-                auto ret = service->addAuthToken(*auth_token, *auth_token_length);
-                if (!ret.isOk()) {
-                    ALOGE("Failure sending auth token to KeyStore: %" PRId32, int32_t(ret));
+                std::vector<uint8_t> auth_token_vector(*auth_token,
+                                                       (*auth_token) + *auth_token_length);
+                int result = 0;
+                auto binder_result = service->addAuthToken(auth_token_vector, &result);
+                if (!binder_result.isOk() || !keystore::KeyStoreServiceReturnCode(result).isOk()) {
+                    ALOGE("Failure sending auth token to KeyStore: %" PRId32, result);
                 }
             } else {
                 ALOGE("Unable to communicate with KeyStore");
diff --git a/init/action.cpp b/init/action.cpp
index 2617d00..5fa6bec 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -379,10 +379,12 @@
     return action_ ? action_->AddCommand(std::move(args), line) : Success();
 }
 
-void ActionParser::EndSection() {
+Result<Success> ActionParser::EndSection() {
     if (action_ && action_->NumCommands() > 0) {
         action_manager_->AddAction(std::move(action_));
     }
+
+    return Success();
 }
 
 }  // namespace init
diff --git a/init/action.h b/init/action.h
index cdfc6a0..1bfc6c7 100644
--- a/init/action.h
+++ b/init/action.h
@@ -130,7 +130,7 @@
     Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
                                  int line) override;
     Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
-    void EndSection() override;
+    Result<Success> EndSection() override;
 
   private:
     ActionManager* action_manager_;
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 29a65ab..268873c 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -25,6 +25,7 @@
 #include "import_parser.h"
 #include "keyword_map.h"
 #include "parser.h"
+#include "service.h"
 #include "test_function_map.h"
 #include "util.h"
 
@@ -34,12 +35,13 @@
 using ActionManagerCommand = std::function<void(ActionManager&)>;
 
 void TestInit(const std::string& init_script_file, const TestFunctionMap& test_function_map,
-              const std::vector<ActionManagerCommand>& commands) {
+              const std::vector<ActionManagerCommand>& commands, ServiceList* service_list) {
     ActionManager am;
 
     Action::set_function_map(&test_function_map);
 
     Parser parser;
+    parser.AddSectionParser("service", std::make_unique<ServiceParser>(service_list, nullptr));
     parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
     parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
 
@@ -55,11 +57,11 @@
 }
 
 void TestInitText(const std::string& init_script, const TestFunctionMap& test_function_map,
-                  const std::vector<ActionManagerCommand>& commands) {
+                  const std::vector<ActionManagerCommand>& commands, ServiceList* service_list) {
     TemporaryFile tf;
     ASSERT_TRUE(tf.fd != -1);
     ASSERT_TRUE(android::base::WriteStringToFd(init_script, tf.fd));
-    TestInit(tf.path, test_function_map, commands);
+    TestInit(tf.path, test_function_map, commands, service_list);
 }
 
 TEST(init, SimpleEventTrigger) {
@@ -76,7 +78,8 @@
     ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
     std::vector<ActionManagerCommand> commands{trigger_boot};
 
-    TestInitText(init_script, test_function_map, commands);
+    ServiceList service_list;
+    TestInitText(init_script, test_function_map, commands, &service_list);
 
     EXPECT_TRUE(expect_true);
 }
@@ -104,7 +107,30 @@
     ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
     std::vector<ActionManagerCommand> commands{trigger_boot};
 
-    TestInitText(init_script, test_function_map, commands);
+    ServiceList service_list;
+    TestInitText(init_script, test_function_map, commands, &service_list);
+}
+
+TEST(init, OverrideService) {
+    std::string init_script = R"init(
+service A something
+    class first
+
+service A something
+    class second
+    override
+
+)init";
+
+    ServiceList service_list;
+    TestInitText(init_script, TestFunctionMap(), {}, &service_list);
+    ASSERT_EQ(1, std::distance(service_list.begin(), service_list.end()));
+
+    auto service = service_list.begin()->get();
+    ASSERT_NE(nullptr, service);
+    EXPECT_EQ(std::set<std::string>({"second"}), service->classnames());
+    EXPECT_EQ("A", service->name());
+    EXPECT_TRUE(service->is_override());
 }
 
 TEST(init, EventTriggerOrderMultipleFiles) {
@@ -162,7 +188,9 @@
     ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
     std::vector<ActionManagerCommand> commands{trigger_boot};
 
-    TestInit(start.path, test_function_map, commands);
+    ServiceList service_list;
+
+    TestInit(start.path, test_function_map, commands, &service_list);
 
     EXPECT_EQ(6, num_executed);
 }
diff --git a/init/parser.cpp b/init/parser.cpp
index 8a4e798..6ddb09f 100644
--- a/init/parser.cpp
+++ b/init/parser.cpp
@@ -50,12 +50,24 @@
     state.nexttoken = 0;
 
     SectionParser* section_parser = nullptr;
+    int section_start_line = -1;
     std::vector<std::string> args;
 
+    auto end_section = [&] {
+        if (section_parser == nullptr) return;
+
+        if (auto result = section_parser->EndSection(); !result) {
+            LOG(ERROR) << filename << ": " << section_start_line << ": " << result.error();
+        }
+
+        section_parser = nullptr;
+        section_start_line = -1;
+    };
+
     for (;;) {
         switch (next_token(&state)) {
             case T_EOF:
-                if (section_parser) section_parser->EndSection();
+                end_section();
                 return;
             case T_NEWLINE:
                 state.line++;
@@ -65,18 +77,18 @@
                 // uevent.
                 for (const auto& [prefix, callback] : line_callbacks_) {
                     if (android::base::StartsWith(args[0], prefix.c_str())) {
-                        if (section_parser) section_parser->EndSection();
+                        end_section();
 
                         if (auto result = callback(std::move(args)); !result) {
                             LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
                         }
-                        section_parser = nullptr;
                         break;
                     }
                 }
                 if (section_parsers_.count(args[0])) {
-                    if (section_parser) section_parser->EndSection();
+                    end_section();
                     section_parser = section_parsers_[args[0]].get();
+                    section_start_line = state.line;
                     if (auto result =
                             section_parser->ParseSection(std::move(args), filename, state.line);
                         !result) {
diff --git a/init/parser.h b/init/parser.h
index 4ab24a4..110a468 100644
--- a/init/parser.h
+++ b/init/parser.h
@@ -26,24 +26,22 @@
 
 //  SectionParser is an interface that can parse a given 'section' in init.
 //
-//  You can implement up to 4 functions below, with ParseSection() being mandatory.
-//  The first two function return bool with false indicating a failure and has a std::string* err
-//  parameter into which an error string can be written.  It will be reported along with the
-//  filename and line number of where the error occurred.
+//  You can implement up to 4 functions below, with ParseSection being mandatory. The first two
+//  functions return Result<Success> indicating if they have an error. It will be reported along
+//  with the filename and line number of where the error occurred.
 //
-//  1) bool ParseSection(std::vector<std::string>&& args, const std::string& filename,
-//                       int line, std::string* err)
+//  1) ParseSection
 //    This function is called when a section is first encountered.
 //
-//  2) bool ParseLineSection(std::vector<std::string>&& args, int line, std::string* err)
+//  2) ParseLineSection
 //    This function is called on each subsequent line until the next section is encountered.
 //
-//  3) bool EndSection()
+//  3) EndSection
 //    This function is called either when a new section is found or at the end of the file.
 //    It indicates that parsing of the current section is complete and any relevant objects should
 //    be committed.
 //
-//  4) bool EndFile()
+//  4) EndFile
 //    This function is called at the end of the file.
 //    It indicates that the parsing has completed and any relevant objects should be committed.
 
@@ -56,7 +54,7 @@
     virtual Result<Success> ParseSection(std::vector<std::string>&& args,
                                          const std::string& filename, int line) = 0;
     virtual Result<Success> ParseLineSection(std::vector<std::string>&&, int) { return Success(); };
-    virtual void EndSection(){};
+    virtual Result<Success> EndSection() { return Success(); };
     virtual void EndFile(){};
 };
 
diff --git a/init/service.cpp b/init/service.cpp
index 12acfc6..481df65 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -530,6 +530,11 @@
     return Success();
 }
 
+Result<Success> Service::ParseOverride(const std::vector<std::string>& args) {
+    override_ = true;
+    return Success();
+}
+
 Result<Success> Service::ParseMemcgSwappiness(const std::vector<std::string>& args) {
     if (!ParseInt(args[1], &swappiness_, 0)) {
         return Error() << "swappiness value must be equal or greater than 0";
@@ -671,6 +676,7 @@
         {"keycodes",    {1,     kMax, &Service::ParseKeycodes}},
         {"oneshot",     {0,     0,    &Service::ParseOneshot}},
         {"onrestart",   {1,     kMax, &Service::ParseOnrestart}},
+        {"override",    {0,     0,    &Service::ParseOverride}},
         {"oom_score_adjust",
                         {1,     1,    &Service::ParseOomScoreAdjust}},
         {"memcg.swappiness",
@@ -1111,11 +1117,6 @@
         return Error() << "invalid service name '" << name << "'";
     }
 
-    Service* old_service = service_list_->FindService(name);
-    if (old_service) {
-        return Error() << "ignored duplicate definition of service '" << name << "'";
-    }
-
     Subcontext* restart_action_subcontext = nullptr;
     if (subcontexts_) {
         for (auto& subcontext : *subcontexts_) {
@@ -1135,10 +1136,23 @@
     return service_ ? service_->ParseLine(std::move(args)) : Success();
 }
 
-void ServiceParser::EndSection() {
+Result<Success> ServiceParser::EndSection() {
     if (service_) {
+        Service* old_service = service_list_->FindService(service_->name());
+        if (old_service) {
+            if (!service_->is_override()) {
+                return Error() << "ignored duplicate definition of service '" << service_->name()
+                               << "'";
+            }
+
+            service_list_->RemoveService(*old_service);
+            old_service = nullptr;
+        }
+
         service_list_->AddService(std::move(service_));
     }
+
+    return Success();
 }
 
 bool ServiceParser::IsValidName(const std::string& name) const {
diff --git a/init/service.h b/init/service.h
index 593f782..d46a413 100644
--- a/init/service.h
+++ b/init/service.h
@@ -111,6 +111,7 @@
     const std::set<std::string>& interfaces() const { return interfaces_; }
     int priority() const { return priority_; }
     int oom_score_adjust() const { return oom_score_adjust_; }
+    bool is_override() const { return override_; }
     bool process_cgroup_empty() const { return process_cgroup_empty_; }
     unsigned long start_order() const { return start_order_; }
     const std::vector<std::string>& args() const { return args_; }
@@ -139,6 +140,7 @@
     Result<Success> ParseOneshot(const std::vector<std::string>& args);
     Result<Success> ParseOnrestart(const std::vector<std::string>& args);
     Result<Success> ParseOomScoreAdjust(const std::vector<std::string>& args);
+    Result<Success> ParseOverride(const std::vector<std::string>& args);
     Result<Success> ParseMemcgLimitInBytes(const std::vector<std::string>& args);
     Result<Success> ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args);
     Result<Success> ParseMemcgSwappiness(const std::vector<std::string>& args);
@@ -201,6 +203,8 @@
 
     bool process_cgroup_empty_ = false;
 
+    bool override_ = false;
+
     unsigned long start_order_;
 
     std::vector<std::pair<int, rlimit>> rlimits_;
@@ -248,7 +252,7 @@
     Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
                                  int line) override;
     Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
-    void EndSection() override;
+    Result<Success> EndSection() override;
 
   private:
     bool IsValidName(const std::string& name) const;
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp
index cd7adb4..f74c878 100644
--- a/init/ueventd_parser.cpp
+++ b/init/ueventd_parser.cpp
@@ -132,8 +132,10 @@
     return std::invoke(*parser, this, std::move(args));
 }
 
-void SubsystemParser::EndSection() {
+Result<Success> SubsystemParser::EndSection() {
     subsystems_->emplace_back(std::move(subsystem_));
+
+    return Success();
 }
 
 }  // namespace init
diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h
index 18d1027..83684f3 100644
--- a/init/ueventd_parser.h
+++ b/init/ueventd_parser.h
@@ -32,7 +32,7 @@
     Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
                                  int line) override;
     Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
-    void EndSection() override;
+    Result<Success> EndSection() override;
 
   private:
     Result<Success> ParseDevName(std::vector<std::string>&& args);
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index d7413d1..9cba109 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -20,7 +20,7 @@
 libcutils_nonwindows_sources = [
     "android_get_control_file.cpp",
     "fs.cpp",
-    "multiuser.c",
+    "multiuser.cpp",
     "socket_inaddr_any_server_unix.cpp",
     "socket_local_client_unix.cpp",
     "socket_local_server_unix.cpp",
diff --git a/libcutils/multiuser.c b/libcutils/multiuser.cpp
similarity index 90%
rename from libcutils/multiuser.c
rename to libcutils/multiuser.cpp
index 61403f4..0fd3d0c 100644
--- a/libcutils/multiuser.c
+++ b/libcutils/multiuser.cpp
@@ -53,9 +53,11 @@
     }
 }
 
-gid_t multiuser_get_shared_gid(userid_t user_id, appid_t app_id) {
+gid_t multiuser_get_shared_gid(userid_t, appid_t app_id) {
     if (app_id >= AID_APP_START && app_id <= AID_APP_END) {
-        return multiuser_get_uid(user_id, (app_id - AID_APP_START) + AID_SHARED_GID_START);
+        return (app_id - AID_APP_START) + AID_SHARED_GID_START;
+    } else if (app_id >= AID_ROOT && app_id <= AID_APP_START) {
+        return app_id;
     } else {
         return -1;
     }
diff --git a/libcutils/tests/multiuser_test.cpp b/libcutils/tests/multiuser_test.cpp
index 2f9d854..4b0fd13 100644
--- a/libcutils/tests/multiuser_test.cpp
+++ b/libcutils/tests/multiuser_test.cpp
@@ -57,7 +57,10 @@
     EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(0, 1000));
     EXPECT_EQ(20000U, multiuser_get_cache_gid(0, 10000));
     EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(0, 50000));
+    EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(10, 0));
+    EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(10, 1000));
     EXPECT_EQ(1020000U, multiuser_get_cache_gid(10, 10000));
+    EXPECT_EQ(ERR_GID, multiuser_get_cache_gid(10, 50000));
 }
 
 TEST(MultiuserTest, TestExt) {
@@ -77,9 +80,12 @@
 }
 
 TEST(MultiuserTest, TestShared) {
-    EXPECT_EQ(ERR_GID, multiuser_get_shared_gid(0, 0));
-    EXPECT_EQ(ERR_GID, multiuser_get_shared_gid(0, 1000));
+    EXPECT_EQ(0U, multiuser_get_shared_gid(0, 0));
+    EXPECT_EQ(1000U, multiuser_get_shared_gid(0, 1000));
     EXPECT_EQ(50000U, multiuser_get_shared_gid(0, 10000));
     EXPECT_EQ(ERR_GID, multiuser_get_shared_gid(0, 50000));
-    EXPECT_EQ(1050000U, multiuser_get_shared_gid(10, 10000));
+    EXPECT_EQ(0U, multiuser_get_shared_gid(10, 0));
+    EXPECT_EQ(1000U, multiuser_get_shared_gid(10, 1000));
+    EXPECT_EQ(50000U, multiuser_get_shared_gid(10, 10000));
+    EXPECT_EQ(ERR_GID, multiuser_get_shared_gid(10, 50000));
 }
diff --git a/liblog/include/log/log_event_list.h b/liblog/include/log/log_event_list.h
index 4d24c68..bb1ce34 100644
--- a/liblog/include/log/log_event_list.h
+++ b/liblog/include/log/log_event_list.h
@@ -108,12 +108,6 @@
 android_log_list_element android_log_read_next(android_log_context ctx);
 android_log_list_element android_log_peek_next(android_log_context ctx);
 
-/**
- * Convert a writer context to a reader context. Useful for testing.
- * Returns an error if ctx is already a reader.
- */
-int android_log_writer_to_reader(android_log_context ctx);
-
 /* Finished with reader or writer context */
 int android_log_destroy(android_log_context* ctx);
 
@@ -128,7 +122,6 @@
  private:
   android_log_context ctx;
   int ret;
-  int tag_;
 
   android_log_event_list(const android_log_event_list&) = delete;
   void operator=(const android_log_event_list&) = delete;
@@ -136,16 +129,11 @@
  public:
   explicit android_log_event_list(int tag) : ret(0) {
     ctx = create_android_logger(static_cast<uint32_t>(tag));
-    tag_ = tag;
   }
-
   explicit android_log_event_list(log_msg& log_msg) : ret(0) {
-    const char* buf = log_msg.msg();
-    ctx = create_android_log_parser(buf + sizeof(uint32_t),
+    ctx = create_android_log_parser(log_msg.msg() + sizeof(uint32_t),
                                     log_msg.entry.len - sizeof(uint32_t));
-    tag_ = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
   }
-
   ~android_log_event_list() {
     android_log_destroy(&ctx);
   }
@@ -161,10 +149,6 @@
     return ctx;
   }
 
-  android_log_context context() const {
-    return ctx;
-  }
-
   /* return errors or transmit status */
   int status() const {
     return ret;
@@ -175,17 +159,12 @@
     if (retval < 0) ret = retval;
     return ret;
   }
-
   int end() {
     int retval = android_log_write_list_end(ctx);
     if (retval < 0) ret = retval;
     return ret;
   }
 
-  uint32_t tag() {
-    return tag_;
-  }
-
   android_log_event_list& operator<<(int32_t value) {
     int retval = android_log_write_int32(ctx, value);
     if (retval < 0) ret = retval;
@@ -317,10 +296,6 @@
     return ret >= 0;
   }
 
-  int convert_to_reader() {
-    return android_log_writer_to_reader(ctx);
-  }
-
   android_log_list_element read() {
     return android_log_read_next(ctx);
   }
diff --git a/liblog/log_event_list.c b/liblog/log_event_list.c
index f6e13db..a59cb87 100644
--- a/liblog/log_event_list.c
+++ b/liblog/log_event_list.c
@@ -565,26 +565,3 @@
 android_log_peek_next(android_log_context ctx) {
   return android_log_read_next_internal(ctx, 1);
 }
-
-LIBLOG_ABI_PUBLIC int android_log_writer_to_reader(android_log_context ctx) {
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
-
-  if (!context || context->read_write_flag != kAndroidLoggerWrite) {
-    return -EBADF;
-  }
-
-  context->len = context->pos;
-  context->storage[1] =
-      context
-          ->count[0];  // What does this do?!?! It's copied from the write func
-  context->pos = 0;
-  memset(context->count, 0, sizeof(context->count));
-  memset(context->list, 0, sizeof(context->list));
-  context->list_nest_depth = 0;
-  context->read_write_flag = kAndroidLoggerRead;
-  context->list_stop = false;
-
-  return 0;
-}
diff --git a/liblog/logger_name.c b/liblog/logger_name.c
index 979b82d..479bbfe 100644
--- a/liblog/logger_name.c
+++ b/liblog/logger_name.c
@@ -22,7 +22,7 @@
 
 /* In the future, we would like to make this list extensible */
 static const char* LOG_NAME[LOG_ID_MAX] = {
-  /* clang-format off */
+      /* clang-format off */
   [LOG_ID_MAIN] = "main",
   [LOG_ID_RADIO] = "radio",
   [LOG_ID_EVENTS] = "events",
diff --git a/logcat/event.logtags b/logcat/event.logtags
index efcc817..0983676 100644
--- a/logcat/event.logtags
+++ b/logcat/event.logtags
@@ -140,5 +140,8 @@
 
 1397638484 snet_event_log (subtag|3) (uid|1) (message|3)
 
+# for events that go to stats log buffer
+1937006964 stats_log (atom_id|1|5),(data|4)
+
 # NOTE - the range 1000000-2000000 is reserved for partners and others who
 # want to define their own log tags without conflicting with the core platform.