Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 10:29:01

0001 // Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
0002 // Distributed under the MIT License (http://opensource.org/licenses/MIT)
0003 
0004 #pragma once
0005 
0006 #ifdef __ANDROID__
0007 
0008     #include <spdlog/details/fmt_helper.h>
0009     #include <spdlog/details/null_mutex.h>
0010     #include <spdlog/details/os.h>
0011     #include <spdlog/details/synchronous_factory.h>
0012     #include <spdlog/sinks/base_sink.h>
0013 
0014     #include <android/log.h>
0015     #include <chrono>
0016     #include <mutex>
0017     #include <string>
0018     #include <thread>
0019     #include <type_traits>
0020 
0021     #if !defined(SPDLOG_ANDROID_RETRIES)
0022         #define SPDLOG_ANDROID_RETRIES 2
0023     #endif
0024 
0025 namespace spdlog {
0026 namespace sinks {
0027 
0028 /*
0029  * Android sink
0030  * (logging using __android_log_write or __android_log_buf_write depending on the specified
0031  * BufferID)
0032  */
0033 template <typename Mutex, int BufferID = log_id::LOG_ID_MAIN>
0034 class android_sink final : public base_sink<Mutex> {
0035 public:
0036     explicit android_sink(std::string tag = "spdlog", bool use_raw_msg = false)
0037         : tag_(std::move(tag)),
0038           use_raw_msg_(use_raw_msg) {}
0039 
0040 protected:
0041     void sink_it_(const details::log_msg &msg) override {
0042         const android_LogPriority priority = convert_to_android_(msg.level);
0043         memory_buf_t formatted;
0044         if (use_raw_msg_) {
0045             details::fmt_helper::append_string_view(msg.payload, formatted);
0046         } else {
0047             base_sink<Mutex>::formatter_->format(msg, formatted);
0048         }
0049         formatted.push_back('\0');
0050         const char *msg_output = formatted.data();
0051 
0052         // See system/core/liblog/logger_write.c for explanation of return value
0053         int ret = android_log(priority, tag_.c_str(), msg_output);
0054         if (ret == -EPERM) {
0055             return;  // !__android_log_is_loggable
0056         }
0057         int retry_count = 0;
0058         while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES)) {
0059             details::os::sleep_for_millis(5);
0060             ret = android_log(priority, tag_.c_str(), msg_output);
0061             retry_count++;
0062         }
0063 
0064         if (ret < 0) {
0065             throw_spdlog_ex("logging to Android failed", ret);
0066         }
0067     }
0068 
0069     void flush_() override {}
0070 
0071 private:
0072     // There might be liblog versions used, that do not support __android_log_buf_write. So we only
0073     // compile and link against
0074     // __android_log_buf_write, if user explicitly provides a non-default log buffer. Otherwise,
0075     // when using the default log buffer, always log via __android_log_write.
0076     template <int ID = BufferID>
0077     typename std::enable_if<ID == static_cast<int>(log_id::LOG_ID_MAIN), int>::type android_log(
0078         int prio, const char *tag, const char *text) {
0079         return __android_log_write(prio, tag, text);
0080     }
0081 
0082     template <int ID = BufferID>
0083     typename std::enable_if<ID != static_cast<int>(log_id::LOG_ID_MAIN), int>::type android_log(
0084         int prio, const char *tag, const char *text) {
0085         return __android_log_buf_write(ID, prio, tag, text);
0086     }
0087 
0088     static android_LogPriority convert_to_android_(spdlog::level::level_enum level) {
0089         switch (level) {
0090             case spdlog::level::trace:
0091                 return ANDROID_LOG_VERBOSE;
0092             case spdlog::level::debug:
0093                 return ANDROID_LOG_DEBUG;
0094             case spdlog::level::info:
0095                 return ANDROID_LOG_INFO;
0096             case spdlog::level::warn:
0097                 return ANDROID_LOG_WARN;
0098             case spdlog::level::err:
0099                 return ANDROID_LOG_ERROR;
0100             case spdlog::level::critical:
0101                 return ANDROID_LOG_FATAL;
0102             default:
0103                 return ANDROID_LOG_DEFAULT;
0104         }
0105     }
0106 
0107     std::string tag_;
0108     bool use_raw_msg_;
0109 };
0110 
0111 using android_sink_mt = android_sink<std::mutex>;
0112 using android_sink_st = android_sink<details::null_mutex>;
0113 
0114 template <int BufferId = log_id::LOG_ID_MAIN>
0115 using android_sink_buf_mt = android_sink<std::mutex, BufferId>;
0116 template <int BufferId = log_id::LOG_ID_MAIN>
0117 using android_sink_buf_st = android_sink<details::null_mutex, BufferId>;
0118 
0119 }  // namespace sinks
0120 
0121 // Create and register android syslog logger
0122 
0123 template <typename Factory = spdlog::synchronous_factory>
0124 inline std::shared_ptr<logger> android_logger_mt(const std::string &logger_name,
0125                                                  const std::string &tag = "spdlog") {
0126     return Factory::template create<sinks::android_sink_mt>(logger_name, tag);
0127 }
0128 
0129 template <typename Factory = spdlog::synchronous_factory>
0130 inline std::shared_ptr<logger> android_logger_st(const std::string &logger_name,
0131                                                  const std::string &tag = "spdlog") {
0132     return Factory::template create<sinks::android_sink_st>(logger_name, tag);
0133 }
0134 
0135 }  // namespace spdlog
0136 
0137 #endif  // __ANDROID__