diff --git a/AK/Format.cpp b/AK/Format.cpp index 40f0a6b40c5..9d2e340921b 100644 --- a/AK/Format.cpp +++ b/AK/Format.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,10 @@ # include #endif +#if defined(AK_OS_ANDROID) +# include +#endif + namespace AK { class FormatParser : public GenericLexer { @@ -895,6 +900,45 @@ void vout(FILE* file, StringView fmtstr, TypeErasedFormatParams& params, bool ne } #endif +#ifdef AK_OS_ANDROID +static char const* s_log_tag_name = "Serenity"; +void set_log_tag_name(char const* tag_name) +{ + static String s_log_tag_storage; + // NOTE: Make sure to copy the null terminator + s_log_tag_storage = MUST(String::from_utf8({ tag_name, strlen(tag_name) + 1 })); + s_log_tag_name = s_log_tag_storage.bytes_as_string_view().characters_without_null_termination(); +} + +void vout(LogLevel log_level, StringView fmtstr, TypeErasedFormatParams& params, bool newline) +{ + StringBuilder builder; + MUST(vformat(builder, fmtstr, params)); + + if (newline) + builder.append('\n'); + builder.append('\0'); + + auto const string = builder.string_view(); + + auto ndk_log_level = ANDROID_LOG_UNKNOWN; + switch (log_level) { + case LogLevel ::Debug: + ndk_log_level = ANDROID_LOG_DEBUG; + break; + case LogLevel ::Info: + ndk_log_level = ANDROID_LOG_INFO; + break; + case LogLevel::Warning: + ndk_log_level = ANDROID_LOG_WARN; + break; + } + + __android_log_write(ndk_log_level, s_log_tag_name, string.characters_without_null_termination()); +} + +#endif + static bool is_debug_enabled = true; void set_debug_enabled(bool value) @@ -944,7 +988,9 @@ void vdbg(StringView fmtstr, TypeErasedFormatParams& params, bool newline) MUST(vformat(builder, fmtstr, params)); if (newline) builder.append('\n'); - +#ifdef AK_OS_ANDROID + builder.append('\0'); +#endif auto const string = builder.string_view(); #ifdef AK_OS_SERENITY @@ -955,7 +1001,11 @@ void vdbg(StringView fmtstr, TypeErasedFormatParams& params, bool newline) } # endif #endif +#ifdef AK_OS_ANDROID + __android_log_write(ANDROID_LOG_DEBUG, s_log_tag_name, string.characters_without_null_termination()); +#else dbgputstr(string.characters_without_null_termination(), string.length()); +#endif } #ifdef KERNEL diff --git a/AK/Format.h b/AK/Format.h index 6fc98e65c69..801a4530447 100644 --- a/AK/Format.h +++ b/AK/Format.h @@ -557,7 +557,7 @@ struct Formatter : Formatter { ErrorOr vformat(StringBuilder&, StringView fmtstr, TypeErasedFormatParams&); -#ifndef KERNEL +#if !defined(KERNEL) void vout(FILE*, StringView fmtstr, TypeErasedFormatParams&, bool newline = false); template @@ -576,20 +576,18 @@ void outln(FILE* file, CheckedFormatString&& fmtstr, Parameters c inline void outln(FILE* file) { fputc('\n', file); } +# ifndef AK_OS_ANDROID template -void out(CheckedFormatString&& fmtstr, Parameters const&... parameters) { out(stdout, move(fmtstr), parameters...); } +void out(CheckedFormatString&& fmtstr, Parameters const&... parameters) +{ + out(stdout, move(fmtstr), parameters...); +} template void outln(CheckedFormatString&& fmtstr, Parameters const&... parameters) { outln(stdout, move(fmtstr), parameters...); } inline void outln() { outln(stdout); } -# define outln_if(flag, fmt, ...) \ - do { \ - if constexpr (flag) \ - outln(fmt, ##__VA_ARGS__); \ - } while (0) - template void warn(CheckedFormatString&& fmtstr, Parameters const&... parameters) { @@ -600,6 +598,55 @@ template void warnln(CheckedFormatString&& fmtstr, Parameters const&... parameters) { outln(stderr, move(fmtstr), parameters...); } inline void warnln() { outln(stderr); } +# else // v Android ^ No Android +enum class LogLevel { + Debug, + Info, + Warning, +}; + +void vout(LogLevel, StringView fmtstr, TypeErasedFormatParams&, bool newline = false); + +template +void out(CheckedFormatString&& fmtstr, Parameters const&... parameters) +{ + VariadicFormatParams variadic_format_params { parameters... }; + vout(LogLevel::Info, fmtstr.view(), variadic_format_params); +} + +template +void outln(CheckedFormatString&& fmtstr, Parameters const&... parameters) +{ + VariadicFormatParams variadic_format_params { parameters... }; + vout(LogLevel::Info, fmtstr.view(), variadic_format_params, true); +} + +inline void outln() { outln(""); } + +template +void warn(CheckedFormatString&& fmtstr, Parameters const&... parameters) +{ + VariadicFormatParams variadic_format_params { parameters... }; + vout(LogLevel::Warning, fmtstr.view(), variadic_format_params); +} + +template +void warnln(CheckedFormatString&& fmtstr, Parameters const&... parameters) +{ + VariadicFormatParams variadic_format_params { parameters... }; + vout(LogLevel::Warning, fmtstr.view(), variadic_format_params, true); +} + +inline void warnln() { warnln(""); } + +void set_log_tag_name(char const*); +# endif // AK_OS_ANDROID + +# define outln_if(flag, fmt, ...) \ + do { \ + if constexpr (flag) \ + outln(fmt, ##__VA_ARGS__); \ + } while (0) # define warnln_if(flag, fmt, ...) \ do { \ diff --git a/Userland/Libraries/LibCore/CMakeLists.txt b/Userland/Libraries/LibCore/CMakeLists.txt index d21d6f51f69..18488ece838 100644 --- a/Userland/Libraries/LibCore/CMakeLists.txt +++ b/Userland/Libraries/LibCore/CMakeLists.txt @@ -65,3 +65,7 @@ if (APPLE) target_link_libraries(LibCore PUBLIC "-framework CoreServices") target_link_libraries(LibCore PUBLIC "-framework Foundation") endif() + +if (ANDROID) + target_link_libraries(LibCore PRIVATE log) +endif()