This commit is contained in:
Rodrigo Kumpera 2017-03-29 11:33:08 -04:00
Родитель 2ae7f04e5f
Коммит 531603b66b
9 изменённых файлов: 953 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mono.android.AndroidTestRunner"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="14" />
<uses-permission
android:name="android.permission.INTERNET"/>
<application android:label="@string/app_name" android:debuggable="true">
<activity android:name="org.mono.android.AndroidRunner" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

56
android/Makefile Normal file
Просмотреть файл

@ -0,0 +1,56 @@
TOP=$(CURDIR)/..
include $(TOP)/paths.mk
ADB = $(SDK_DIR)/platform-tools/adb
ANDROID = $(SDK_DIR)/tools/android
ANT = ant
NDK_BUILD = $(NDK_DIR)/ndk-build
PACKAGE = org.mono.android.AndroidTestRunner
ACTIVITY = org.mono.android.AndroidRunner
PROJECT_SETUP_FILES = project.properties local.properties
all: setup stage-sdk
make -C managed all
$(NDK_BUILD)
$(ANT) debug
$(ANT) release
stage-sdk:
mkdir -p jni/armeabi-v7a
mkdir -p jni/arm64-v8a
cp $(TOP)/out/armv7-android/* jni/armeabi-v7a/
cp $(TOP)/out/aarch64-android/* jni/arm64-v8a/
mkdir -p assets/mconfig
cp machine.config assets/mconfig
app: setup stage-sdk
make -C managed all
$(NDK_BUILD)
$(ANT) debug
clean:
$(ANT) clean
deploy:
$(ADB) install bin/AndroidRunner-debug.apk
undeploy:
$(ADB) uninstall $(PACKAGE)
run:
$(ADB) shell am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER $(PACKAGE)/$(ACTIVITY)
kill:
$(ADB) shell am force-stop $(PACKAGE)
$(PROJECT_SETUP_FILES): build.xml AndroidManifest.xml
$(ANDROID) update project -p . -t "android-14"
setup: $(PROJECT_SETUP_FILES)
logcat:
$(ADB) logcat
shell:
$(ADB) shell

92
android/build.xml Normal file
Просмотреть файл

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="AndroidRunner" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>

36
android/jni/Android.mk Normal file
Просмотреть файл

@ -0,0 +1,36 @@
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE := runtime-bootstrap
LOCAL_SRC_FILES := runtime-bootstrap.c
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := lib-monosgen
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libmonosgen-2.0.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := lib-suppport
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libMonoPosixHelper.so
include $(PREBUILT_SHARED_LIBRARY)

Просмотреть файл

@ -0,0 +1,2 @@
# Build both ARMv5TE and ARMv7-A machine code.
APP_ABI := armeabi-v7a arm64-v8a

Просмотреть файл

@ -0,0 +1,588 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <pthread.h>
#include <dlfcn.h>
#include <unistd.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <jni.h>
#include <linux/prctl.h>
#include <android/log.h>
#include <sys/system_properties.h>
#define DEFAULT_DIRECTORY_MODE S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
typedef enum {
MONO_IMAGE_OK,
MONO_IMAGE_ERROR_ERRNO,
MONO_IMAGE_MISSING_ASSEMBLYREF,
MONO_IMAGE_IMAGE_INVALID
} MonoImageOpenStatus;
enum {
MONO_DL_EAGER = 0,
MONO_DL_LAZY = 1,
MONO_DL_LOCAL = 2,
MONO_DL_MASK = 3
};
typedef struct MonoDomain_ MonoDomain;
typedef struct MonoAssembly_ MonoAssembly;
typedef struct MonoMethod_ MonoMethod;
typedef struct MonoException_ MonoException;
typedef struct MonoString_ MonoString;
typedef struct MonoClass_ MonoClass;
typedef struct MonoImage_ MonoImage;
typedef struct MonoObject_ MonoObject;
typedef struct MonoThread_ MonoThread;
/*
* The "err" variable contents must be allocated using g_malloc or g_strdup
*/
typedef void* (*MonoDlFallbackLoad) (const char *name, int flags, char **err, void *user_data);
typedef void* (*MonoDlFallbackSymbol) (void *handle, const char *name, char **err, void *user_data);
typedef void* (*MonoDlFallbackClose) (void *handle, void *user_data);
typedef void *(*mono_dl_fallback_register_fn) (MonoDlFallbackLoad load_func, MonoDlFallbackSymbol symbol_func, MonoDlFallbackClose close_func, void *user_data);
typedef MonoDomain* (*mono_jit_init_version_fn) (const char *root_domain_name, const char *runtime_version);
typedef int (*mono_jit_exec_fn) (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
typedef MonoDomain* (*mono_domain_get_fn) (void);
typedef MonoAssembly* (*mono_assembly_open_fn) (const char *filename, MonoImageOpenStatus *status);
typedef void (*mono_set_assemblies_path_fn) (const char* path);
typedef MonoString* (*mono_string_new_fn) (MonoDomain *domain, const char *text);
typedef MonoClass* (*mono_class_from_name_case_fn) (MonoImage *image, const char* name_space, const char *name);
typedef MonoImage* (*mono_assembly_get_image_fn) (MonoAssembly *assembly);
typedef MonoClass* (*mono_class_from_name_fn) (MonoImage *image, const char* name_space, const char *name);
typedef MonoMethod* (*mono_class_get_method_from_name_fn) (MonoClass *klass, const char *name, int param_count);
typedef MonoString* (*mono_object_to_string_fn) (MonoObject *obj, MonoObject **exc);
typedef char* (*mono_string_to_utf8_fn) (MonoString *string_obj);
typedef MonoObject* (*mono_runtime_invoke_fn) (MonoMethod *method, void *obj, void **params, MonoObject **exc);
typedef void (*mono_free_fn) (void*);
typedef void (*mono_set_crash_chaining_fn) (int);
typedef void (*mono_set_signal_chaining_fn) (int);
typedef MonoThread *(*mono_thread_attach_fn) (MonoDomain *domain);
typedef void (*mono_domain_set_config_fn) (MonoDomain *, const char *, const char *);
typedef int (*mono_runtime_set_main_args_fn) (int argc, char* argv[]);
static mono_jit_init_version_fn mono_jit_init_version;
static mono_assembly_open_fn mono_assembly_open;
static mono_domain_get_fn mono_domain_get;
static mono_jit_exec_fn mono_jit_exec;
static mono_set_assemblies_path_fn mono_set_assemblies_path;
static mono_string_new_fn mono_string_new;
static mono_class_from_name_case_fn mono_class_from_name_case;
static mono_assembly_get_image_fn mono_assembly_get_image;
static mono_class_from_name_fn mono_class_from_name;
static mono_class_get_method_from_name_fn mono_class_get_method_from_name;
static mono_object_to_string_fn mono_object_to_string;
static mono_string_to_utf8_fn mono_string_to_utf8;
static mono_runtime_invoke_fn mono_runtime_invoke;
static mono_free_fn mono_free;
static mono_set_crash_chaining_fn mono_set_crash_chaining;
static mono_set_signal_chaining_fn mono_set_signal_chaining;
static mono_dl_fallback_register_fn mono_dl_fallback_register;
static mono_thread_attach_fn mono_thread_attach;
static mono_domain_set_config_fn mono_domain_set_config;
static mono_runtime_set_main_args_fn mono_runtime_set_main_args;
static char file_dir[2048];
static char cache_dir[2048];
static char data_dir[2048];
static char assemblies_dir[2048];
static MonoAssembly *main_assembly;
static void *runtime_bootstrap_dso;
static void *mono_posix_helper_dso;
//forward decls
static void* my_dlsym (void *handle, const char *name, char **err, void *user_data);
static void* my_dlopen (const char *name, int flags, char **err, void *user_data);
//stuff
static void
_log (const char *format, ...)
{
char buf[100];
va_list args;
sprintf (buf, "MONO");
va_start (args, format);
__android_log_vprint (ANDROID_LOG_INFO, buf, format, args);
va_end (args);
}
static void
cpy_str (JNIEnv *env, char *buff, jstring str)
{
jboolean isCopy = 0;
const char *copy_buff = (*env)->GetStringUTFChars (env, str, &isCopy);
strcpy (buff, copy_buff);
if (isCopy)
(*env)->ReleaseStringUTFChars (env, str, copy_buff);
}
static char *
m_strdup_printf (const char *format, ...)
{
char *ret;
va_list args;
int n;
va_start (args, format);
n = vasprintf (&ret, format, args);
va_end (args);
if (n == -1)
return NULL;
return ret;
}
static int
m_make_directory (const char *path, int mode)
{
#if WINDOWS
return mkdir (path);
#else
return mkdir (path, mode);
#endif
}
static int
m_create_directory (const char *pathname, int mode)
{
if (mode <= 0)
mode = DEFAULT_DIRECTORY_MODE;
if (!pathname || *pathname == '\0') {
errno = EINVAL;
return -1;
}
mode_t oldumask = umask (022);
char *path = strdup (pathname);
int rv, ret = 0;
char *d;
for (d = path; *d; ++d) {
if (*d != '/')
continue;
*d = 0;
if (*path) {
rv = m_make_directory (path, mode);
if (rv == -1 && errno != EEXIST) {
ret = -1;
break;
}
}
*d = '/';
}
free (path);
if (ret == 0)
ret = m_make_directory (pathname, mode);
umask (oldumask);
return ret;
}
static void
create_and_set (const char *home, const char *relativePath, const char *envvar)
{
char *dir = m_strdup_printf ("%s/%s", home, relativePath);
int rv = m_create_directory (dir, DEFAULT_DIRECTORY_MODE);
if (rv < 0 && errno != EEXIST)
_log ("Failed to create XDG directory %s. %s", dir, strerror (errno));
if (envvar)
setenv (envvar, dir, 1);
free (dir);
}
static MonoDomain *root_domain;
//jni funcs
void
Java_org_mono_android_AndroidRunner_init (JNIEnv* env, jobject _this, jstring path0, jstring path1, jstring path2, jstring path3)
{
char buff[1024];
_log ("IN Java_com_example_hellojni_HelloJni_init \n");
cpy_str (env, file_dir, path0);
cpy_str (env, cache_dir, path1);
cpy_str (env, data_dir, path2);
cpy_str (env, assemblies_dir, path3);
_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);
prctl (PR_SET_DUMPABLE, 1);
sprintf (buff, "%s/libmonosgen-2.0.so", data_dir);
void *libmono = dlopen (buff, RTLD_LAZY);
mono_jit_init_version = dlsym (libmono, "mono_jit_init_version");
mono_assembly_open = dlsym (libmono, "mono_assembly_open");
mono_domain_get = dlsym (libmono, "mono_domain_get");
mono_jit_exec = dlsym (libmono, "mono_jit_exec");
mono_set_assemblies_path = dlsym (libmono, "mono_set_assemblies_path");
mono_string_new = dlsym (libmono, "mono_string_new");
mono_class_from_name_case = dlsym (libmono, "mono_class_from_name_case");
mono_assembly_get_image = dlsym (libmono, "mono_assembly_get_image");
mono_class_from_name = dlsym (libmono, "mono_class_from_name");
mono_class_get_method_from_name = dlsym (libmono, "mono_class_get_method_from_name");
mono_object_to_string = dlsym (libmono, "mono_object_to_string");
mono_string_to_utf8 = dlsym (libmono, "mono_string_to_utf8");
mono_runtime_invoke = dlsym (libmono, "mono_runtime_invoke");
mono_free = dlsym (libmono, "mono_free");
mono_set_crash_chaining = dlsym (libmono, "mono_set_crash_chaining");
mono_set_signal_chaining = dlsym (libmono, "mono_set_signal_chaining");
mono_dl_fallback_register = dlsym (libmono, "mono_dl_fallback_register");
mono_thread_attach = dlsym (libmono, "mono_thread_attach");
mono_domain_set_config = dlsym (libmono, "mono_domain_set_config");
mono_runtime_set_main_args = dlsym (libmono, "mono_runtime_set_main_args");
//MUST HAVE envs
setenv ("TMPDIR", cache_dir, 1);
setenv ("MONO_CFG_DIR", file_dir, 1);
create_and_set (file_dir, "home", "HOME");
create_and_set (file_dir, "home/.local/share", "XDG_DATA_HOME");
create_and_set (file_dir, "home/.local/share", "XDG_DATA_HOME");
create_and_set (file_dir, "home/.config", "XDG_CONFIG_HOME");
//Debug flags
// setenv ("MONO_LOG_LEVEL", "debug", 1);
// setenv ("MONO_VERBOSE_METHOD", "GetCallingAssembly", 1);
mono_set_assemblies_path (assemblies_dir);
mono_set_crash_chaining (1);
mono_set_signal_chaining (1);
mono_dl_fallback_register (my_dlopen, my_dlsym, NULL, NULL);
root_domain = mono_jit_init_version ("TEST RUNNER", "mobile");
mono_domain_set_config (root_domain, assemblies_dir, file_dir);
sprintf (buff, "%s/libruntime-bootstrap.so", data_dir);
runtime_bootstrap_dso = dlopen (buff, RTLD_LAZY);
sprintf (buff, "%s/libMonoPosixHelper.so", data_dir);
mono_posix_helper_dso = dlopen (buff, RTLD_LAZY);
}
int
Java_org_mono_android_AndroidRunner_execMain (JNIEnv* env, jobject _this)
{
int argc = 1;
char *argv[] = { "main.exe" };
char *main_assembly_name = "main.exe";
char buff[1024];
mono_thread_attach (root_domain);
sprintf (buff, "%s/%s", assemblies_dir, main_assembly_name);
main_assembly = mono_assembly_open (buff, NULL);
mono_runtime_set_main_args (argc, argv);
return 0;
}
static MonoMethod *send_method;
jstring
Java_org_mono_android_AndroidRunner_send (JNIEnv* env, jobject thiz, jstring key, jstring val)
{
jboolean key_copy, val_copy;
const char *key_buff = (*env)->GetStringUTFChars (env, key, &key_copy);
const char *val_buff = (*env)->GetStringUTFChars (env, val, &val_copy);
mono_thread_attach (root_domain);
void * params[] = {
mono_string_new (mono_domain_get (), key_buff),
mono_string_new (mono_domain_get (), val_buff),
};
if (!send_method) {
MonoClass *driver_class = mono_class_from_name (mono_assembly_get_image (main_assembly), "", "Driver");
send_method = mono_class_get_method_from_name (driver_class, "Send", -1);
}
MonoException *exc = NULL;
MonoString *res = (MonoString *)mono_runtime_invoke (send_method, NULL, params, (MonoObject**)&exc);
jstring java_result;
if (exc) {
MonoException *second_exc = NULL;
res = mono_object_to_string ((MonoObject*)exc, (MonoObject**)&second_exc);
if (second_exc)
res = mono_string_new (mono_domain_get (), "DOUBLE FAULTED EXCEPTION");
}
if (res) {
char *str = mono_string_to_utf8 (res);
// _log ("SEND RETURNED: %s\n", str);
java_result = (*env)->NewStringUTF (env, str);
mono_free (str);
} else {
java_result = (*env)->NewStringUTF (env, "<NULL>");
}
if (key_copy)
(*env)->ReleaseStringUTFChars (env, key, key_buff);
if (val_copy)
(*env)->ReleaseStringUTFChars (env, val, val_buff);
return java_result;
}
static int
convert_dl_flags (int flags)
{
int lflags = flags & MONO_DL_LOCAL? 0: RTLD_GLOBAL;
if (flags & MONO_DL_LAZY)
lflags |= RTLD_LAZY;
else
lflags |= RTLD_NOW;
return lflags;
}
/*
This is the Android specific glue ZZZZOMG
# Issues with the monodroid BCL profile
This pinvoke should not be on __Internal by libmonodroid.so: System.TimeZoneInfo+AndroidTimeZones:monodroid_get_system_property
This depends on monodroid native code: System.TimeZoneInfo+AndroidTimeZones.GetDefaultTimeZoneName
*/
#define MONO_API __attribute__ ((__visibility__ ("default")))
#define INTERNAL_LIB_HANDLE ((void*)(size_t)-1)
static void*
my_dlopen (const char *name, int flags, char **err, void *user_data)
{
if (!name)
return INTERNAL_LIB_HANDLE;
void *res = dlopen (name, convert_dl_flags (flags));
//TODO handle loading AOT modules from assemblies_dir
return res;
}
static void*
my_dlsym (void *handle, const char *name, char **err, void *user_data)
{
void *s;
if (handle == INTERNAL_LIB_HANDLE) {
s = dlsym (runtime_bootstrap_dso, name);
if (!s && mono_posix_helper_dso)
s = dlsym (mono_posix_helper_dso, name);
} else {
s = dlsym (handle, name);
}
if (!s && err) {
*err = m_strdup_printf ("Could not find symbol '%s'.", name);
}
return s;
}
MONO_API int
monodroid_get_system_property (const char *name, char **value)
{
char *pvalue;
char sp_value [PROP_VALUE_MAX+1] = { 0, };
int len;
if (value)
*value = NULL;
pvalue = sp_value;
len = __system_property_get (name, sp_value);
if (len >= 0 && value) {
*value = malloc (len + 1);
if (!*value)
return -len;
memcpy (*value, pvalue, len);
(*value)[len] = '\0';
}
return len;
}
MONO_API void
monodroid_free (void *ptr)
{
free (ptr);
}
typedef struct {
struct _monodroid_ifaddrs *ifa_next; /* Pointer to the next structure. */
char *ifa_name; /* Name of this network interface. */
unsigned int ifa_flags; /* Flags as from SIOCGIFFLAGS ioctl. */
struct sockaddr *ifa_addr; /* Network address of this interface. */
struct sockaddr *ifa_netmask; /* Netmask of this interface. */
union {
/* At most one of the following two is valid. If the IFF_BROADCAST
bit is set in `ifa_flags', then `ifa_broadaddr' is valid. If the
IFF_POINTOPOINT bit is set, then `ifa_dstaddr' is valid.
It is never the case that both these bits are set at once. */
struct sockaddr *ifu_broadaddr; /* Broadcast address of this interface. */
struct sockaddr *ifu_dstaddr; /* Point-to-point destination address. */
} ifa_ifu;
void *ifa_data; /* Address-specific data (may be unused). */
} m_ifaddrs;
typedef int (*get_ifaddr_fn)(m_ifaddrs **ifap);
typedef void (*freeifaddr_fn)(m_ifaddrs *ifap);
static void
init_sock_addr (struct sockaddr **res, const char *str_addr)
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
inet_pton (AF_INET, str_addr, &addr.sin_addr);
*res = calloc (1, sizeof (struct sockaddr));
**(struct sockaddr_in**)res = addr;
}
MONO_API int
monodroid_getifaddrs (m_ifaddrs **ifap)
{
char buff[1024];
FILE * f = fopen ("/proc/net/route", "r");
if (f) {
int i = 0;
fgets (buff, 1023, f);
fgets (buff, 1023, f);
while (!isspace (buff [i]) && i < 1024)
++i;
buff [i] = 0;
fclose (f);
} else {
strcpy (buff, "wlan0");
}
m_ifaddrs *res = calloc (1, sizeof (m_ifaddrs));
memset (res, 0, sizeof (res));
res->ifa_next = NULL;
res->ifa_name = m_strdup_printf ("%s", buff);
res->ifa_flags = 0;
res->ifa_ifu.ifu_dstaddr = NULL;
init_sock_addr (&res->ifa_addr, "192.168.0.1");
init_sock_addr (&res->ifa_netmask, "255.255.255.0");
*ifap = res;
return 0;
}
MONO_API void
monodroid_freeifaddrs (m_ifaddrs *ifap)
{
free (ifap->ifa_name);
if (ifap->ifa_addr)
free (ifap->ifa_addr);
if (ifap->ifa_netmask)
free (ifap->ifa_netmask);
free (ifap);
}
MONO_API int
_monodroid_get_android_api_level (void)
{
return 24;
}
MONO_API int
_monodroid_get_network_interface_up_state (void *ifname, int *is_up)
{
*is_up = 1;
return 1;
}
MONO_API int
_monodroid_get_network_interface_supports_multicast (void *ifname, int *supports_multicast)
{
*supports_multicast = 0;
return 1;
}
MONO_API int
_monodroid_get_dns_servers (void **dns_servers_array)
{
*dns_servers_array = NULL;
if (!dns_servers_array)
return -1;
size_t len;
char *dns;
char *dns_servers [8];
int count = 0;
char prop_name[] = "net.dnsX";
int i;
for (i = 0; i < 8; i++) {
prop_name [7] = (char)(i + 0x31);
len = monodroid_get_system_property (prop_name, &dns);
if (len <= 0) {
dns_servers [i] = NULL;
continue;
}
dns_servers [i] = strndup (dns, len);
count++;
}
if (count <= 0)
return 0;
char **ret = (char**)malloc (sizeof (char*) * count);
char **p = ret;
for (i = 0; i < 8; i++) {
if (!dns_servers [i])
continue;
*p++ = dns_servers [i];
}
*dns_servers_array = (void*)ret;
return count;
}

Просмотреть файл

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content_run_mono"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Run Tests" android:id="@+id/button" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="NO RUN"
android:id="@+id/text" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/input" />
</LinearLayout>

Просмотреть файл

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Mono Runtime Test runner</string>
</resources>

Просмотреть файл

@ -0,0 +1,136 @@
package org.mono.android;
import android.content.pm.ApplicationInfo;
import android.content.Context;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.content.res.AssetManager;
import android.util.Log;
import android.widget.*;
import android.view.*;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.mono.android.AndroidTestRunner.R;
public class AndroidRunner extends Activity
{
Handler the_handler;
public void updateTheButton () {
// Log.w ("MONO", "CHECKING STATUS!");
String s = send ("status", "tests");
final TextView tv = (TextView)findViewById (R.id.text);
if (!s.equals ("NO RUN"))
tv.setText (s);
if (s.equals ("IN-PROGRESS"))
the_handler.postDelayed(
new Runnable () {
public void run () {
updateTheButton ();
}
},
1000);
}
static String mkstr (CharSequence cq) {
StringBuilder sb = new StringBuilder ();
sb.append (cq);
return sb.toString();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater)this.getSystemService (Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate (R.layout.main, null, false);
setContentView (view);
Button b = (Button)findViewById (R.id.button);
final TextView tv = (TextView)findViewById (R.id.text);
final TextView ed = (EditText)findViewById (R.id.input);
the_handler = new Handler (this.getMainLooper());
b.setOnClickListener(
new View.OnClickListener () {
public void onClick(View v) {
String input_str = mkstr (ed.getText ());
tv.setText (send ("start", input_str));
updateTheButton ();
}
});
setupRuntime (this);
}
void copy (InputStream in, OutputStream out) throws IOException {
byte[] buff = new byte [1024];
int len = in.read (buff);
while (len != -1) {
out.write (buff, 0, len);
len = in.read (buff);
}
in.close ();
out.close ();
}
void copyAssetDir (AssetManager am, String path, String outpath) {
Log.w ("MONO", "EXTRACTING: " + path);
try {
String[] res = am.list (path);
for (int i = 0; i < res.length; ++i) {
String fromFile = path + "/" + res [i];
String toFile = outpath + "/" + res [i];
Log.w ("MONO", "\tCOPYING " + fromFile + " to " + toFile);
copy (am.open (fromFile), new FileOutputStream (toFile));
}
} catch (Exception e) {
Log.w ("MONO", "WTF", e);
}
}
public void setupRuntime (Context context) {
String filesDir = context.getFilesDir ().getAbsolutePath ();
String cacheDir = context.getCacheDir ().getAbsolutePath ();
String dataDir = getNativeLibraryPath (context);
String assemblyDir = filesDir + "/" + "assemblies";
//XXX copy stuff
Log.w ("MONO", "DOING THE COPYING!2");
AssetManager am = context.getAssets ();
new File (assemblyDir).mkdir ();
copyAssetDir (am, "asm", assemblyDir);
new File (filesDir + "/mono").mkdir ();
new File (filesDir + "/mono/2.1").mkdir ();
copyAssetDir (am, "mconfig", filesDir + "/mono/2.1");
init (filesDir, cacheDir, dataDir, assemblyDir);
execMain ();
}
static String getNativeLibraryPath (Context context) {
return getNativeLibraryPath (context.getApplicationInfo ());
}
static String getNativeLibraryPath (ApplicationInfo ainfo) {
if (android.os.Build.VERSION.SDK_INT >= 9)
return ainfo.nativeLibraryDir;
return ainfo.dataDir + "/lib";
}
native void init(String path0, String path1, String path2, String path3);
native int execMain ();
native String send (String key, String value);
static {
System.loadLibrary("runtime-bootstrap");
}
}