Skip to content

Commit

Permalink
Make AndroidSampleApp use host_runtime_contact::external_assembly_probe
Browse files Browse the repository at this point in the history
  • Loading branch information
elinor-fung committed Feb 27, 2025
1 parent 57974b0 commit 1ea37be
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 17 deletions.
1 change: 1 addition & 0 deletions src/mono/sample/Android/AndroidSampleApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

<ItemGroup>
<RuntimeComponents Condition="'$(RuntimeFlavor)' == 'Mono' and '$(DiagnosticPorts)' != ''" Include="diagnostics_tracing" />
<RuntimeHeaders Include="$(SharedNativeRoot)" Condition="'$(RuntimeFlavor)' != 'Mono'"/>
</ItemGroup>

<Import Project="$(MonoProjectRoot)\msbuild\android\build\AndroidBuild.props" />
Expand Down
100 changes: 83 additions & 17 deletions src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include <coreclrhost.h>
#include <dirent.h>

#include <corehost/host_runtime_contract.h>

/********* exported symbols *********/

/* JNI exports */
Expand All @@ -34,11 +36,15 @@ Java_net_dot_MonoRunner_freeNativeResources (JNIEnv* env, jobject thiz);

/********* implementation *********/

static const char* g_bundle_path = NULL;
static char* g_bundle_path = NULL;
static const char* g_executable_path = NULL;
static unsigned int g_coreclr_domainId = 0;
static void* g_coreclr_handle = NULL;

#define MAX_MAPPED_COUNT 50 // Arbitrarily 'large enough' number
static void* g_mapped_files[MAX_MAPPED_COUNT];
static size_t g_mapped_file_sizes[MAX_MAPPED_COUNT];
static unsigned int g_mapped_files_count = 0;

#define LOG_INFO(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, "DOTNET", fmt, ##__VA_ARGS__)
#define LOG_ERROR(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, "DOTNET", fmt, ##__VA_ARGS__)
Expand Down Expand Up @@ -70,7 +76,7 @@ strncpy_str (JNIEnv *env, char *buff, jstring str, int nbuff)

/*
* Get the list of trusted assemblies from a specified @dir_path.
* The path is searched for .dll files which when found are concatenated
* The path is searched for .dll files which when found are concatenated
* to the output string @tpas separated by ':'.
* The output string should be freed by the caller.
* The return value is the length of the output string.
Expand Down Expand Up @@ -147,6 +153,56 @@ bundle_executable_path (const char* executable, const char* bundle_path, const c
return executable_path_len;
}

static bool
external_assembly_probe(const char* name, void** data, int64_t* size)
{
if (g_mapped_files_count >= MAX_MAPPED_COUNT)
{
LOG_ERROR("Too many mapped files, cannot map %s", name);
return false;
}

// Get just the file name
const char* pos = strrchr(name, '/');
if (pos != NULL)
name = pos + 1;

// Look in the bundle path where the files were extracted
char full_path[1024];
size_t path_len = strlen(g_bundle_path) + strlen(name) + 1; // +1 for '/'
size_t res = snprintf(full_path, path_len + 1, "%s/%s", g_bundle_path, name);
if (res < 0 || res != path_len)
return false;

int fd = open(full_path, O_RDONLY);
if (fd == -1)
return false;

struct stat buf;
if (fstat(fd, &buf) == -1)
{
close(fd);
return false;
}

int64_t size_local = buf.st_size;
void* mapped = mmap(NULL, size_local, PROT_READ, MAP_PRIVATE, fd, 0);
if (mapped == MAP_FAILED)
{
close(fd);
return false;
}

LOG_INFO("Mapped %s -> %s", name, full_path);
g_mapped_files[g_mapped_files_count] = mapped;
g_mapped_file_sizes[g_mapped_files_count] = size_local;
g_mapped_files_count++;
close(fd);
*data = mapped;
*size = size_local;
return true;
}

static void
free_resources ()
{
Expand All @@ -166,9 +222,13 @@ free_resources ()
coreclr_shutdown (g_coreclr_handle, g_coreclr_domainId);
g_coreclr_handle = NULL;
}
for (int i = 0; i < g_mapped_files_count; ++i)
{
munmap (g_mapped_files[i], g_mapped_file_sizes[i]);
}
}

static int
static int
mono_droid_execute_assembly (const char* executable_path, void* coreclr_handle, unsigned int coreclr_domainId, int managed_argc, const char** managed_argv)
{
unsigned int rv;
Expand All @@ -178,6 +238,8 @@ mono_droid_execute_assembly (const char* executable_path, void* coreclr_handle,
return rv;
}

#define PROPERTY_COUNT 3

static int
mono_droid_runtime_init (const char* executable)
{
Expand All @@ -198,34 +260,38 @@ mono_droid_runtime_init (const char* executable)

chdir (g_bundle_path);

// TODO: set TRUSTED_PLATFORM_ASSEMBLIES, APP_PATHS and NATIVE_DLL_SEARCH_DIRECTORIES
struct host_runtime_contract host_contract = {
sizeof(struct host_runtime_contract),
NULL, // context
NULL, // get_runtime_property
NULL, // bundle_proble
NULL, // pinvoke_override
&external_assembly_probe };

const char* appctx_keys[3];
const char* appctx_keys[PROPERTY_COUNT];
appctx_keys[0] = "RUNTIME_IDENTIFIER";
appctx_keys[1] = "APP_CONTEXT_BASE_DIRECTORY";
appctx_keys[2] = "TRUSTED_PLATFORM_ASSEMBLIES";
appctx_keys[2] = "HOST_RUNTIME_CONTRACT";

const char* appctx_values[3];
const char* appctx_values[PROPERTY_COUNT];
appctx_values[0] = ANDROID_RUNTIME_IDENTIFIER;
appctx_values[1] = g_bundle_path;
size_t tpas_len = get_tpas_from_path(g_bundle_path, &appctx_values[2]);
if (tpas_len < 1)
{
LOG_ERROR("Failed to get trusted assemblies from path: %s", g_bundle_path);
return -1;
}

char contract_str[19]; // 0x + 16 hex digits + '\0'
snprintf(contract_str, 19, "0x%zx", (size_t)(&host_contract));
appctx_values[2] = contract_str;

LOG_INFO ("Calling coreclr_initialize");
int rv = coreclr_initialize (
g_executable_path,
executable,
3,
PROPERTY_COUNT,
appctx_keys,
appctx_values,
&g_coreclr_handle,
&g_coreclr_domainId
);
LOG_INFO ("coreclr_initialize returned %d", rv);
LOG_INFO ("coreclr_initialize returned 0x%x", rv);
return rv;
}

Expand All @@ -237,7 +303,7 @@ Java_net_dot_MonoRunner_setEnv (JNIEnv* env, jobject thiz, jstring j_key, jstrin

const char *key = (*env)->GetStringUTFChars(env, j_key, 0);
const char *val = (*env)->GetStringUTFChars(env, j_value, 0);

LOG_INFO ("Setting env: %s=%s", key, val);
setenv (key, val, true);
(*env)->ReleaseStringUTFChars(env, j_key, key);
Expand Down Expand Up @@ -270,7 +336,7 @@ int
Java_net_dot_MonoRunner_execEntryPoint (JNIEnv* env, jobject thiz, jstring j_entryPointLibName, jobjectArray j_args)
{
LOG_INFO("Java_net_dot_MonoRunner_execEntryPoint (CoreCLR):");

if ((g_bundle_path == NULL) || (g_executable_path == NULL))
{
LOG_ERROR("Bundle path or executable path not set");
Expand Down

0 comments on commit 1ea37be

Please sign in to comment.