diff options
author | Ludovic Henry <luhenry@microsoft.com> | 2017-11-28 00:37:11 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-28 00:37:11 +0300 |
commit | 984f6484666c2ee6fefec949c81fdff1189c9488 (patch) | |
tree | c73bd36899c94bbdefc0835d003b1a37c592ebf0 /sdks/android | |
parent | 20de41832a4ee7a393e432700182b01c9e775fe6 (diff) |
[sdks] Use runtime logging features to intercept Console.{Out,Error} and runtime logs for instrumentation (#6083)
* [sdks] Fix Android pick of mono runtime
* [android] Have Console.{Out,Error} go through the runtime log mechanism to ease their interception
* [sdks] Intercept runtime logs instead of Console to send back for instrumentation
* [sdks] Intercept Android test runner logging
Diffstat (limited to 'sdks/android')
-rw-r--r-- | sdks/android/jni/runtime-bootstrap.c | 112 | ||||
-rw-r--r-- | sdks/android/managed/main.cs | 44 |
2 files changed, 88 insertions, 68 deletions
diff --git a/sdks/android/jni/runtime-bootstrap.c b/sdks/android/jni/runtime-bootstrap.c index 2f060df132b..535f4b1bbc9 100644 --- a/sdks/android/jni/runtime-bootstrap.c +++ b/sdks/android/jni/runtime-bootstrap.c @@ -62,6 +62,9 @@ typedef struct MonoImage_ MonoImage; typedef struct MonoObject_ MonoObject; typedef struct MonoThread_ MonoThread; +/* Imported from `mono-logger.h` */ +typedef void (*MonoLogCallback) (const char *log_domain, const char *log_level, const char *message, int32_t fatal, void *user_data); + /* * The "err" variable contents must be allocated using g_malloc or g_strdup */ @@ -93,6 +96,8 @@ typedef void (*mono_domain_set_config_fn) (MonoDomain *, const char *, const cha typedef int (*mono_runtime_set_main_args_fn) (int argc, char* argv[]); typedef MonoMethod* (*mono_class_get_methods_fn) (MonoClass* klass, void **iter); typedef const char* (*mono_method_get_name_fn) (MonoMethod *method); +typedef void (*mono_trace_init_fn) (void); +typedef void (*mono_trace_set_log_handler_fn) (MonoLogCallback callback, void *user_data); static JavaVM *jvm; @@ -119,6 +124,8 @@ static mono_domain_set_config_fn mono_domain_set_config; static mono_runtime_set_main_args_fn mono_runtime_set_main_args; static mono_class_get_methods_fn mono_class_get_methods; static mono_method_get_name_fn mono_method_get_name; +static mono_trace_init_fn mono_trace_init; +static mono_trace_set_log_handler_fn mono_trace_set_log_handler; static MonoAssembly *main_assembly; static void *runtime_bootstrap_dso; @@ -131,13 +138,82 @@ static void* my_dlopen (const char *name, int flags, char **err, void *user_data //stuff + +static void +_runtime_log (const char *log_domain, const char *log_level, const char *message, int32_t fatal, void *user_data) +{ + static jclass AndroidRunner_klass = NULL; + static jmethodID AndroidRunner_WriteLineToInstrumentation_method = NULL; + JNIEnv *env; + jstring j_message; + + if (jvm == NULL) + __android_log_assert ("", "mono-sdks", "%s: jvm is NULL", __func__); + + (*jvm)->GetEnv (jvm, (void**)&env, JNI_VERSION_1_6); + + if (AndroidRunner_klass == NULL || AndroidRunner_WriteLineToInstrumentation_method == NULL) { + AndroidRunner_klass = (*env)->FindClass (env, "org/mono/android/AndroidRunner"); + AndroidRunner_WriteLineToInstrumentation_method = (*env)->GetStaticMethodID (env, AndroidRunner_klass, "WriteLineToInstrumentation", "(Ljava/lang/String;)V"); + } + + j_message = (*env)->NewStringUTF(env, message); + + (*env)->CallStaticVoidMethod (env, AndroidRunner_klass, AndroidRunner_WriteLineToInstrumentation_method, j_message); + + (*env)->DeleteLocalRef (env, j_message); + + /* Still print it on the logcat */ + + android_LogPriority android_log_level; + switch (*log_level) { + case 'e': /* error */ + android_log_level = ANDROID_LOG_FATAL; + break; + case 'c': /* critical */ + android_log_level = ANDROID_LOG_ERROR; + break; + case 'w': /* warning */ + android_log_level = ANDROID_LOG_WARN; + break; + case 'm': /* message */ + android_log_level = ANDROID_LOG_INFO; + break; + case 'i': /* info */ + android_log_level = ANDROID_LOG_DEBUG; + break; + case 'd': /* debug */ + android_log_level = ANDROID_LOG_VERBOSE; + break; + default: + android_log_level = ANDROID_LOG_UNKNOWN; + break; + } + + __android_log_write (android_log_level, log_domain, message); + if (android_log_level == ANDROID_LOG_FATAL) + abort (); +} + static void _log (const char *format, ...) { va_list args; + char *buf; + int nbuf; + + errno = 0; + va_start (args, format); - __android_log_vprint (ANDROID_LOG_INFO, "MONO", format, args); + nbuf = vasprintf (&buf, format, args); va_end (args); + + if (buf == NULL || nbuf == -1) + __android_log_assert ("", "mono-sdks", "%s: vasprintf failed, error: \"%s\" (%d), nbuf = %d, buf = \"%s\"", __func__, strerror(errno), errno, nbuf, buf ? buf : "(null)"); + + _runtime_log ("mono-sdks", "debug", buf, 0, NULL); + + free (buf); } static void @@ -243,10 +319,10 @@ Java_org_mono_android_AndroidRunner_runTests (JNIEnv* env, jobject thiz, jstring strncpy_str (env, data_dir, j_data_dir, sizeof(data_dir)); strncpy_str (env, assemblies_dir, j_assembly_dir, sizeof(assemblies_dir)); - _log ("-- file dir %s\n", file_dir); - _log ("-- cache dir %s\n", cache_dir); - _log ("-- data dir %s\n", data_dir); - _log ("-- assembly dir %s\n", assemblies_dir); + _log ("-- file dir %s", file_dir); + _log ("-- cache dir %s", cache_dir); + _log ("-- data dir %s", data_dir); + _log ("-- assembly dir %s", assemblies_dir); prctl (PR_SET_DUMPABLE, 1); snprintf (buff, sizeof(buff), "%s/libmonosgen-2.0.so", data_dir); @@ -279,6 +355,8 @@ Java_org_mono_android_AndroidRunner_runTests (JNIEnv* env, jobject thiz, jstring mono_runtime_set_main_args = dlsym (libmono, "mono_runtime_set_main_args"); mono_class_get_methods = dlsym (libmono, "mono_class_get_methods"); mono_method_get_name = dlsym (libmono, "mono_method_get_name"); + mono_trace_init = dlsym (libmono, "mono_trace_init"); + mono_trace_set_log_handler = dlsym (libmono, "mono_trace_set_log_handler"); //MUST HAVE envs setenv ("TMPDIR", cache_dir, 1); @@ -290,9 +368,13 @@ Java_org_mono_android_AndroidRunner_runTests (JNIEnv* env, jobject thiz, jstring create_and_set (file_dir, "home/.config", "XDG_CONFIG_HOME"); //Debug flags - // setenv ("MONO_LOG_LEVEL", "debug", 1); + setenv ("MONO_LOG_LEVEL", "info", 1); + setenv ("MONO_LOG_MASK", "all", 1); // setenv ("MONO_VERBOSE_METHOD", "GetCallingAssembly", 1); + mono_trace_init (); + mono_trace_set_log_handler (_runtime_log, NULL); + mono_set_assemblies_path (assemblies_dir); mono_set_crash_chaining (1); mono_set_signal_chaining (1); @@ -558,24 +640,6 @@ _monodroid_get_dns_servers (void **dns_servers_array) return count; } -MONO_API void -AndroidIntrumentationWriter_WriteLineToInstrumentation (char *chars) -{ - JNIEnv *env; - jclass AndroidRunner_klass; - jmethodID AndroidRunner_WriteLineToInstrumentation_method; - jstring j_chars; - - (*jvm)->GetEnv (jvm, (void**)&env, JNI_VERSION_1_6); - - AndroidRunner_klass = (*env)->FindClass (env, "org/mono/android/AndroidRunner"); - AndroidRunner_WriteLineToInstrumentation_method = (*env)->GetStaticMethodID (env, AndroidRunner_klass, "WriteLineToInstrumentation", "(Ljava/lang/String;)V"); - - j_chars = (*env)->NewStringUTF(env, chars); - - (*env)->CallStaticVoidMethod (env, AndroidRunner_klass, AndroidRunner_WriteLineToInstrumentation_method, j_chars); -} - JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM *vm, void *reserved) { diff --git a/sdks/android/managed/main.cs b/sdks/android/managed/main.cs index 1ac277d3699..84b6081cb56 100644 --- a/sdks/android/managed/main.cs +++ b/sdks/android/managed/main.cs @@ -14,9 +14,6 @@ public class Driver public static void RunTests () { - Console.SetOut (TextWriter.Synchronized (new AndroidIntrumentationWriter (Console.Out))); - Console.SetError (TextWriter.Synchronized (new AndroidIntrumentationWriter (Console.Error))); - string assembly = File.ReadAllText ($"{AppDomain.CurrentDomain.BaseDirectory}/testassembly.txt"); Console.WriteLine ($"Testing assembly \"{assembly}\""); @@ -40,45 +37,4 @@ public class Driver { Environment.Exit (1); } - - class AndroidIntrumentationWriter : TextWriter - { - readonly StringBuilder Line = new StringBuilder (); - - readonly TextWriter Inner; - - public override Encoding Encoding => Inner.Encoding; - - public AndroidIntrumentationWriter (TextWriter inner) - { - Inner = inner; - } - - public override void Write(char value) - { - if (value == '\n') - WriteLine (); - else - Line.Append (value); - } - - public override void WriteLine () - { - var l = Line.ToString (); - Line.Clear (); - - unsafe - { - fixed (byte *chars = Encoding.UTF8.GetBytes (l + '\0')) - { - WriteLineToInstrumentation (chars); - } - } - - Inner.WriteLine (l); - } - - [DllImport ("__Internal", EntryPoint = "AndroidIntrumentationWriter_WriteLineToInstrumentation", CharSet = CharSet.Unicode)] - static unsafe extern void WriteLineToInstrumentation (byte *chars); - } } |