diff options
author | Florian Dold <florian.dold@gmail.com> | 2019-12-10 23:38:24 +0100 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2019-12-10 23:38:24 +0100 |
commit | 91fbb65ed4e5dc843eb5b1c5d1bcb44a2f256967 (patch) | |
tree | 4c5ee6423518ada341dffebc96d94febfa0b9206 | |
parent | cb3eb410fbf79cb2bb9ddb969b771259ea9acf6e (diff) | |
download | akono-91fbb65ed4e5dc843eb5b1c5d1bcb44a2f256967.tar.gz akono-91fbb65ed4e5dc843eb5b1c5d1bcb44a2f256967.tar.bz2 akono-91fbb65ed4e5dc843eb5b1c5d1bcb44a2f256967.zip |
module loading
-rw-r--r-- | .gitmodules | 2 | ||||
-rw-r--r-- | .idea/dictionaries/dold.xml | 1 | ||||
-rw-r--r-- | akono/akono-akono.iml | 2 | ||||
-rw-r--r-- | akono/build.gradle.kts | 5 | ||||
-rw-r--r-- | akono/src/androidTest/java/akono/InstrumentedAkonoTests.kt | 35 | ||||
-rw-r--r-- | akono/src/main/cpp/akono-jni.cpp | 85 | ||||
-rw-r--r-- | akono/src/main/java/akono/AkonoJni.kt | 20 | ||||
m--------- | deps/android-node-v8 | 0 |
8 files changed, 93 insertions, 57 deletions
diff --git a/.gitmodules b/.gitmodules index c99a6ae7..56f61a59 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "deps/android-node-v8"] path = deps/android-node-v8 url = https://git.taler.net/android-node-v8.git - branch = androidbuild + branch = master diff --git a/.idea/dictionaries/dold.xml b/.idea/dictionaries/dold.xml index f383697a..4229f6a5 100644 --- a/.idea/dictionaries/dold.xml +++ b/.idea/dictionaries/dold.xml @@ -2,6 +2,7 @@ <dictionary name="dold"> <words> <w>akono</w> + <w>taler</w> </words> </dictionary> </component>
\ No newline at end of file diff --git a/akono/akono-akono.iml b/akono/akono-akono.iml index 7719671c..80bdb714 100644 --- a/akono/akono-akono.iml +++ b/akono/akono-akono.iml @@ -25,7 +25,7 @@ <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" /> <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" /> <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/build/generated/res/rs/debug;file://$MODULE_DIR$/build/generated/res/resValues/debug" /> - <option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="" /> + <option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug;file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" /> <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" /> <option name="PROJECT_TYPE" value="1" /> </configuration> diff --git a/akono/build.gradle.kts b/akono/build.gradle.kts index d5362832..3fb5e31b 100644 --- a/akono/build.gradle.kts +++ b/akono/build.gradle.kts @@ -21,7 +21,10 @@ android { ndk { // Tells Gradle to build outputs for the following ABIs and package // them into your APK. - abiFilters("armeabi-v7a"); + abiFilters("armeabi-v7a") + abiFilters("arm64-v8a") + abiFilters("x86") + abiFilters("x86_64") } externalNativeBuild { diff --git a/akono/src/androidTest/java/akono/InstrumentedAkonoTests.kt b/akono/src/androidTest/java/akono/InstrumentedAkonoTests.kt index beda5119..26fb2012 100644 --- a/akono/src/androidTest/java/akono/InstrumentedAkonoTests.kt +++ b/akono/src/androidTest/java/akono/InstrumentedAkonoTests.kt @@ -22,24 +22,6 @@ class SyncMessageHandler : AkonoJni.MessageHandler { } } - -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 @@ -47,6 +29,7 @@ public class InstrumentedAkonoTestOne { @Test fun myJsTest() { val ajni: AkonoJni = AkonoJni() + ajni.putModuleCode("a", "function foo() {}") assertEquals("2", ajni.evalSimpleJs("1+1")) assertEquals("36", ajni.evalSimpleJs("6*6")) assertEquals("42", ajni.evalSimpleJs("(()=>{let x = 42; return x;})()")) @@ -64,21 +47,13 @@ public class InstrumentedAkonoTestOne { 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("require('akono');") ajni.evalNodeCode("a = require('a');") - ajni.evalNodeCode("a.foo()") + //ajni.evalNodeCode("a.foo()") - val msg2 = myHandler.waitForMessage() + //val msg2 = myHandler.waitForMessage() - assertEquals("hello42", msg2) + //assertEquals("hello42", msg2) ajni.waitStopped() } diff --git a/akono/src/main/cpp/akono-jni.cpp b/akono/src/main/cpp/akono-jni.cpp index 1d0f7512..0fd05a7e 100644 --- a/akono/src/main/cpp/akono-jni.cpp +++ b/akono/src/main/cpp/akono-jni.cpp @@ -1,9 +1,27 @@ +/* + This file is part of GNU Taler + (C) 2019 GNUnet e.V. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + #include <sys/types.h> #include <sys/syscall.h> #include <cstring> +#include <map> #include <jni.h> #include <libplatform/libplatform.h> #include <v8.h> +#include <android/asset_manager.h> #define NODE_WANT_INTERNALS 1 // NOLINT(cppcoreguidelines-macro-usage) @@ -16,6 +34,9 @@ #include <node_binding.h> #include <node_native_module_env.h> + +void _register_akono(); + // Provide stubs so that libnode.so links properly namespace node { namespace native_module { @@ -33,10 +54,15 @@ namespace node { } } +/** + * Mapping from module name to a string with the module's code. + */ +std::map<std::string, char *> modmap; + static int pfd[2]; static pthread_t thr; -static const char *tag = "myapp"; +static const char *tag = "akono-jni.cpp"; static void *thread_func(void *) { @@ -54,9 +80,7 @@ static void mylog(const char *msg) { __android_log_write(ANDROID_LOG_DEBUG, tag, msg); } -int start_logger(const char *app_name) { - tag = app_name; - +int start_logger() { /* make stdout line-buffered and stderr unbuffered */ setvbuf(stdout, 0, _IOLBF, 0); setvbuf(stderr, 0, _IONBF, 0); @@ -139,12 +163,13 @@ public: jobject currentJniThiz = nullptr; NativeAkonoInstance() : globalContext() { + _register_akono(); loop = uv_default_loop(); uv_async_init(loop, &async_notify, notifyCb); async_notify.data = this; if (!logInitialized) { - start_logger("myapp"); + start_logger(); logInitialized = true; } @@ -165,7 +190,6 @@ public: node::ArrayBufferAllocator *allocator = node::CreateArrayBufferAllocator(); this->isolate = node::NewIsolate(allocator, uv_default_loop()); - v8::Isolate::Scope isolate_scope(isolate); v8::HandleScope handle_scope(isolate); @@ -208,9 +232,9 @@ public: v8::Local<v8::Object> global = context->Global(); - global->Set(v8::String::NewFromUtf8(isolate, "__akono_sendMessage", + global->Set(context, v8::String::NewFromUtf8(isolate, "__akono_sendMessage", v8::NewStringType::kNormal).ToLocalChecked(), - sendMessageFunction); + sendMessageFunction).Check(); } @@ -220,7 +244,7 @@ public: * @param env JNI env of the thread we're running in. */ void runNode() { - //printf("running node loop, tid=%llu\n", (unsigned long long) syscall(__NR_gettid)); + //printf("blup running node loop, tid=%llu\n", (unsigned long long) syscall(__NR_gettid)); v8::Locker locker(isolate); v8::Isolate::Scope isolate_scope(isolate); v8::HandleScope handle_scope(isolate); @@ -260,6 +284,7 @@ public: jstring evalJs(JNIEnv *env, jstring sourceString) { JStringValue jsv(env, sourceString); + v8::Locker locker(isolate); v8::Isolate::Scope isolate_scope(isolate); @@ -314,8 +339,9 @@ void notifyCb(uv_async_t *async) { } static void sendMessageCallback(const v8::FunctionCallbackInfo<v8::Value> &args) { - if (args.Length() < 1) return; v8::Isolate *isolate = args.GetIsolate(); + v8::Locker locker(isolate); + if (args.Length() < 1) return; v8::HandleScope scope(isolate); v8::Local<v8::Value> arg = args[0]; v8::String::Utf8Value value(isolate, arg); @@ -351,6 +377,34 @@ static void sendMessageCallback(const v8::FunctionCallbackInfo<v8::Value> &args) env->CallVoidMethod(myInstance->currentJniThiz, meth, jstr1, jstr2); } +static void dummy(const v8::FunctionCallbackInfo<v8::Value> &args) { + +} + +static void getModuleCode(const v8::FunctionCallbackInfo<v8::Value> &args) { + if (args.Length() < 1) return; + v8::Isolate *isolate = args.GetIsolate(); + v8::Locker locker(isolate); + v8::HandleScope scope(isolate); + v8::Local<v8::Value> arg = args[0]; + v8::String::Utf8Value value(isolate, arg); + + printf("handling request for module %s\n", *value); + + std::string modName(*value); + + char *code = modmap[modName]; + + if (!code) { + printf("module not found in modmap %s\n", *value); + return; + } + printf("found module in modmap %s\n", *value); + args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, code, + v8::NewStringType::kNormal).ToLocalChecked()); + +} + extern "C" JNIEXPORT jobject JNICALL Java_akono_AkonoJni_initNative(JNIEnv *env, jobject thiz) { NativeAkonoInstance *myInstance = new NativeAkonoInstance(); @@ -372,6 +426,16 @@ Java_akono_AkonoJni_evalJs(JNIEnv *env, jobject thiz, jstring sourceStr, jobject } extern "C" JNIEXPORT void JNICALL +Java_akono_AkonoJni_putModuleCodeNative(JNIEnv *env, jobject thiz, jstring modName, jstring modCode) { + mylog("in putModuleCodeNative"); + JStringValue cModName(env, modName); + JStringValue cModCode(env, modCode); + std::string cppModName(strdup(*cModName)); + modmap[cppModName] = strdup(*cModCode); + mylog("registered module"); +} + +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); @@ -398,6 +462,7 @@ void InitializeAkono(v8::Local<v8::Object> target, v8::Local<v8::Value> unused, v8::Local<v8::Context> context, void* priv) { + NODE_SET_METHOD(target, "getModuleCode", getModuleCode); } NODE_MODULE_CONTEXT_AWARE_INTERNAL(akono, InitializeAkono) diff --git a/akono/src/main/java/akono/AkonoJni.kt b/akono/src/main/java/akono/AkonoJni.kt index 6aecb3af..e5a10547 100644 --- a/akono/src/main/java/akono/AkonoJni.kt +++ b/akono/src/main/java/akono/AkonoJni.kt @@ -11,8 +11,6 @@ import kotlin.concurrent.thread typealias AkonoNativePointer = ByteBuffer -data class ModuleResult(val path: String, val contents: String) - private val TAG = "AkonoJni" class AkonoJni(vararg nodeArgv: String) { @@ -25,6 +23,7 @@ class AkonoJni(vararg nodeArgv: String) { private external fun runNode(p: AkonoNativePointer) private external fun makeCallbackNative(source: String, p: AkonoNativePointer) + private external fun putModuleCodeNative(key: String, source: String) private external fun destroyNative(b: AkonoNativePointer) private external fun initNative(nodeArgv: Array<out String>): AkonoNativePointer @@ -95,9 +94,6 @@ class AkonoJni(vararg nodeArgv: String) { evalNodeCode(source) } - /** - * - */ fun waitStopped(): Unit { Log.i(TAG, "waiting for stop") scheduleNodeThread { @@ -107,6 +103,11 @@ class AkonoJni(vararg nodeArgv: String) { return } + fun putModuleCode(modName: String, code: String) { + Log.v(TAG, "putting module code (kotlin)") + putModuleCodeNative(modName, code) + } + /** * Register a message handler that is called when the JavaScript code * running in [runNodeJs] calls __akono_sendMessage @@ -141,7 +142,6 @@ class AkonoJni(vararg nodeArgv: String) { } companion object { - init { System.loadLibrary("akono-jni") } @@ -150,12 +150,4 @@ class AkonoJni(vararg nodeArgv: String) { interface MessageHandler { fun handleMessage(message: String) } - - interface LoadModuleHandler { - fun loadModule(name: String, paths: Array<String>): ModuleResult? - } - - interface GetDataHandler { - fun handleGetData(what: String): ByteArray? - } } diff --git a/deps/android-node-v8 b/deps/android-node-v8 -Subproject 7c040c7d01621f0f704fd88481e8dd455247f04 +Subproject d0e8ef2e22f0f8126760019d104b8858daf7cfa |