summaryrefslogtreecommitdiff
path: root/library/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/src')
-rw-r--r--library/src/androidTest/java/akono/InstrumentedAkonoTests.kt85
-rw-r--r--library/src/main/AndroidManifest.xml7
-rw-r--r--library/src/main/cpp/CMakeLists.txt42
-rw-r--r--library/src/main/cpp/akono-jni.cpp588
-rw-r--r--library/src/main/java/akono/AkonoJni.kt208
-rw-r--r--library/src/main/java/akono/Library.kt10
-rw-r--r--library/src/test/java/akono/LibraryTest.kt16
7 files changed, 0 insertions, 956 deletions
diff --git a/library/src/androidTest/java/akono/InstrumentedAkonoTests.kt b/library/src/androidTest/java/akono/InstrumentedAkonoTests.kt
deleted file mode 100644
index beda5119..00000000
--- a/library/src/androidTest/java/akono/InstrumentedAkonoTests.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-package akono.test;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import org.junit.runner.RunWith
-import org.junit.Test
-import androidx.test.filters.LargeTest
-import org.junit.Assert.assertEquals
-import akono.AkonoJni
-import akono.ModuleResult
-import android.util.Log
-import java.util.concurrent.LinkedBlockingDeque
-
-
-class SyncMessageHandler : AkonoJni.MessageHandler {
- private val messageQueue = LinkedBlockingDeque<String>()
- override fun handleMessage(message: String) {
- messageQueue.put(message)
- }
-
- fun waitForMessage(): String {
- return messageQueue.take()
- }
-}
-
-
-class StaticModuleLoadHandler : AkonoJni.LoadModuleHandler {
- private val modules: MutableMap<String, String> = HashMap()
-
- override fun loadModule(name: String, paths: Array<String>): ModuleResult? {
- val code = modules.get(name) ?: return null
- if (modules.containsKey(name)) {
- return ModuleResult("/vmodroot/$name.js", code)
- }
- return null
- }
-
- fun registerModule(name: String, source: String) {
- modules[name] = source
- }
-}
-
-
-// @RunWith is required only if you use a mix of JUnit3 and JUnit4.
-@RunWith(AndroidJUnit4::class)
-@LargeTest
-public class InstrumentedAkonoTestOne {
- @Test
- fun myJsTest() {
- val ajni: AkonoJni = AkonoJni()
- assertEquals("2", ajni.evalSimpleJs("1+1"))
- assertEquals("36", ajni.evalSimpleJs("6*6"))
- assertEquals("42", ajni.evalSimpleJs("(()=>{let x = 42; return x;})()"))
- assertEquals("undefined", ajni.evalSimpleJs("const myVal = 42"))
- assertEquals("43", ajni.evalSimpleJs("myVal + 1"))
-
- val myHandler = SyncMessageHandler()
- ajni.setMessageHandler(myHandler)
- ajni.evalNodeCode("console.log('hi from the test case')")
- // Tell the message handler to just ping back messages to us
- ajni.evalNodeCode("global.__akono_onMessage = (x) => { global.__akono_sendMessage(x); }")
- val sentMessage = "Hello AKONO!!"
- ajni.sendMessage(sentMessage)
- val receivedMessage = myHandler.waitForMessage()
- assertEquals(sentMessage, receivedMessage)
- Log.i("myapp", "test case received message: $receivedMessage")
-
- val myModHandler = StaticModuleLoadHandler()
-
- ajni.setLoadModuleHandler(myModHandler)
-
- myModHandler.registerModule("a", """
- |console.log('I am module a');
- |exports.foo = () => { global.__akono_sendMessage('hello42'); };
- """.trimMargin())
-
- ajni.evalNodeCode("a = require('a');")
- ajni.evalNodeCode("a.foo()")
-
- val msg2 = myHandler.waitForMessage()
-
- assertEquals("hello42", msg2)
-
- ajni.waitStopped()
- }
-}
diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml
deleted file mode 100644
index 3a8d4915..00000000
--- a/library/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="net.taler.akono">
-
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
-</manifest>
diff --git a/library/src/main/cpp/CMakeLists.txt b/library/src/main/cpp/CMakeLists.txt
deleted file mode 100644
index 10d6396f..00000000
--- a/library/src/main/cpp/CMakeLists.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-cmake_minimum_required(VERSION 3.4.1)
-
-add_library(
- akono-jni SHARED
- akono-jni.cpp
-)
-
-set(deps_dir ${CMAKE_CURRENT_SOURCE_DIR}/../../../../deps)
-
-if(NOT EXISTS ${deps_dir})
- message( FATAL_ERROR "Dependency directory does not exist")
-endif()
-
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14")
-
-include_directories(
- ${deps_dir}/android-node-v8/src
- ${deps_dir}/android-node-v8/deps/v8/include
- ${deps_dir}/android-node-v8/deps/uv/include
-)
-
-add_library(node SHARED IMPORTED)
-set_target_properties(node PROPERTIES IMPORTED_LOCATION
- ${deps_dir}/compiled/${ANDROID_ABI}/libnode.so)
-
-add_library(v8 STATIC IMPORTED)
-set_target_properties(v8 PROPERTIES IMPORTED_LOCATION
- ${deps_dir}/compiled/${ANDROID_ABI}/libv8.cr.so)
-
-add_library(v8_platform STATIC IMPORTED)
-set_target_properties(v8_platform PROPERTIES IMPORTED_LOCATION
- ${deps_dir}/compiled/${ANDROID_ABI}/libv8_libplatform.cr.so)
-
-# Include libraries needed for hello-jni lib
-target_link_libraries(akono-jni
- v8
- v8_platform
- node
- android
- log)
-
-
diff --git a/library/src/main/cpp/akono-jni.cpp b/library/src/main/cpp/akono-jni.cpp
deleted file mode 100644
index b9e71012..00000000
--- a/library/src/main/cpp/akono-jni.cpp
+++ /dev/null
@@ -1,588 +0,0 @@
-#include <string.h>
-#include <jni.h>
-#include <libplatform/libplatform.h>
-#include <v8.h>
-
-#define NODE_WANT_INTERNALS 1
-
-#include <node.h>
-
-#include <uv.h>
-#include <unistd.h>
-#include <android/log.h>
-#include <node_main_instance.h>
-#include <node_native_module_env.h>
-
-
-
-// Provide stubs so that libnode.so links properly
-namespace node {
- namespace native_module {
- const bool has_code_cache = false;
-
- void NativeModuleEnv::InitializeCodeCache() {}
- }
-
- v8::StartupData *NodeMainInstance::GetEmbeddedSnapshotBlob() {
- return nullptr;
- }
-
- const std::vector<size_t> *NodeMainInstance::GetIsolateDataIndexes() {
- return nullptr;
- }
-}
-
-
-static int pfd[2];
-static pthread_t thr;
-static const char *tag = "myapp";
-
-
-static void *thread_func(void *) {
- ssize_t rdsz;
- char buf[128];
- while ((rdsz = read(pfd[0], buf, sizeof buf - 1)) > 0) {
- if (buf[rdsz - 1] == '\n') --rdsz;
- buf[rdsz] = 0; /* add null-terminator */
- __android_log_write(ANDROID_LOG_DEBUG, tag, buf);
- }
- return 0;
-}
-
-static void mylog(const char *msg) {
- __android_log_write(ANDROID_LOG_DEBUG, tag, msg);
-}
-
-int start_logger(const char *app_name) {
- tag = app_name;
-
- /* make stdout line-buffered and stderr unbuffered */
- setvbuf(stdout, 0, _IOLBF, 0);
- setvbuf(stderr, 0, _IONBF, 0);
-
- /* create the pipe and redirect stdout and stderr */
- pipe(pfd);
- dup2(pfd[1], 1);
- dup2(pfd[1], 2);
-
- /* spawn the logging thread */
- if (pthread_create(&thr, 0, thread_func, 0) == -1)
- return -1;
- pthread_detach(thr);
- return 0;
-}
-
-
-/**
- * Helper class to manage conversion from a JNI string to a C string.
- */
-class JStringValue {
-private:
- jstring m_jstr;
- const char *m_cstr;
- JNIEnv *m_env;
-public:
- JStringValue(JNIEnv *env, jstring s) : m_env(env), m_jstr(s) {
- m_cstr = env->GetStringUTFChars(s, NULL);
- }
-
- ~JStringValue() {
- m_env->ReleaseStringUTFChars(m_jstr, m_cstr);
- }
-
- const char *operator*() {
- return m_cstr;
- }
-};
-
-
-/**
- * Slightly more sane wrapper around node::Init
- */
-static void InitNode(std::vector<const char *> argv) {
- int ret_exec_argc = 0;
- int ret_argc = argv.size();
- const char **ret_exec_argv = nullptr;
-
- node::Init(&ret_argc, &argv[0], &ret_exec_argc, &ret_exec_argv);
-}
-
-// Forward declarations
-void notifyCb(uv_async_t *async);
-
-static void sendMessageCallback(const v8::FunctionCallbackInfo<v8::Value> &args);
-static void loadModuleCallback(const v8::FunctionCallbackInfo<v8::Value> &args);
-static void getDataCallback(const v8::FunctionCallbackInfo<v8::Value> &args);
-
-static const char *main_code = "global.__akono_run = (x) => {"
- " console.log('running code', x);"
- " global.eval(x);"
- "};"
- ""
- "global.__akono_onMessage = (x) => {"
- " console.log('got __akono_onMessage', x);"
- "};"
- ""
- "mod = require('module');"
- "mod._saved_findPath = mod._findPath;"
- "mod._akonoMods = {};"
- "mod._findPath = (request, paths, isMain) => {"
- " console.log('in _findPath');"
- " const res = mod._saved_findPath(request, paths, isMain);"
- " if (res !== false) return res;"
- " const args = JSON.stringify({ request, paths});"
- " const loadResult = JSON.parse(global.__akono_loadModule(args));"
- " console.log('got loadModule result', loadResult);"
- " if (!loadResult) return false;"
- " mod._akonoMods[loadResult.path] = loadResult;"
- " console.log('returning path', loadResult.path);"
- " return loadResult.path;"
- "};"
- ""
- "function stripBOM(content) {"
- " if (content.charCodeAt(0) === 0xFEFF) {"
- " content = content.slice(1);"
- " }"
- " return content;"
- "}"
- ""
- "mod._saved_js_extension = mod._extensions[\".js\"];"
- "mod._extensions[\".js\"] = (module, filename) => {"
- " console.log('handling js extension', [module, filename]);"
- " if (mod._akonoMods.hasOwnProperty(filename)) {"
- " const akmod = mod._akonoMods[filename];"
- " console.log('found mod', akmod);"
- " const content = akmod.content;"
- " return module._compile(stripBOM(content), filename);"
- " }"
- " console.log('falling back');"
- " return mod._saved_js_extension(module, filename);"
- "};";
-
-
-class NativeAkonoInstance {
-private:
- static bool logInitialized;
- static bool v8Initialized;
- //static std::unique_ptr<v8::Platform> platform;
- static node::MultiIsolatePlatform *platform;
-public:
- v8::Isolate *isolate;
- node::Environment *environment;
- v8::Persistent<v8::Context> globalContext;
- uv_async_t async_notify;
- uv_loop_t *loop;
- bool breakRequested = false;
- JNIEnv *currentJniEnv = nullptr;
- jobject currentJniThiz = nullptr;
-
- NativeAkonoInstance() : globalContext() {
- loop = uv_default_loop();
- uv_async_init(loop, &async_notify, notifyCb);
- async_notify.data = this;
-
- if (!logInitialized) {
- start_logger("myapp");
- logInitialized = true;
- }
-
- if (!v8Initialized) {
- //platform = v8::platform::NewDefaultPlatform();
- //v8::V8::InitializePlatform(platform.get());
- //v8::V8::Initialize();
-
- // Here, only the arguments used to initialize the global node/v8 platform
- // are relevant, the others are skipped.
- InitNode(std::vector<const char *>{"node", "-e", main_code});
- platform = node::InitializeV8Platform(10);
- v8::V8::Initialize();
-
- v8Initialized = true;
- }
-
- node::ArrayBufferAllocator *allocator = node::CreateArrayBufferAllocator();
- this->isolate = node::NewIsolate(allocator, uv_default_loop());
-
-
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
-
- node::IsolateData *isolateData = node::CreateIsolateData(
- this->isolate,
- uv_default_loop(),
- platform,
- allocator);
-
-
- globalContext.Reset(isolate, node::NewContext(isolate));
-
- v8::Local<v8::Context> context = globalContext.Get(isolate);
-
- // Arguments for node itself
- std::vector<const char *> nodeArgv{"node", "-e", "console.log('hello world');"};
- // Arguments for the script run by node
- std::vector<const char *> nodeExecArgv{};
-
- mylog("entering global scopt");
-
- v8::Context::Scope context_scope(globalContext.Get(isolate));
-
- mylog("creating environment");
-
- node::Environment *environment = node::CreateEnvironment(
- isolateData,
- globalContext.Get(isolate),
- nodeArgv.size(),
- &nodeArgv[0],
- nodeExecArgv.size(),
- &nodeExecArgv[0]);
-
-
- mylog("loading environment");
-
- node::LoadEnvironment(environment);
-
- mylog("finished loading environment");
-
- v8::Local<v8::ObjectTemplate> dataTemplate = v8::ObjectTemplate::New(isolate);
- dataTemplate->SetInternalFieldCount(1);
- v8::Local<v8::Object> dataObject = dataTemplate->NewInstance(context).ToLocalChecked();
- dataObject->SetAlignedPointerInInternalField(0, this);
-
- v8::Local<v8::Function> sendMessageFunction = v8::Function::New(context,
- sendMessageCallback,
- dataObject).ToLocalChecked();
-
- v8::Local<v8::Function> loadModuleFunction = v8::Function::New(context,
- loadModuleCallback,
- dataObject).ToLocalChecked();
-
- v8::Local<v8::Function> getDataFunction = v8::Function::New(context,
- getDataCallback,
- dataObject).ToLocalChecked();
-
- v8::Local<v8::Object> global = context->Global();
-
- global->Set(v8::String::NewFromUtf8(isolate, "__akono_sendMessage",
- v8::NewStringType::kNormal).ToLocalChecked(),
- sendMessageFunction);
-
- global->Set(v8::String::NewFromUtf8(isolate, "__akono_loadModule",
- v8::NewStringType::kNormal).ToLocalChecked(),
- loadModuleFunction);
-
- // Get data synchronously (!) from the embedder
- global->Set(v8::String::NewFromUtf8(isolate, "__akono_getData",
- v8::NewStringType::kNormal).ToLocalChecked(),
- getDataFunction);
-
- }
-
- /**
- * Process the node message loop until a break has been requested.
- *
- * @param env JNI env of the thread we're running in.
- */
- void runNode() {
- this->breakRequested = false;
- while (1) {
- uv_run(uv_default_loop(), UV_RUN_ONCE);
- if (this->breakRequested)
- break;
- }
- }
-
- /**
- * Inject code into the running node instance.
- *
- * Must not be called from a different thread.
- */
- void makeCallback(const char *code) {
- mylog("in makeCallback");
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
- v8::Local<v8::Context> context = globalContext.Get(isolate);
- v8::Context::Scope context_scope(context);
- v8::Local<v8::Object> global = context->Global();
- v8::Local<v8::Value> argv[] = {
- v8::String::NewFromUtf8(isolate, code,
- v8::NewStringType::kNormal).ToLocalChecked()
- };
- mylog("calling node::MakeCallback");
- node::MakeCallback(isolate, global, "__akono_run", 1, argv, {0, 0});
- }
-
- ~NativeAkonoInstance() {
- //this->isolate->Dispose();
- }
-
- jstring evalJs(JNIEnv *env, jstring sourceString) {
- mylog("begin evalJs");
-
- JStringValue jsv(env, sourceString);
-
- v8::Isolate::Scope isolate_scope(isolate);
-
- // Create a stack-allocated handle scope.
- v8::HandleScope handle_scope(isolate);
-
- // Create a new context.
- //v8::Local<v8::Context> context = v8::Context::New(isolate);
-
- v8::Local<v8::Context> context = globalContext.Get(isolate);
-
- // Enter the context for compiling and running the hello world script.
- v8::Context::Scope context_scope(context);
-
- {
- // Create a string containing the JavaScript source code.
- v8::Local<v8::String> source =
- v8::String::NewFromUtf8(isolate, *jsv,
- v8::NewStringType::kNormal)
- .ToLocalChecked();
-
- // Compile the source code.
- v8::Local<v8::Script> script;
-
- mylog("about to compile script");
-
- if (!v8::Script::Compile(context, source).ToLocal(&script)) {
- return nullptr;
- }
-
- mylog("about to run script");
-
- // Run the script to get the result.
- v8::Local<v8::Value> result;
- if (!script->Run(context).ToLocal(&result)) {
- mylog("running script failed");
- return nullptr;
- }
-
- mylog("converting script result value");
-
- // Convert the result to an UTF8 string and print it.
- v8::String::Utf8Value utf8(isolate, result);
-
- mylog("about to return value");
-
- return env->NewStringUTF(*utf8);
- }
- }
-};
-
-
-bool NativeAkonoInstance::v8Initialized = false;
-bool NativeAkonoInstance::logInitialized = false;
-node::MultiIsolatePlatform *NativeAkonoInstance::platform = nullptr;
-
-
-void notifyCb(uv_async_t *async) {
- NativeAkonoInstance *akono = (NativeAkonoInstance *) async->data;
- mylog("async notifyCb called!");
- akono->breakRequested = true;
-}
-
-static void sendMessageCallback(const v8::FunctionCallbackInfo<v8::Value> &args) {
- if (args.Length() < 1) return;
- v8::Isolate *isolate = args.GetIsolate();
- v8::HandleScope scope(isolate);
- v8::Local<v8::Value> arg = args[0];
- v8::String::Utf8Value value(isolate, arg);
- mylog("sendMessageCallback called, yay!");
-
- v8::Local<v8::Object> data = v8::Local<v8::Object>::Cast(args.Data());
-
- mylog("getting instance");
- NativeAkonoInstance *myInstance = (NativeAkonoInstance *) data->GetAlignedPointerFromInternalField(0);
-
- JNIEnv *env = myInstance->currentJniEnv;
-
- if (env == nullptr) {
- mylog("FATAL: JNI env is nullptr");
- return;
- }
-
- mylog("finding class");
- jclass clazz = env->FindClass("akono/AkonoJni");
-
- if (clazz == nullptr) {
- mylog("FATAL: class not found");
- return;
- }
-
- mylog("creating strings");
- jstring jstr1 = env->NewStringUTF("message");
- jstring jstr2 = env->NewStringUTF(*value);
-
- mylog("getting method");
-
- jmethodID meth = env->GetMethodID(clazz, "internalOnNotify", "(Ljava/lang/String;Ljava/lang/String;)V");
-
- if (meth == nullptr) {
- mylog("FATAL: method not found");
- return;
- }
-
- mylog("calling method");
-
- env->CallVoidMethod(myInstance->currentJniThiz, meth, jstr1, jstr2);
-}
-
-
-static void loadModuleCallback(const v8::FunctionCallbackInfo<v8::Value> &args) {
- if (args.Length() < 1) return;
- v8::Isolate *isolate = args.GetIsolate();
- v8::HandleScope scope(isolate);
- v8::Local<v8::Value> arg = args[0];
- v8::String::Utf8Value value(isolate, arg);
- mylog("sendMessageCallback called, yay!");
-
- v8::Local<v8::Object> data = v8::Local<v8::Object>::Cast(args.Data());
-
- mylog("getting instance");
- NativeAkonoInstance *myInstance = (NativeAkonoInstance *) data->GetAlignedPointerFromInternalField(0);
-
- JNIEnv *env = myInstance->currentJniEnv;
-
- if (env == nullptr) {
- mylog("FATAL: JNI env is nullptr");
- return;
- }
-
- mylog("finding class");
- jclass clazz = env->FindClass("akono/AkonoJni");
-
- if (clazz == nullptr) {
- mylog("FATAL: class not found");
- return;
- }
-
- mylog("creating strings");
- jstring jstr1 = env->NewStringUTF(*value);
-
- mylog("getting method");
-
- jmethodID meth = env->GetMethodID(clazz, "internalOnModuleLoad", "(Ljava/lang/String;)Ljava/lang/String;");
-
- if (meth == nullptr) {
- mylog("FATAL: method not found");
- return;
- }
-
- mylog("calling method");
-
- jstring jresult = (jstring) env->CallObjectMethod(myInstance->currentJniThiz, meth, jstr1);
-
- JStringValue resultStringValue(env, jresult);
-
- printf("before creating string, res %s\n", *resultStringValue);
-
- // Create a string containing the JavaScript source code.
- v8::Local<v8::String> rs =
- v8::String::NewFromUtf8(isolate, *resultStringValue,
- v8::NewStringType::kNormal)
- .ToLocalChecked();
-
- args.GetReturnValue().Set(rs);
-}
-
-
-static void getDataCallback(const v8::FunctionCallbackInfo<v8::Value> &args) {
- if (args.Length() < 1) return;
- v8::Isolate *isolate = args.GetIsolate();
- v8::HandleScope scope(isolate);
- v8::Local<v8::Value> arg = args[0];
- v8::String::Utf8Value value(isolate, arg);
- mylog("getDataCallback called");
-
- v8::Local<v8::Object> data = v8::Local<v8::Object>::Cast(args.Data());
- mylog("getting instance");
- NativeAkonoInstance *myInstance = (NativeAkonoInstance *) data->GetAlignedPointerFromInternalField(0);
-
- JNIEnv *env = myInstance->currentJniEnv;
- if (env == nullptr) {
- mylog("FATAL: JNI env is nullptr");
- return;
- }
-
- mylog("finding class");
- jclass clazz = env->FindClass("akono/AkonoJni");
-
- if (clazz == nullptr) {
- mylog("FATAL: class not found");
- return;
- }
-
- mylog("creating strings");
- jstring jstr1 = env->NewStringUTF(*value);
-
- mylog("getting method");
-
- jmethodID meth = env->GetMethodID(clazz, "internalOnGetData", "(Ljava/lang/String;)Ljava/lang/String;");
-
- if (meth == nullptr) {
- mylog("FATAL: method not found");
- return;
- }
-
- mylog("calling method");
-
- jstring jresult = (jstring) env->CallObjectMethod(myInstance->currentJniThiz, meth, jstr1);
-
- JStringValue resultStringValue(env, jresult);
-
- printf("before creating string, res %s\n", *resultStringValue);
-
- // Create a string containing the JavaScript source code.
- v8::Local<v8::String> rs =
- v8::String::NewFromUtf8(isolate, *resultStringValue,
- v8::NewStringType::kNormal)
- .ToLocalChecked();
-
- args.GetReturnValue().Set(rs);
-}
-
-
-extern "C" JNIEXPORT jobject JNICALL
-Java_akono_AkonoJni_initNative(JNIEnv *env, jobject thiz) {
- NativeAkonoInstance *myInstance = new NativeAkonoInstance();
- return env->NewDirectByteBuffer(myInstance, 0);
-}
-
-
-extern "C" JNIEXPORT void JNICALL
-Java_akono_AkonoJni_destroyNative(JNIEnv *env, jobject thiz, jobject buf) {
- NativeAkonoInstance *myInstance = (NativeAkonoInstance *) env->GetDirectBufferAddress(buf);
- delete myInstance;
-}
-
-
-extern "C" JNIEXPORT jstring JNICALL
-Java_akono_AkonoJni_evalJs(JNIEnv *env, jobject thiz, jstring sourceStr, jobject buf) {
- NativeAkonoInstance *myInstance = (NativeAkonoInstance *) env->GetDirectBufferAddress(buf);
- return myInstance->evalJs(env, sourceStr);
-}
-
-extern "C" JNIEXPORT void JNICALL
-Java_akono_AkonoJni_notifyNative(JNIEnv *env, jobject thiz, jobject buf) {
- NativeAkonoInstance *myInstance = (NativeAkonoInstance *) env->GetDirectBufferAddress(buf);
- uv_async_send(&myInstance->async_notify);
-}
-
-extern "C" JNIEXPORT void JNICALL
-Java_akono_AkonoJni_runNode(JNIEnv *env, jobject thiz, jobject buf) {
- NativeAkonoInstance *myInstance = (NativeAkonoInstance *) env->GetDirectBufferAddress(buf);
- myInstance->currentJniEnv = env;
- myInstance->currentJniThiz = thiz;
- myInstance->runNode();
-}
-
-extern "C" JNIEXPORT void JNICALL
-Java_akono_AkonoJni_makeCallbackNative(JNIEnv *env, jobject thiz, jstring sourceStr, jobject buf) {
- JStringValue jsv(env, sourceStr);
- NativeAkonoInstance *myInstance = (NativeAkonoInstance *) env->GetDirectBufferAddress(buf);
- myInstance->currentJniEnv = env;
- myInstance->currentJniThiz = thiz;
- return myInstance->makeCallback(*jsv);
-}
diff --git a/library/src/main/java/akono/AkonoJni.kt b/library/src/main/java/akono/AkonoJni.kt
deleted file mode 100644
index 4a89a3f6..00000000
--- a/library/src/main/java/akono/AkonoJni.kt
+++ /dev/null
@@ -1,208 +0,0 @@
-package akono
-
-import android.util.Base64
-import android.util.Log
-import org.json.JSONObject
-import java.lang.Exception
-import java.nio.ByteBuffer
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.LinkedBlockingDeque
-import kotlin.concurrent.thread
-
-typealias AkonoNativePointer = ByteBuffer
-
-data class ModuleResult(val path: String, val contents: String)
-
-class AkonoJni(vararg nodeArgv: String) {
- private var getDataHandler: GetDataHandler? = null
- private var messageHandler: MessageHandler? = null
- private var loadModuleHandler: LoadModuleHandler? = null
- private val initializedLatch = CountDownLatch(1)
-
- private val workQueue = LinkedBlockingDeque<() -> Unit>()
-
- private external fun evalJs(source: String, p: AkonoNativePointer): String
- private external fun runNode(p: AkonoNativePointer)
-
- private external fun makeCallbackNative(source: String, p: AkonoNativePointer)
-
- private external fun destroyNative(b: AkonoNativePointer)
- private external fun initNative(nodeArgv: Array<out String>): AkonoNativePointer
- private external fun notifyNative(b: AkonoNativePointer)
-
- private lateinit var internalNativePointer: AkonoNativePointer
-
- private val jniThread: Thread
-
- private var stopped = false
-
- /**
- * Schedule a block do be executed in the node thread.
- */
- private fun scheduleNodeThread(b: () -> Unit) {
- initializedLatch.await()
- workQueue.put(b)
- notifyNative()
- }
-
- /**
- * Called by node/v8 from its thread.
- */
- @Suppress("unused")
- private fun internalOnNotify(type: String, payload: String) {
- Log.i("myapp", "internalOnNotify called")
- Log.i("myapp", "type: $type")
- Log.i("myapp", "payload: $payload")
- messageHandler?.handleMessage(payload)
- }
-
- /**
- * Called by node/v8 from its thread.
- */
- @Suppress("unused")
- private fun internalOnModuleLoad(loadInfoStr: String): String {
- Log.i("myapp", "internalOnModuleLoad called")
- Log.i("myapp", "loadInfoStr is $loadInfoStr")
- try {
- val loadInfo = JSONObject(loadInfoStr)
- val request: String = loadInfo.getString("request")
- Log.i("myapp", "request is $request")
- val handler = loadModuleHandler
- if (handler != null) {
- val modResult = handler.loadModule(request, arrayOf()) ?: return "null"
- val result = JSONObject()
- result.put("path", modResult.path)
- result.put("content", modResult.contents)
- return result.toString()
- } else {
- Log.v("myapp", "no module load handler registered")
- return "null"
- }
- } catch (e: Exception) {
- Log.v("myapp", "exception during internalOnModuleLoad: $e")
- return "null"
- }
- }
-
- /**
- * Called by node/v8 from its thread.
- */
- @Suppress("unused")
- private fun internalOnGetData(what: String): String? {
- Log.i("myapp", "internalOnGetData called for $what")
- val data = getDataHandler?.handleGetData(what) ?: return null
- return Base64.encodeToString(data, Base64.NO_WRAP)
- }
-
-
- fun notifyNative() {
- initializedLatch.await()
- notifyNative(internalNativePointer)
- }
-
- /**
- * Schedule Node.JS to be run.
- */
- fun evalSimpleJs(source: String): String {
- val latch = CountDownLatch(1)
- var result: String? = null
- scheduleNodeThread {
- result = evalJs(source, internalNativePointer)
- latch.countDown()
- }
- latch.await()
- return result ?: throw Exception("invariant failed")
- }
-
- fun evalNodeCode(source: String) {
- scheduleNodeThread {
- makeCallbackNative(source, internalNativePointer)
- }
- }
-
- /**
- * Send a message to node, calling global.__akono_onMessage.
- */
- fun sendMessage(message: String) {
- val encoded = Base64.encodeToString(message.toByteArray(), Base64.NO_WRAP)
- val source = """
- if (global.__akono_onMessage) {
- const msg = (new Buffer('$encoded', 'base64')).toString('ascii');
- global.__akono_onMessage(msg);
- } else {
- console.log("WARN: no __akono_onMessage defined");
- }
- """.trimIndent()
- evalNodeCode(source)
- }
-
- /**
- *
- */
- fun waitStopped(): Unit {
- Log.i("myapp", "waiting for stop")
- scheduleNodeThread {
- stopped = true
- }
- jniThread.join()
- return
- }
-
- /**
- * Register a message handler that is called when the JavaScript code
- * running in [runNodeJs] calls __akono_sendMessage
- *
- * Does not block.
- */
- fun setMessageHandler(handler: MessageHandler) {
- this.messageHandler = handler
- }
-
- fun setLoadModuleHandler(handler: LoadModuleHandler) {
- this.loadModuleHandler = handler
- }
-
- fun setGetDataHandler(handler: GetDataHandler) {
- this.getDataHandler = handler
- }
-
- @Override
- protected fun finalize() {
- destroyNative(internalNativePointer)
- }
-
- init {
- jniThread = thread {
- internalNativePointer = initNative(nodeArgv)
- initializedLatch.countDown()
- while (true) {
- runNode(internalNativePointer)
- while (true) {
- val w = workQueue.poll() ?: break
- w()
- }
- if (stopped) {
- break
- }
- }
- }
- }
-
- companion object {
- init {
- System.loadLibrary("akono-jni")
- }
- }
-
- interface MessageHandler {
- fun handleMessage(message: String)
- }
-
- interface LoadModuleHandler {
- fun loadModule(name: String, paths: Array<String>): ModuleResult?
- }
-
- interface GetDataHandler {
- fun handleGetData(what: String): ByteArray?
- }
-} \ No newline at end of file
diff --git a/library/src/main/java/akono/Library.kt b/library/src/main/java/akono/Library.kt
deleted file mode 100644
index 920648fd..00000000
--- a/library/src/main/java/akono/Library.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * This Kotlin source file was generated by the Gradle 'init' task.
- */
-package akono
-
-class Library {
- fun someLibraryMethod(): Boolean {
- return true
- }
-}
diff --git a/library/src/test/java/akono/LibraryTest.kt b/library/src/test/java/akono/LibraryTest.kt
deleted file mode 100644
index 1a16e7e6..00000000
--- a/library/src/test/java/akono/LibraryTest.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * This Kotlin source file was generated by the Gradle 'init' task.
- */
-package akono
-
-import kotlin.test.Test
-import kotlin.test.assertTrue
-import kotlin.test.assertEquals
-
-import akono.AkonoJni
-
-class LibraryTest {
- @Test fun testSomeLibraryMethod() {
- assertTrue(true)
- }
-}