diff --git a/src/android.cpp b/src/android.cpp index fd4c6200..615a8381 100644 --- a/src/android.cpp +++ b/src/android.cpp @@ -20,12 +20,71 @@ typedef union { void* venv; } UnionJNIEnvToVoid; +typedef unsigned short char16_t; + +class String8 { +public: + String8() { + mString = 0; + } + + ~String8() { + if (mString) { + free(mString); + } + } + + void set(const char16_t* o, size_t numChars) { + if (mString) { + free(mString); + } + mString = (char*) malloc(numChars + 1); + if (!mString) { + return; + } + for (size_t i = 0; i < numChars; i++) { + mString[i] = (char) o[i]; + } + mString[numChars] = '\0'; + } + + const char* string() { + return mString; + } +private: + char* mString; +}; + static UnionJNIEnvToVoid uenv; static jmethodID newProtectedSocketMethod = NULL; static jmethodID freeProtectedSocketMethod = NULL; static jclass clazz = NULL; -static const char *classPathName = "com/github/shadowsocks/Socket"; +static const char *classPathName = "com/github/shadowsocks/Daemon"; + +void Java_com_github_shadowsocks_daemon_exec(JNIEnv *env, jobject thiz, jobjectArray argv) { + + int argc = argv ? env->GetArrayLength(argv) : 0; + char **daemon_argv = NULL; + String8 tmp_8; + + if (argc > 0) { + daemon_argv = (char **)malloc((argc+1)*sizeof(char *)); + for (int i = 0; i < argc; ++i) { + jstring arg = reinterpret_cast(env->GetObjectArrayElement(argv, i)); + const jchar *str = env->GetStringCritical(arg, 0); + tmp_8.set(str, env->GetStringLength(arg)); + env->ReleaseStringCritical(arg, str); + daemon_argv[i] = strdup(tmp_8.string()); + } + daemon_argv[args] = NULL; + } + + int ret = main(argc, daemon_argv); + + for (init i = 0; i < argc; i++) free(daemon_argv[i]); + free(daemon_argv); +} /* * Register several native methods for one class. @@ -54,6 +113,16 @@ static int registerNativeMethods(JNIEnv* env, const char* className) return JNI_FALSE; } + JNINativeMethod methods[] = { + { "exec", "([Ljava/lang/String;)V", + (void*) Java_com_github_shadowsocks_daemon_exec } + }; + + if (env->RegisterNatives(clazz, methods, 1) < 0) { + LOGE("RegisterNatives failed for '%s'", className); + return JNI_FALSE; + } + return JNI_TRUE; }