AK: Send dbgln/outln/warnln to the NDK logger on Android

The embedding application is responsible for setting the android log
tag. If it doesn't a default of "Serenity" will be used for any Lagom
code.
This commit is contained in:
Andrew Kaster 2023-09-13 23:19:25 -06:00 committed by Andrew Kaster
parent e267f8e68f
commit 0c5a546dca
Notes: sideshowbarker 2024-07-17 10:05:47 +09:00
3 changed files with 110 additions and 9 deletions

View file

@ -8,6 +8,7 @@
#include <AK/Format.h>
#include <AK/GenericLexer.h>
#include <AK/IntegralMath.h>
#include <AK/String.h>
#include <AK/StringBuilder.h>
#include <AK/kstdio.h>
@ -25,6 +26,10 @@
# include <string.h>
#endif
#if defined(AK_OS_ANDROID)
# include <android/log.h>
#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

View file

@ -557,7 +557,7 @@ struct Formatter<nullptr_t> : Formatter<FlatPtr> {
ErrorOr<void> vformat(StringBuilder&, StringView fmtstr, TypeErasedFormatParams&);
#ifndef KERNEL
#if !defined(KERNEL)
void vout(FILE*, StringView fmtstr, TypeErasedFormatParams&, bool newline = false);
template<typename... Parameters>
@ -576,20 +576,18 @@ void outln(FILE* file, CheckedFormatString<Parameters...>&& fmtstr, Parameters c
inline void outln(FILE* file) { fputc('\n', file); }
# ifndef AK_OS_ANDROID
template<typename... Parameters>
void out(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters) { out(stdout, move(fmtstr), parameters...); }
void out(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
{
out(stdout, move(fmtstr), parameters...);
}
template<typename... Parameters>
void outln(CheckedFormatString<Parameters...>&& 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<typename... Parameters>
void warn(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
{
@ -600,6 +598,55 @@ template<typename... Parameters>
void warnln(CheckedFormatString<Parameters...>&& 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<typename... Parameters>
void out(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
{
VariadicFormatParams<AllowDebugOnlyFormatters::Yes, Parameters...> variadic_format_params { parameters... };
vout(LogLevel::Info, fmtstr.view(), variadic_format_params);
}
template<typename... Parameters>
void outln(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
{
VariadicFormatParams<AllowDebugOnlyFormatters::Yes, Parameters...> variadic_format_params { parameters... };
vout(LogLevel::Info, fmtstr.view(), variadic_format_params, true);
}
inline void outln() { outln(""); }
template<typename... Parameters>
void warn(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
{
VariadicFormatParams<AllowDebugOnlyFormatters::Yes, Parameters...> variadic_format_params { parameters... };
vout(LogLevel::Warning, fmtstr.view(), variadic_format_params);
}
template<typename... Parameters>
void warnln(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
{
VariadicFormatParams<AllowDebugOnlyFormatters::Yes, Parameters...> 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 { \

View file

@ -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()