http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/547da26a/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp ---------------------------------------------------------------------- diff --git a/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp index 472727f..2d19683 100644 --- a/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp +++ b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp @@ -23,199 +23,552 @@ #include <android/base/string/string_utils.h> #include <core/config/core_environment.h> #include <android/jsengine/multiprocess/ExtendJSApi.h> +#include <core/api/WeexJSCoreApi.h> +#include <dlfcn.h> const char *s_cacheDir; bool s_start_pie = true; static IPCSender *sSender; -static std::unique_ptr <IPCHandler> sHandler; -static std::unique_ptr <WeexJSConnection> sConnection; - +static std::unique_ptr<IPCHandler> sHandler; +static std::unique_ptr<WeexJSConnection> sConnection; +static WEEX_CORE_JS_SERVER_API_FUNCTIONS *js_server_api_functions = nullptr; +bool g_use_single_process = true; namespace WeexCore { -void WeexProxy::reset() { - sConnection.reset(); - sHandler.reset(); -} - -jint WeexProxy::doInitFramework(JNIEnv *env, jobject object, - jstring script, jobject params, - jstring cacheDir, jboolean pieSupport) { - const char *cache = env->GetStringUTFChars( - reinterpret_cast<jstring>(cacheDir), nullptr); - if (strlen(cache) > 0) { - s_cacheDir = cache; - } - s_start_pie = pieSupport; - return doInitFramework(env, jThis, script, params); -} - -jint WeexProxy::doInitFramework(JNIEnv *env, - jobject object, - jstring script, - jobject params) { - bool reinit = false; - startInitFrameWork: - try { - sHandler = std::move(createIPCHandler()); - sConnection.reset(new WeexJSConnection()); - sSender = sConnection->start(sHandler.get(), reinit); - if (sSender == nullptr) { - LOGE("JSFreamwork init start sender is null"); - if (!reinit) { - reinit = true; - goto startInitFrameWork; - } else { - return false; - } - } else { - // initHandler(sHandler.get()); - ExtendJSApi *pExtensionJSApi = new ExtendJSApi(); - Bridge_Impl_Android::getInstance()->setGlobalRef(jThis); - pExtensionJSApi->initFunction(sHandler.get()); - - // using base::debug::TraceEvent; - // TraceEvent::StartATrace(env); - std::unique_ptr <IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::INITFRAMEWORK)); - initFromParam(env, script, params, serializer.get()); - std::unique_ptr <IPCBuffer> buffer = serializer->finish(); - std::unique_ptr <IPCResult> result = sSender->send(buffer.get()); - if (result->getType() != IPCType::INT32) { - LOGE("initFramework Unexpected result type"); - reportException("", "initFramework", - "error, initFramework Unexpected result type"); + void WeexProxy::reset() { + sConnection.reset(); + sHandler.reset(); + } + + static WeexString *genWeexString(const uint16_t *str, size_t length) { + size_t byteSize = length * sizeof(uint16_t); + auto *string = (WeexString *) malloc(byteSize + sizeof(WeexString)); + if (string == nullptr) + return nullptr; + + memset(string, 0, byteSize + sizeof(WeexString)); + string->length = length; + memcpy(string->content, str, byteSize); + return string; + } + + static WeexByteArray *genWeexByteArray(const char *str, size_t strLen) { + auto *ret = (WeexByteArray *) malloc(strLen + sizeof(WeexByteArray)); + + if (ret == nullptr) + return nullptr; + + memset(ret, 0, strLen + sizeof(WeexByteArray)); + + ret->length = strLen; + memcpy(ret->content, str, strLen); + ret->content[strLen] = '\0'; + return ret; + } + + static INIT_FRAMEWORK_PARAMS * + genInitFrameworkParams(const char *type, const char *value) { + auto *init_framework_params = (INIT_FRAMEWORK_PARAMS *) malloc( + sizeof(INIT_FRAMEWORK_PARAMS)); + + if (init_framework_params == nullptr) + return nullptr; + + memset(init_framework_params, 0, sizeof(INIT_FRAMEWORK_PARAMS)); + + init_framework_params->type = genWeexByteArray(type, strlen(type)); + init_framework_params->value = genWeexByteArray(value, strlen(value)); + + // LOGE("genInitFrameworkParams and type is %s and length is %d", init_framework_params->type->content, + // init_framework_params->type->length); + // LOGE("genInitFrameworkParams and value is %s and length is %d", init_framework_params->value->content, + // init_framework_params->value->length); + + return init_framework_params; + } + + static WeexString *jstring2WeexString(JNIEnv *env, jstring fromJString) { + if (fromJString != nullptr) { + ScopedJString scopedString(env, fromJString); + return genWeexString(scopedString.getChars(), scopedString.getCharsLength()); + } else { + uint16_t tmp = 0; + return genWeexString(&tmp, 0); + } + } + + static VALUE_WITH_TYPE *getValueWithTypePtr() { + auto *param = (VALUE_WITH_TYPE *) malloc(sizeof(VALUE_WITH_TYPE)); + if (param == nullptr) + return nullptr; + + memset(param, 0, sizeof(VALUE_WITH_TYPE)); + + return param; + } + + jint WeexProxy::doInitFramework(JNIEnv *env, jobject object, + jstring script, jobject params, + jstring cacheDir, jboolean pieSupport) { + const char *cache = env->GetStringUTFChars( + reinterpret_cast<jstring>(cacheDir), nullptr); + if (strlen(cache) > 0) { + s_cacheDir = cache; + } + s_start_pie = pieSupport; + return doInitFramework(env, jThis, script, params); + } + + jint + WeexProxy::initFrameworkInMultiProcess(JNIEnv *env, jstring script, IPCSerializer *serializer) { + bool reinit = false; + startInitFrameWork: + try { + sHandler = std::move(createIPCHandler()); + sConnection.reset(new WeexJSConnection()); + sSender = sConnection->start(sHandler.get(), reinit); + if (sSender == nullptr) { + LOGE("JSFreamwork init start sender is null"); + if (!reinit) { + reinit = true; + goto startInitFrameWork; + } else { + return false; + } + } else { + // initHandler(sHandler.get()); + ExtendJSApi *pExtensionJSApi = new ExtendJSApi(); + + pExtensionJSApi->initFunction(sHandler.get()); + + // using base::debug::TraceEvent; + // TraceEvent::StartATrace(env); + + serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::INITFRAMEWORK)); + + std::unique_ptr<IPCBuffer> buffer = serializer->finish(); + std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); + if (result->getType() != IPCType::INT32) { + LOGE("initFramework Unexpected result type"); + reportException("", "initFramework", + "error, initFramework Unexpected result type"); + return false; + } + return result->get<jint>(); + } + } catch (IPCException &e) { + LOGE("WeexProxy catchï¼%s", e.msg()); + if (!reinit) { + reinit = true; + goto startInitFrameWork; + } else { + LOGE("%s", e.msg()); + reportException("", "initFramework", e.msg()); + return false; + } + } + } + + jint WeexProxy::doInitFramework(JNIEnv *env, + jobject object, + jstring script, + jobject params) { + + Bridge_Impl_Android::getInstance()->setGlobalRef(jThis); + std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); + const std::vector<INIT_FRAMEWORK_PARAMS *> &initFrameworkParams = initFromParam(env, script, + params, + serializer.get()); + LOGE("doInitFramework is running"); + if (g_use_single_process) { + if (initFrameworkInSingleProcess(env, script, initFrameworkParams)) { + //reportNativeInitStatus("-1011", "init Single Process Success"); + return true; + } + + if (initFrameworkInMultiProcess(env, script, serializer.get())) { + return true; + } + } else { + if (initFrameworkInMultiProcess(env, script, serializer.get())) { + return true; + } + + if (initFrameworkInSingleProcess(env, script, initFrameworkParams)) { + reportNativeInitStatus("-1011", "init Single Process Success"); + return true; + } + } + reportNativeInitStatus("-1010", "init Failed"); return false; - } - return result->get<jint>(); - } - } catch (IPCException &e) { - LOGE("WeexProxy catchï¼%s", e.msg()); - if (!reinit) { - reinit = true; - goto startInitFrameWork; - } else { - LOGE("%s", e.msg()); - reportException("", "initFramework", e.msg()); - return false; - } - } -} - -bool WeexProxy::execJSService(JNIEnv *env, jobject object, jstring script) { - if (!sSender) { - LOGE("have not connected to a js server"); - return false; - } - try { - std::unique_ptr <IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJSSERVICE)); - addString(env, serializer.get(), script); - std::unique_ptr <IPCBuffer> buffer = serializer->finish(); - std::unique_ptr <IPCResult> result = sSender->send(buffer.get()); - if (result->getType() != IPCType::INT32) { - LOGE("execJSService Unexpected result type"); - return false; - } - return result->get<jint>(); - } catch (IPCException &e) { - LOGE("%s", e.msg()); - return false; - } - return true; -} - -bool WeexProxy::execJS(JNIEnv *env, - jobject jthis, - jstring jinstanceid, - jstring jnamespace, - jstring jfunction, - jobjectArray jargs) { - std::string mMessage = ""; - if (!sSender) { - LOGE("have not connected to a js server"); - return false; - } - int length = 0; - if (jargs != NULL) { - length = env->GetArrayLength(jargs); - } - try { - std::unique_ptr <IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJS)); - addString(env, serializer.get(), jinstanceid); - if (jnamespace) { - addString(env, serializer.get(), jnamespace); - } else { - uint16_t tmp = 0; - serializer->add(&tmp, 0); - } - addString(env, serializer.get(), jfunction); - - for (int i = 0; i < length; i++) { - jobject jArg = env->GetObjectArrayElement(jargs, i); - - jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I"); - jint jTypeInt = env->GetIntField(jArg, jTypeId); - - jfieldID jDataId = env->GetFieldID(jWXJSObject, - "data", "Ljava/lang/Object;"); - jobject jDataObj = env->GetObjectField(jArg, jDataId); - if (jTypeInt == 1) { - if (jDoubleValueMethodId == NULL) { - jclass jDoubleClazz = env->FindClass("java/lang/Double"); - jDoubleValueMethodId = env->GetMethodID(jDoubleClazz, - "doubleValue", "()D"); - env->DeleteLocalRef(jDoubleClazz); - } - jdouble jDoubleObj = env->CallDoubleMethod(jDataObj, - jDoubleValueMethodId); - serializer->add(jDoubleObj); - - } else if (jTypeInt == 2) { - jstring jDataStr = (jstring) jDataObj; - addString(env, serializer.get(), jDataStr); - } else if (jTypeInt == 3) { - jstring jDataStr = (jstring) jDataObj; - addJSONString(env, serializer.get(), jDataStr); - } else { - serializer->addJSUndefined(); - } - env->DeleteLocalRef(jDataObj); - env->DeleteLocalRef(jArg); - } - - std::unique_ptr <IPCBuffer> buffer = serializer->finish(); - - std::unique_ptr <IPCResult> result = sSender->send(buffer.get()); - - if (result->getType() != IPCType::INT32) { - LOGE("execJS Unexpected result type"); - return false; - } - - return result->get<jint>(); - } catch (IPCException &e) { - LOGE("%s", e.msg()); - // report crash here - WeexProxy::reportServerCrash(jinstanceid); - return false; - } - return true; -} - - -void WeexProxy::initFromParam(JNIEnv *env, - jstring script, - jobject params, - IPCSerializer *serializer) { - { - ScopedJString scopedString(env, script); - const jchar *chars = scopedString.getChars(); - int charLength = scopedString.getCharsLength(); - serializer->add(chars, charLength); - } + + } + + bool WeexProxy::execJSService(JNIEnv *env, jobject object, jstring script) { + if (!sSender && !js_server_api_functions) { + LOGE("have not connected to a js server"); + return false; + } + + if (js_server_api_functions != nullptr) { + ScopedJStringUTF8 source(env, script); + js_server_api_functions->funcExeJsService(source.getChars()); + return true; + } else { + try { + std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); + serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJSSERVICE)); + addString(env, serializer.get(), script); + std::unique_ptr<IPCBuffer> buffer = serializer->finish(); + std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); + if (result->getType() != IPCType::INT32) { + LOGE("execJSService Unexpected result type"); + return false; + } + return result->get<jint>(); + } catch (IPCException &e) { + LOGE("%s", e.msg()); + return false; + } + return true; + } + } + + bool WeexProxy::execJS(JNIEnv *env, + jobject jthis, + jstring jinstanceid, + jstring jnamespace, + jstring jfunction, + jobjectArray jargs) { + std::string mMessage = ""; + if (!sSender && !js_server_api_functions) { + LOGE("have not connected to a js server"); + return false; + } + if (jfunction == nullptr || jinstanceid == nullptr) { + LOGE("native_execJS function is NULL"); + return false; + } + int length = 0; + if (jargs != nullptr) { + length = env->GetArrayLength(jargs); + } + try { + std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); + std::vector<VALUE_WITH_TYPE *> params; + if (js_server_api_functions == nullptr) { + serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJS)); + addString(env, serializer.get(), jinstanceid); + if (jnamespace) + addString(env, serializer.get(), jnamespace); + else { + uint16_t tmp = 0; + serializer->add(&tmp, 0); + } + addString(env, serializer.get(), jfunction); + } + + for (int i = 0; i < length; i++) { + VALUE_WITH_TYPE *param = nullptr; + + if (js_server_api_functions != nullptr) { + param = getValueWithTypePtr(); + if (param == nullptr) + return false; + } + + jobject jArg = env->GetObjectArrayElement(jargs, i); + + jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I"); + jint jTypeInt = env->GetIntField(jArg, jTypeId); + + jfieldID jDataId = env->GetFieldID(jWXJSObject, + "data", "Ljava/lang/Object;"); + jobject jDataObj = env->GetObjectField(jArg, jDataId); + if (jTypeInt == 1) { + if (jDoubleValueMethodId == NULL) { + jclass jDoubleClazz = env->FindClass("java/lang/Double"); + jDoubleValueMethodId = env->GetMethodID(jDoubleClazz, + "doubleValue", "()D"); + env->DeleteLocalRef(jDoubleClazz); + } + jdouble jDoubleObj = env->CallDoubleMethod(jDataObj, + jDoubleValueMethodId); + if (js_server_api_functions != nullptr) { + param->type = ParamsType::DOUBLE; + param->value.doubleValue = jDoubleObj; + } else { + serializer->add(jDoubleObj); + } + + } else if (jTypeInt == 2) { + jstring jDataStr = (jstring) jDataObj; + if (js_server_api_functions != nullptr) { + param->type = ParamsType::STRING; + param->value.string = jstring2WeexString(env, jDataStr); + } else { + addString(env, serializer.get(), jDataStr); + } + } else if (jTypeInt == 3) { + jstring jDataStr = (jstring) jDataObj; + if (js_server_api_functions != nullptr) { + param->type = ParamsType::JSONSTRING; + param->value.string = jstring2WeexString(env, jDataStr); + } else { + addJSONString(env, serializer.get(), jDataStr); + } + } else { + if (js_server_api_functions != nullptr) { + param->type = ParamsType::JSUNDEFINED; + } else { + serializer->addJSUndefined(); + } + } + if (param != nullptr) + params.push_back(param); + env->DeleteLocalRef(jDataObj); + env->DeleteLocalRef(jArg); + } + + if (js_server_api_functions != nullptr) { + + ScopedJStringUTF8 idChar(env, jinstanceid); + const char *name; + if (jnamespace) { + ScopedJStringUTF8 nameSpaceChar(env, jnamespace); + name = nameSpaceChar.getChars(); + } else { + name = nullptr; + } + ScopedJStringUTF8 funcChar(env, jfunction); + + int i = js_server_api_functions->funcExeJS(idChar.getChars(), + name, + funcChar.getChars(), + params); + for (auto ¶m : params) { + if (param->type == ParamsType::STRING || + param->type == ParamsType::JSONSTRING) { + free(param->value.string); + } + free(param); + } + return static_cast<bool>(i); + } else { + std::unique_ptr<IPCBuffer> buffer = serializer->finish(); + + std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); + if (result->getType() != IPCType::INT32) { + LOGE("execJS Unexpected result type"); + return false; + } + + return result->get<jint>(); + } + + + } catch (IPCException &e) { + LOGE("%s", e.msg()); + // report crash here + WeexProxy::reportServerCrash(jinstanceid); + return false; + } + return true; + } + + static std::string findPath() { + std::string executablePath = ""; + unsigned long target = reinterpret_cast<unsigned long>(__builtin_return_address(0)); + FILE *f = fopen("/proc/self/maps", "r"); + if (!f) { + return ""; + } + char buffer[256]; + char *line; + while ((line = fgets(buffer, 256, f))) { + char *end; + unsigned long val; + errno = 0; + val = strtoul(line, &end, 16); + if (errno) + continue; + if (val > target) + continue; + end += 1; + errno = 0; + val = strtoul(end, &end, 16); + if (errno) + continue; + if (val > target) { + char *s = strstr(end, "/"); + if (s != nullptr) + executablePath.assign(s); + std::size_t found = executablePath.rfind('/'); + if (found != std::string::npos) { + executablePath = executablePath.substr(0, found); + } + } + if (!executablePath.empty()) { + break; + } + } + fclose(f); + return executablePath; + } + + static WEEX_CORE_JS_API_FUNCTIONS *getWeexCoreApiFunctions() { + WEEX_CORE_JS_API_FUNCTIONS tempFunctions = { + _setJSVersion, + _reportException, + _callNative, + _callNativeModule, + _callNativeComponent, + _callAddElement, + _setTimeout, + _callNativeLog, + _callCreateBody, + _callUpdateFinish, + _callCreateFinish, + _callRefreshFinish, + _callUpdateAttrs, + _callUpdateStyle, + _callRemoveElement, + _callMoveElement, + _callAddEvent, + _callRemoveEvent, + _setInterval, + _clearInterval, + _callGCanvasLinkNative, + _t3dLinkNative, + callHandlePostMessage, + callDIspatchMessage + }; + + auto *functions = (WEEX_CORE_JS_API_FUNCTIONS *) malloc(sizeof(WEEX_CORE_JS_API_FUNCTIONS)); + + if (!functions) { + return nullptr; + } + + memset(functions, 0, sizeof(WEEX_CORE_JS_API_FUNCTIONS)); + memcpy(functions, &tempFunctions, sizeof(WEEX_CORE_JS_API_FUNCTIONS)); + + return functions; + } + + typedef WEEX_CORE_JS_SERVER_API_FUNCTIONS *(*InitMethodFunc)( + WEEX_CORE_JS_API_FUNCTIONS *functions); + + jint + WeexProxy::initFrameworkInSingleProcess(JNIEnv *env, jstring script, + std::vector<INIT_FRAMEWORK_PARAMS *> initFrameworkParams) { + + std::string soPath = ""; + + // ----------------------------------------------- + // use find path to get lib path + // use set path is better idea, should change in future + soPath = findPath(); + + std::string::size_type pos = std::string::npos; + LOGE("find so path: %s", soPath.c_str()); + // dynamic deploy + if (!soPath.empty() && soPath.find(".maindex") != std::string::npos) { + std::string libs[] = {"/opt", "/oat/arm"}; + auto libsCount = sizeof(libs) / sizeof(std::string); + for (int i = 0; i < libsCount; ++i) { + auto lib = libs[i]; + pos = soPath.find(lib); + if (pos != std::string::npos) { + soPath.replace(pos, lib.length(), "/lib"); + break; + } + } + soPath += "/libweexjss.so"; + } else { + soPath += "libweexjss.so"; + } + // ------------------------------------------------- + // ------------------------------------------------- + if (access(soPath.c_str(), 00) != 0) { + LOGE("so path: %s is not exsist, use full package lib", soPath.c_str()); + const char *error = soPath.c_str(); + soPath = s_cacheDir; + std::string lib = "/cache"; + if ((pos = soPath.find(lib)) != std::string::npos) { + soPath.replace(pos, lib.length(), "/lib"); + } + soPath += "/libweexjss.so"; + if (access(soPath.c_str(), 00) != 0) { + LOGE("so path: %s is not exsist", soPath.c_str()); + //reportNativeInitStatus("-1004", error); + //return false; + //use libweexjss.so directly + soPath = "libweexjss.so"; + } + } + + LOGE("final executablePath:%s", soPath.c_str()); + + void *handle = dlopen(soPath.c_str(), RTLD_NOW); + if (!handle) { + const char *error = dlerror(); + LOGE("load libweexjss.so failed,error=%s\n", error); +// reportNativeInitStatus("-1005", error); + // try again use current path + dlclose(handle); + return false; + } + + //clear dlopen error message + dlerror(); + + LOGE("dlopen so and call function"); + auto initMethod = (InitMethodFunc) dlsym(handle, "exchangeMethod"); + if (!initMethod) { + const char *error = dlerror(); + LOGE("load External_InitFrameWork failed,error=%s\n", error); +// reportNativeInitStatus("-1006", error); + dlclose(handle); + return false; + } + + //clear dlopen error message + dlerror(); + + WEEX_CORE_JS_API_FUNCTIONS *pFunctions = getWeexCoreApiFunctions(); + + js_server_api_functions = initMethod(pFunctions); + + if (js_server_api_functions != nullptr) { + js_server_api_functions->funcInitFramework(env->GetStringUTFChars(script, nullptr), + std::move(initFrameworkParams)); + return true; + } else { + dlclose(handle); + free(pFunctions); + free(js_server_api_functions); + //reportNativeInitStatus("-1007", "Init Functions failed"); + return false; + } + } + + + std::vector<INIT_FRAMEWORK_PARAMS *> WeexProxy::initFromParam(JNIEnv *env, + jstring script, + jobject params, + IPCSerializer *serializer) { + { + ScopedJString scopedString(env, script); + const jchar *chars = scopedString.getChars(); + int charLength = scopedString.getCharsLength(); + serializer->add(chars, charLength); + } + LOGE("initFromParam is running "); + std::vector<INIT_FRAMEWORK_PARAMS *> initFrameworkParams; + #define ADDSTRING(name) \ { \ const char* myname = #name; \ @@ -224,732 +577,977 @@ void WeexProxy::initFromParam(JNIEnv *env, const char* chars = scopedString.getChars(); \ int charLength = strlen(chars); \ serializer->add(chars, charLength); \ + initFrameworkParams.push_back(genInitFrameworkParams(myname,chars));\ + } + jclass c_params = env->GetObjectClass(params); + + jmethodID m_platform = env->GetMethodID(c_params, + "getPlatform", + "()Ljava/lang/String;"); + jobject platform = env->CallObjectMethod(params, m_platform); + if (!WXCoreEnvironment::getInstance()->SetPlatform( + jString2StrFast(env, reinterpret_cast<jstring &>(platform)))) { + LOGD("setPlatform"); + } + ADDSTRING(platform); + + + jmethodID m_use_single_process = env->GetMethodID(c_params, "getUseSingleProcess", + "()Ljava/lang/String;"); + if (m_use_single_process == nullptr) { + LOGE("getUseSingleProcess method is missing"); + } else { + jobject j_use_single_process = env->CallObjectMethod(params, m_use_single_process); + const char *use_single_process = env->GetStringUTFChars( + (jstring) (j_use_single_process), + nullptr); + LOGE("g_use_single_process is %s ", use_single_process); + g_use_single_process = strstr(use_single_process, "true") != nullptr; + } + + jmethodID m_osVersion = env->GetMethodID( + c_params, "getOsVersion", "()Ljava/lang/String;"); + jobject osVersion = env->CallObjectMethod(params, m_osVersion); + ADDSTRING(osVersion); + + // use param ti get cacheDir + jmethodID m_cacheMethod = env->GetMethodID( + c_params, "getCacheDir", "()Ljava/lang/String;"); + if (m_cacheMethod != NULL) { + jobject cacheDir = env->CallObjectMethod(params, m_cacheMethod); + if (cacheDir != NULL) { + ADDSTRING(cacheDir); + } + } + + jmethodID m_appVersion = env->GetMethodID( + c_params, "getAppVersion", "()Ljava/lang/String;"); + jobject appVersion = env->CallObjectMethod(params, m_appVersion); + ADDSTRING(appVersion); + + jmethodID m_weexVersion = env->GetMethodID( + c_params, "getWeexVersion", "()Ljava/lang/String;"); + jobject weexVersion = env->CallObjectMethod(params, m_weexVersion); + ADDSTRING(weexVersion); + + jmethodID m_deviceModel = env->GetMethodID( + c_params, "getDeviceModel", "()Ljava/lang/String;"); + jobject deviceModel = env->CallObjectMethod(params, m_deviceModel); + ADDSTRING(deviceModel); + + jmethodID m_appName = env->GetMethodID( + c_params, "getAppName", "()Ljava/lang/String;"); + jobject appName = env->CallObjectMethod(params, m_appName); + ADDSTRING(appName); + + jmethodID m_deviceWidth = env->GetMethodID( + c_params, "getDeviceWidth", "()Ljava/lang/String;"); + jobject deviceWidth = env->CallObjectMethod(params, m_deviceWidth); + if (!WXCoreEnvironment::getInstance()->SetDeviceWidth( + jString2StrFast(env, reinterpret_cast<jstring &>(deviceWidth)))) { + LOGD("setDeviceWidth"); + } + ADDSTRING(deviceWidth); + + jmethodID m_deviceHeight = env->GetMethodID( + c_params, "getDeviceHeight", "()Ljava/lang/String;"); + jobject deviceHeight = env->CallObjectMethod(params, m_deviceHeight); + if (!WXCoreEnvironment::getInstance()->SetDeviceHeight( + jString2StrFast(env, reinterpret_cast<jstring &>(deviceHeight)))) { + LOGD("setDeviceHeight"); + } + ADDSTRING(deviceHeight); + + jmethodID m_options = env->GetMethodID( + c_params, "getOptions", "()Ljava/lang/Object;"); + jobject options = env->CallObjectMethod(params, m_options); + jclass jmapclass = env->FindClass("java/util/HashMap"); + jmethodID jkeysetmid = env->GetMethodID(jmapclass, + "keySet", + "()Ljava/util/Set;"); + jmethodID jgetmid = env->GetMethodID( + jmapclass, + "get", + "(Ljava/lang/Object;)Ljava/lang/Object;"); + jobject jsetkey = env->CallObjectMethod(options, jkeysetmid); + jclass jsetclass = env->FindClass("java/util/Set"); + jmethodID jtoArraymid = env->GetMethodID(jsetclass, + "toArray", + "()[Ljava/lang/Object;"); + jobjectArray jobjArray = + (jobjectArray) env->CallObjectMethod(jsetkey, jtoArraymid); + env->DeleteLocalRef(jsetkey); + if (jobjArray != NULL) { + jsize arraysize = env->GetArrayLength(jobjArray); + for (int i = 0; i < arraysize; i++) { + jstring jkey = (jstring) env->GetObjectArrayElement(jobjArray, i); + jstring jvalue = (jstring) env->CallObjectMethod(options, jgetmid, jkey); + + if (jkey != NULL) { + // const char* c_key = env->GetStringUTFChars(jkey, NULL); + // addString(vm, WXEnvironment, c_key, jString2String(env, jvalue)); + // serializer->add(c_key, strlen(c_key)); + // env->DeleteLocalRef(jkey); + // if (jvalue != NULL) { + // env->DeleteLocalRef(jvalue); + // } + ScopedJStringUTF8 c_key(env, jkey); + ScopedJStringUTF8 c_value(env, jvalue); + const char *c_key_chars = c_key.getChars(); + int c_key_len = strlen(c_key_chars); + const char *c_value_chars = c_value.getChars(); + int c_value_len = strlen(c_value_chars); + serializer->add(c_key_chars, c_key_len); + serializer->add(c_value_chars, c_value_len); + WXCoreEnvironment::getInstance()->AddOption(jString2Str(env, jkey), + jString2Str(env, jvalue)); + } + } + env->DeleteLocalRef(jobjArray); + } + env->DeleteLocalRef(options); + return initFrameworkParams; + } + + void + WeexProxy::reportException(const char *instanceID, + const char *func, + const char *exception_string) { + _reportException(instanceID, func, exception_string); +// JNIEnv *env = getJNIEnv(); +// jstring jExceptionString = env->NewStringUTF(exception_string); +// jstring jInstanceId = env->NewStringUTF(instanceID); +// jstring jFunc = env->NewStringUTF(func); +// jmethodID tempMethodId = env->GetMethodID( +// jBridgeClazz, +// "reportJSException", +// "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); +// env->CallVoidMethod(jThis, +// tempMethodId, +// jInstanceId, +// jFunc, +// jExceptionString); +// env->DeleteLocalRef(jExceptionString); +// env->DeleteLocalRef(jInstanceId); +// env->DeleteLocalRef(jFunc); + } + + void WeexProxy::reportServerCrash(jstring jinstanceid) { + JNIEnv *env = getJNIEnv(); + jmethodID reportMethodId; + jstring crashFile; + std::string crashFileStr; + reportMethodId = env->GetMethodID(jBridgeClazz, + "reportServerCrash", + "(Ljava/lang/String;Ljava/lang/String;)V"); + if (!reportMethodId) + goto no_method; + + crashFileStr.assign("/jsserver_crash/jsserver_crash_info.log"); + + crashFile = env->NewStringUTF(crashFileStr.c_str()); + env->CallVoidMethod(jThis, reportMethodId, jinstanceid, crashFile); + env->DeleteLocalRef(crashFile); + no_method: + env->ExceptionClear(); + } + + void WeexProxy::reportNativeInitStatus(const char *statusCode, const char *errorMsg) { + JNIEnv *env = getJNIEnv(); + jmethodID reportMethodId; + jstring errorCodeString = env->NewStringUTF(statusCode); + + std::string m_errorMsgString = "useSingleProcess is "; + m_errorMsgString.append(g_use_single_process ? "true" : "false"); + m_errorMsgString.append(" And Error Msg is "); + m_errorMsgString.append(errorMsg); + + + LOGE("reportNativeInitStatus error msg is %s ", m_errorMsgString.c_str()); + + jstring errorMsgString = env->NewStringUTF(m_errorMsgString.c_str()); + reportMethodId = env->GetMethodID(jBridgeClazz, + "reportNativeInitStatus", + "(Ljava/lang/String;Ljava/lang/String;)V"); + + + if (!reportMethodId) + goto no_method; + + + env->CallVoidMethod(jThis, reportMethodId, errorCodeString, errorMsgString); + + no_method: + env->DeleteLocalRef(errorCodeString); + env->DeleteLocalRef(errorMsgString); + env->ExceptionClear(); + } + + const char *WeexProxy::getCacheDir(JNIEnv *env) { + jclass activityThreadCls, applicationCls, fileCls; + jobject applicationObj, fileObj, pathStringObj; + jmethodID currentApplicationMethodId, + getCacheDirMethodId, + getAbsolutePathMethodId; + static std::string storage; + const char *tmp; + const char *ret = nullptr; + if (!storage.empty()) { + ret = storage.c_str(); + goto no_empty; + } + activityThreadCls = env->FindClass("android/app/ActivityThread"); + if (!activityThreadCls || env->ExceptionOccurred()) { + goto no_class; + } + currentApplicationMethodId = env->GetStaticMethodID( + activityThreadCls, + "currentApplication", + "()Landroid/app/Application;"); + if (!currentApplicationMethodId || env->ExceptionOccurred()) { + goto no_currentapplication_method; + } + applicationObj = env->CallStaticObjectMethod(activityThreadCls, + currentApplicationMethodId, + nullptr); + if (!applicationObj || env->ExceptionOccurred()) { + goto no_application; + } + applicationCls = env->GetObjectClass(applicationObj); + getCacheDirMethodId = env->GetMethodID(applicationCls, + "getCacheDir", + "()Ljava/io/File;"); + if (!getCacheDirMethodId || env->ExceptionOccurred()) { + goto no_getcachedir_method; + } + fileObj = env->CallObjectMethod(applicationObj, getCacheDirMethodId, nullptr); + if (!fileObj || env->ExceptionOccurred()) { + goto no_file_obj; + } + fileCls = env->GetObjectClass(fileObj); + getAbsolutePathMethodId = env->GetMethodID(fileCls, + "getAbsolutePath", + "()Ljava/lang/String;"); + if (!getAbsolutePathMethodId || env->ExceptionOccurred()) { + goto no_getabsolutepath_method; + } + pathStringObj = env->CallObjectMethod(fileObj, + getAbsolutePathMethodId, + nullptr); + if (!pathStringObj || env->ExceptionOccurred()) { + goto no_path_string; + } + tmp = env->GetStringUTFChars(reinterpret_cast<jstring>(pathStringObj), + nullptr); + storage.assign(tmp); + env->ReleaseStringUTFChars(reinterpret_cast<jstring>(pathStringObj), + tmp); + ret = storage.c_str(); + no_path_string: + no_getabsolutepath_method: + env->DeleteLocalRef(fileCls); + env->DeleteLocalRef(fileObj); + no_file_obj: + no_getcachedir_method: + env->DeleteLocalRef(applicationCls); + env->DeleteLocalRef(applicationObj); + no_application: + no_currentapplication_method: + env->DeleteLocalRef(activityThreadCls); + no_class: + env->ExceptionDescribe(); + env->ExceptionClear(); + no_empty: + return ret; + } + + void WeexProxy::setCacheDir(JNIEnv *env) { + s_cacheDir = getCacheDir(env); + } + + jbyteArray WeexProxy::execJSWithResult(JNIEnv *env, jobject jthis, + jstring jinstanceid, + jstring jnamespace, + jstring jfunction, + jobjectArray jargs) { + if (!sSender && !js_server_api_functions) { + LOGE("have not connected to a js server"); + return NULL; + } + if (jfunction == NULL || jinstanceid == NULL) { + LOGE("native_execJS function is NULL"); + return NULL; + } + + int length = 0; + if (jargs != NULL) { + length = env->GetArrayLength(jargs); + } + try { + std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); + std::vector<VALUE_WITH_TYPE *> params; + if (js_server_api_functions == nullptr) { + serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJSWITHRESULT)); + addString(env, serializer.get(), jinstanceid); + if (jnamespace) + addString(env, serializer.get(), jnamespace); + else { + uint16_t tmp = 0; + serializer->add(&tmp, 0); + } + addString(env, serializer.get(), jfunction); + } + + for (int i = 0; i < length; i++) { + VALUE_WITH_TYPE *param = nullptr; + + if (js_server_api_functions != nullptr) { + param = getValueWithTypePtr(); + if (param == nullptr) + return false; + } + + jobject jArg = env->GetObjectArrayElement(jargs, i); + + jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I"); + jint jTypeInt = env->GetIntField(jArg, jTypeId); + + jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;"); + jobject jDataObj = env->GetObjectField(jArg, jDataId); + if (jTypeInt == 1) { + if (jDoubleValueMethodId == NULL) { + jclass jDoubleClazz = env->FindClass("java/lang/Double"); + jDoubleValueMethodId = env->GetMethodID(jDoubleClazz, "doubleValue", "()D"); + env->DeleteLocalRef(jDoubleClazz); + } + jdouble jDoubleObj = env->CallDoubleMethod(jDataObj, jDoubleValueMethodId); + if (js_server_api_functions != nullptr) { + param->type = ParamsType::DOUBLE; + param->value.doubleValue = jDoubleObj; + } else { + serializer->add(jDoubleObj); + } + + } else if (jTypeInt == 2) { + jstring jDataStr = (jstring) jDataObj; + if (js_server_api_functions != nullptr) { + param->type = ParamsType::STRING; + param->value.string = jstring2WeexString(env, jDataStr); + } else { + addString(env, serializer.get(), jDataStr); + } + } else if (jTypeInt == 3) { + jstring jDataStr = (jstring) jDataObj; + if (js_server_api_functions != nullptr) { + param->type = ParamsType::JSONSTRING; + param->value.string = jstring2WeexString(env, jDataStr); + } else { + addJSONString(env, serializer.get(), jDataStr); + } + } else { + if (js_server_api_functions != nullptr) { + param->type = ParamsType::JSUNDEFINED; + } else { + serializer->addJSUndefined(); + } + } + if (param != nullptr) + params.push_back(param); + env->DeleteLocalRef(jDataObj); + env->DeleteLocalRef(jArg); + } + + if (js_server_api_functions != nullptr) { + char *result = js_server_api_functions->funcExeJSWithResult( + env->GetStringUTFChars(jinstanceid, + nullptr), + env->GetStringUTFChars(jnamespace, + nullptr), + env->GetStringUTFChars(jfunction, + nullptr), + params); + for (auto ¶m : params) { + if (param->type == ParamsType::STRING || + param->type == ParamsType::JSONSTRING) { + free(param->value.string); + } + free(param); + } + return newJByteArray(env, result); + } else { + + std::unique_ptr<IPCBuffer> buffer = serializer->finish(); + std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); + if (result->getType() != IPCType::BYTEARRAY) { + return NULL; + } + if (result->getByteArrayLength() == 0) { + return NULL; + } + jbyteArray array = env->NewByteArray(result->getByteArrayLength()); + env->SetByteArrayRegion(array, 0, result->getByteArrayLength(), + reinterpret_cast<const jbyte *>(result->getByteArrayContent())); + return array; + } + } catch (IPCException &e) { + LOGE("%s", e.msg()); + // report crash here + reportServerCrash(jinstanceid); + return NULL; + } + return NULL; + } + + void WeexProxy::updateGlobalConfig(JNIEnv *env, jobject jcaller, jstring config) { + if (!sSender && js_server_api_functions == nullptr) { + LOGE("have not connected to a js server"); + return; + } + if (config == NULL) { + LOGE("native_execJS function is NULL"); + return; + } + + if (js_server_api_functions != nullptr) { + js_server_api_functions->funcUpdateGlobalConfig( + env->GetStringUTFChars(config, nullptr)); + return; + } else { + try { + std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); + serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::UPDATEGLOBALCONFIG)); + addString(env, serializer.get(), config); + std::unique_ptr<IPCBuffer> buffer = serializer->finish(); + std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); + } catch (IPCException &e) { + LOGE("%s", e.msg()); + } + } + } + + static jstring getJsonData(JNIEnv *env, jobjectArray jargs, int index) { + int length = 0; + if (jargs != NULL) { + length = env->GetArrayLength(jargs); + } + jstring ret = NULL; + if (length < (index + 1)) { + return ret; + } + jobject jArg = env->GetObjectArrayElement(jargs, index); + + jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I"); + jint jTypeInt = env->GetIntField(jArg, jTypeId); + jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;"); + jobject jDataObj = env->GetObjectField(jArg, jDataId); + if (jTypeInt == 3) { + ret = (jstring) jDataObj; + } + // env->DeleteLocalRef(jDataObj); + env->DeleteLocalRef(jArg); + return ret; + } + + jint + WeexProxy::createInstanceContext(JNIEnv *env, jobject jcaller, jstring jinstanceid, + jstring name, + jstring jfunction, jobjectArray jargs) { + if (!sSender && js_server_api_functions == nullptr) { + LOGE("have not connected to a js server"); + return false; + } + if (jfunction == NULL || jinstanceid == NULL) { + LOGE("native_createInstanceContext function is NULL"); + return false; + } + + int length = 0; + if (jargs != NULL) { + length = env->GetArrayLength(jargs); + } + if (length < 4) { + LOGE("native_createInstanceContext jargs format error"); + return false; + } +// get temp data, such as js bundle + jobject jArg = env->GetObjectArrayElement(jargs, 1); + jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;"); + jobject jDataObj = env->GetObjectField(jArg, jDataId); + jstring jscript = (jstring) jDataObj; + jstring opts = getJsonData(env, jargs, 2); + // init jsonData + jstring initData = getJsonData(env, jargs, 3); + // get extend api data, such as rax-api + jArg = env->GetObjectArrayElement(jargs, 4); + jDataObj = env->GetObjectField(jArg, jDataId); + jstring japi = (jstring) jDataObj; + if (js_server_api_functions != nullptr) { + ScopedJStringUTF8 idChar(env, jinstanceid); + ScopedJStringUTF8 funcChar(env, jfunction); + ScopedJStringUTF8 scriptChar(env, jscript); + ScopedJStringUTF8 optsChar(env, opts); + ScopedJStringUTF8 initDataChar(env, initData); + ScopedJStringUTF8 apiChar(env, japi); + + return js_server_api_functions->funcCreateInstance( + idChar.getChars(), + funcChar.getChars(), + scriptChar.getChars(), + optsChar.getChars(), + initDataChar.getChars(), + apiChar.getChars()); + } else { + try { + std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); + serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::CREATEINSTANCE)); + addString(env, serializer.get(), jinstanceid); + addString(env, serializer.get(), jfunction); + addString(env, serializer.get(), jscript); + addJSONString(env, serializer.get(), opts); + addJSONString(env, serializer.get(), initData); + addString(env, serializer.get(), japi); + + std::unique_ptr<IPCBuffer> buffer = serializer->finish(); + std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); + env->DeleteLocalRef(jArg); + env->DeleteLocalRef(jDataObj); + env->DeleteLocalRef(opts); + if (result->getType() != IPCType::INT32) { + LOGE("createInstanceContext Unexpected result type"); + return false; + } + return result->get<jint>(); + } catch (IPCException &e) { + LOGE("%s", e.msg()); + // report crash here + reportServerCrash(jinstanceid); + return false; + } + } + return true; + } + + jint WeexProxy::destoryInstance(JNIEnv *env, jobject jcaller, jstring jinstanceid, + jstring jnamespace, + jstring jfunction, jobjectArray jargs) { + int ret = execJS(env, nullptr, jinstanceid, jnamespace, jfunction, jargs); + if (jfunction == NULL || jinstanceid == NULL) { + LOGE("native_destoryInstance function is NULL"); + return false; + } + + if (js_server_api_functions != nullptr) { + ScopedJStringUTF8 idChar(env, jinstanceid); + return js_server_api_functions->funcDestroyInstance(idChar.getChars()); + } else { + try { + std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); + serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::DESTORYINSTANCE)); + addString(env, serializer.get(), jinstanceid); + + std::unique_ptr<IPCBuffer> buffer = serializer->finish(); + std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); + if (result->getType() != IPCType::INT32) { + LOGE("destoryInstance Unexpected result type"); + return false; + } + return result->get<jint>(); + } catch (IPCException &e) { + LOGE("%s", e.msg()); + // report crash here + reportServerCrash(jinstanceid); + return false; + } + } + return true; + } + + jstring + WeexProxy::execJSOnInstance(JNIEnv *env, jobject jcaller, jstring instanceId, jstring script, + jint type) { + if (instanceId == NULL || script == NULL) { + return env->NewStringUTF(""); + } + + + if (js_server_api_functions != nullptr) { + ScopedJStringUTF8 idChar(env, instanceId); + ScopedJStringUTF8 scriptChar(env, script); + char *string = js_server_api_functions->funcExeJSOnInstance( + idChar.getChars(), + scriptChar.getChars()); + return env->NewStringUTF(string); + } else { + try { + // base::debug::TraceScope traceScope("weex", "native_execJSOnInstance"); + std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); + serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJSONINSTANCE)); + + addString(env, serializer.get(), instanceId); + addString(env, serializer.get(), script); + + std::unique_ptr<IPCBuffer> buffer = serializer->finish(); + std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); + if (result->getType() != IPCType::BYTEARRAY) { + // LOGE("native_execJSOnInstance return type error"); + return env->NewStringUTF(""); + } + return env->NewStringUTF(result->getByteArrayContent()); + } catch (IPCException &e) { + LOGE("%s", e.msg()); + // report crash here + reportServerCrash(instanceId); + return env->NewStringUTF(""); + } + } } - jclass c_params = env->GetObjectClass(params); - - jmethodID m_platform = env->GetMethodID(c_params, - "getPlatform", - "()Ljava/lang/String;"); - jobject platform = env->CallObjectMethod(params, m_platform); - if (!WXCoreEnvironment::getInstance()->SetPlatform( - jString2StrFast(env, reinterpret_cast<jstring &>(platform)))) { - LOGD("setPlatform"); - } - ADDSTRING(platform); - - jmethodID m_osVersion = env->GetMethodID( - c_params, "getOsVersion", "()Ljava/lang/String;"); - jobject osVersion = env->CallObjectMethod(params, m_osVersion); - ADDSTRING(osVersion); - - // use param ti get cacheDir - jmethodID m_cacheMethod = env->GetMethodID( - c_params, "getCacheDir", "()Ljava/lang/String;"); - if (m_cacheMethod != NULL) { - jobject cacheDir = env->CallObjectMethod(params, m_cacheMethod); - if (cacheDir != NULL) { - ADDSTRING(cacheDir); - } - } - - jmethodID m_appVersion = env->GetMethodID( - c_params, "getAppVersion", "()Ljava/lang/String;"); - jobject appVersion = env->CallObjectMethod(params, m_appVersion); - ADDSTRING(appVersion); - - jmethodID m_weexVersion = env->GetMethodID( - c_params, "getWeexVersion", "()Ljava/lang/String;"); - jobject weexVersion = env->CallObjectMethod(params, m_weexVersion); - ADDSTRING(weexVersion); - - jmethodID m_deviceModel = env->GetMethodID( - c_params, "getDeviceModel", "()Ljava/lang/String;"); - jobject deviceModel = env->CallObjectMethod(params, m_deviceModel); - ADDSTRING(deviceModel); - - jmethodID m_appName = env->GetMethodID( - c_params, "getAppName", "()Ljava/lang/String;"); - jobject appName = env->CallObjectMethod(params, m_appName); - ADDSTRING(appName); - - jmethodID m_deviceWidth = env->GetMethodID( - c_params, "getDeviceWidth", "()Ljava/lang/String;"); - jobject deviceWidth = env->CallObjectMethod(params, m_deviceWidth); - if (!WXCoreEnvironment::getInstance()->SetDeviceWidth( - jString2StrFast(env, reinterpret_cast<jstring &>(deviceWidth)))) { - LOGD("setDeviceWidth"); - } - ADDSTRING(deviceWidth); - - jmethodID m_deviceHeight = env->GetMethodID( - c_params, "getDeviceHeight", "()Ljava/lang/String;"); - jobject deviceHeight = env->CallObjectMethod(params, m_deviceHeight); - if (!WXCoreEnvironment::getInstance()->SetDeviceHeight( - jString2StrFast(env, reinterpret_cast<jstring &>(deviceHeight)))) { - LOGD("setDeviceHeight"); - } - ADDSTRING(deviceHeight); - - jmethodID m_options = env->GetMethodID( - c_params, "getOptions", "()Ljava/lang/Object;"); - jobject options = env->CallObjectMethod(params, m_options); - jclass jmapclass = env->FindClass("java/util/HashMap"); - jmethodID jkeysetmid = env->GetMethodID(jmapclass, - "keySet", - "()Ljava/util/Set;"); - jmethodID jgetmid = env->GetMethodID( - jmapclass, - "get", - "(Ljava/lang/Object;)Ljava/lang/Object;"); - jobject jsetkey = env->CallObjectMethod(options, jkeysetmid); - jclass jsetclass = env->FindClass("java/util/Set"); - jmethodID jtoArraymid = env->GetMethodID(jsetclass, - "toArray", - "()[Ljava/lang/Object;"); - jobjectArray jobjArray = - (jobjectArray) env->CallObjectMethod(jsetkey, jtoArraymid); - env->DeleteLocalRef(jsetkey); - if (jobjArray != NULL) { - jsize arraysize = env->GetArrayLength(jobjArray); - for (int i = 0; i < arraysize; i++) { - jstring jkey = (jstring) env->GetObjectArrayElement(jobjArray, i); - jstring jvalue = (jstring) env->CallObjectMethod(options, jgetmid, jkey); - - if (jkey != NULL) { - // const char* c_key = env->GetStringUTFChars(jkey, NULL); - // addString(vm, WXEnvironment, c_key, jString2String(env, jvalue)); - // serializer->add(c_key, strlen(c_key)); - // env->DeleteLocalRef(jkey); - // if (jvalue != NULL) { - // env->DeleteLocalRef(jvalue); - // } - ScopedJStringUTF8 c_key(env, jkey); - ScopedJStringUTF8 c_value(env, jvalue); - const char *c_key_chars = c_key.getChars(); - int c_key_len = strlen(c_key_chars); - const char *c_value_chars = c_value.getChars(); - int c_value_len = strlen(c_value_chars); - serializer->add(c_key_chars, c_key_len); - serializer->add(c_value_chars, c_value_len); - WXCoreEnvironment::getInstance()->AddOption(jString2Str(env, jkey), jString2Str(env, jvalue)); - } - } - env->DeleteLocalRef(jobjArray); - } - env->DeleteLocalRef(options); -} - -void -WeexProxy::reportException(const char *instanceID, - const char *func, - const char *exception_string) { - JNIEnv *env = getJNIEnv(); - jstring jExceptionString = env->NewStringUTF(exception_string); - jstring jInstanceId = env->NewStringUTF(instanceID); - jstring jFunc = env->NewStringUTF(func); - jmethodID tempMethodId = env->GetMethodID( - jBridgeClazz, - "reportJSException", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); - env->CallVoidMethod(jThis, - tempMethodId, - jInstanceId, - jFunc, - jExceptionString); - env->DeleteLocalRef(jExceptionString); - env->DeleteLocalRef(jInstanceId); - env->DeleteLocalRef(jFunc); -} - -void WeexProxy::reportServerCrash(jstring jinstanceid) { - JNIEnv *env = getJNIEnv(); - jmethodID reportMethodId; - jstring crashFile; - std::string crashFileStr; - reportMethodId = env->GetMethodID(jBridgeClazz, - "reportServerCrash", - "(Ljava/lang/String;Ljava/lang/String;)V"); - if (!reportMethodId) - goto no_method; - - crashFileStr.assign("/jsserver_crash/jsserver_crash_info.log"); - - crashFile = env->NewStringUTF(crashFileStr.c_str()); - env->CallVoidMethod(jThis, reportMethodId, jinstanceid, crashFile); - env->DeleteLocalRef(crashFile); - no_method: - env->ExceptionClear(); -} - -const char *WeexProxy::getCacheDir(JNIEnv *env) { - jclass activityThreadCls, applicationCls, fileCls; - jobject applicationObj, fileObj, pathStringObj; - jmethodID currentApplicationMethodId, - getCacheDirMethodId, - getAbsolutePathMethodId; - static std::string storage; - const char *tmp; - const char *ret = nullptr; - if (!storage.empty()) { - ret = storage.c_str(); - goto no_empty; - } - activityThreadCls = env->FindClass("android/app/ActivityThread"); - if (!activityThreadCls || env->ExceptionOccurred()) { - goto no_class; - } - currentApplicationMethodId = env->GetStaticMethodID( - activityThreadCls, - "currentApplication", - "()Landroid/app/Application;"); - if (!currentApplicationMethodId || env->ExceptionOccurred()) { - goto no_currentapplication_method; - } - applicationObj = env->CallStaticObjectMethod(activityThreadCls, - currentApplicationMethodId, - nullptr); - if (!applicationObj || env->ExceptionOccurred()) { - goto no_application; - } - applicationCls = env->GetObjectClass(applicationObj); - getCacheDirMethodId = env->GetMethodID(applicationCls, - "getCacheDir", - "()Ljava/io/File;"); - if (!getCacheDirMethodId || env->ExceptionOccurred()) { - goto no_getcachedir_method; - } - fileObj = env->CallObjectMethod(applicationObj, getCacheDirMethodId, nullptr); - if (!fileObj || env->ExceptionOccurred()) { - goto no_file_obj; - } - fileCls = env->GetObjectClass(fileObj); - getAbsolutePathMethodId = env->GetMethodID(fileCls, - "getAbsolutePath", - "()Ljava/lang/String;"); - if (!getAbsolutePathMethodId || env->ExceptionOccurred()) { - goto no_getabsolutepath_method; - } - pathStringObj = env->CallObjectMethod(fileObj, - getAbsolutePathMethodId, - nullptr); - if (!pathStringObj || env->ExceptionOccurred()) { - goto no_path_string; - } - tmp = env->GetStringUTFChars(reinterpret_cast<jstring>(pathStringObj), - nullptr); - storage.assign(tmp); - env->ReleaseStringUTFChars(reinterpret_cast<jstring>(pathStringObj), - tmp); - ret = storage.c_str(); - no_path_string: - no_getabsolutepath_method: - env->DeleteLocalRef(fileCls); - env->DeleteLocalRef(fileObj); - no_file_obj: - no_getcachedir_method: - env->DeleteLocalRef(applicationCls); - env->DeleteLocalRef(applicationObj); - no_application: - no_currentapplication_method: - env->DeleteLocalRef(activityThreadCls); - no_class: - env->ExceptionDescribe(); - env->ExceptionClear(); - no_empty: - return ret; -} - -void WeexProxy::setCacheDir(JNIEnv *env) { - s_cacheDir = getCacheDir(env); -} - -jbyteArray WeexProxy::execJSWithResult(JNIEnv* env, jobject jthis, - jstring jinstanceid, - jstring jnamespace, - jstring jfunction, - jobjectArray jargs) { - if (!sSender) { - LOGE("have not connected to a js server"); - return NULL; - } - if (jfunction == NULL || jinstanceid == NULL) { - LOGE("native_execJS function is NULL"); - return NULL; - } - - int length = 0; - if (jargs != NULL) { - length = env->GetArrayLength(jargs); - } - try { - std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJSWITHRESULT)); - addString(env, serializer.get(), jinstanceid); - if (jnamespace) - addString(env, serializer.get(), jnamespace); - else { - uint16_t tmp = 0; - serializer->add(&tmp, 0); - } - addString(env, serializer.get(), jfunction); - - for (int i = 0; i < length; i++) { - jobject jArg = env->GetObjectArrayElement(jargs, i); - - jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I"); - jint jTypeInt = env->GetIntField(jArg, jTypeId); - - jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;"); - jobject jDataObj = env->GetObjectField(jArg, jDataId); - if (jTypeInt == 1) { - if (jDoubleValueMethodId == NULL) { - jclass jDoubleClazz = env->FindClass("java/lang/Double"); - jDoubleValueMethodId = env->GetMethodID(jDoubleClazz, "doubleValue", "()D"); - env->DeleteLocalRef(jDoubleClazz); - } - jdouble jDoubleObj = env->CallDoubleMethod(jDataObj, jDoubleValueMethodId); - serializer->add(jDoubleObj); - - } else if (jTypeInt == 2) { - jstring jDataStr = (jstring)jDataObj; - addString(env, serializer.get(), jDataStr); - } else if (jTypeInt == 3) { - jstring jDataStr = (jstring)jDataObj; - addJSONString(env, serializer.get(), jDataStr); - } else { - serializer->addJSUndefined(); - } - env->DeleteLocalRef(jDataObj); - env->DeleteLocalRef(jArg); - } - std::unique_ptr<IPCBuffer> buffer = serializer->finish(); - std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); - if (result->getType() != IPCType::BYTEARRAY) { - return NULL; - } - if(result->getByteArrayLength() == 0){ - return NULL; - } - jbyteArray array = env->NewByteArray(result->getByteArrayLength()); - env->SetByteArrayRegion(array, 0, result->getByteArrayLength(), reinterpret_cast<const jbyte*>(result->getByteArrayContent())); - return array; - } catch (IPCException& e) { - LOGE("%s", e.msg()); - // report crash here - reportServerCrash(jinstanceid); - return NULL; - } - return NULL; -} - -void WeexProxy::updateGlobalConfig(JNIEnv *env, jobject jcaller, jstring config) { - if (!sSender) { - LOGE("have not connected to a js server"); - return; - } - if (config == NULL) { - LOGE("native_execJS function is NULL"); - return; - } - try { - std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::UPDATEGLOBALCONFIG)); - addString(env, serializer.get(), config); - std::unique_ptr<IPCBuffer> buffer = serializer->finish(); - std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); - } catch (IPCException& e) { - LOGE("%s", e.msg()); - } -} - -static jstring getJsonData(JNIEnv *env, jobjectArray jargs, int index) { - int length = 0; - if (jargs != NULL) { - length = env->GetArrayLength(jargs); - } - jstring ret = NULL; - if (length < (index + 1)) { - return ret; - } - jobject jArg = env->GetObjectArrayElement(jargs, index); - - jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I"); - jint jTypeInt = env->GetIntField(jArg, jTypeId); - jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;"); - jobject jDataObj = env->GetObjectField(jArg, jDataId); - if (jTypeInt == 3) { - ret = (jstring) jDataObj; - } - // env->DeleteLocalRef(jDataObj); - env->DeleteLocalRef(jArg); - return ret; -} - -jint -WeexProxy::createInstanceContext(JNIEnv *env, jobject jcaller, jstring jinstanceid, jstring name, - jstring jfunction, jobjectArray jargs) { - if (!sSender) { - LOGE("have not connected to a js server"); - return false; - } - if (jfunction == NULL || jinstanceid == NULL) { - LOGE("native_createInstanceContext function is NULL"); - return false; - } - - int length = 0; - if (jargs != NULL) { - length = env->GetArrayLength(jargs); - } - if (length < 4) { - LOGE("native_createInstanceContext jargs format error"); - return false; - } - try { - std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::CREATEINSTANCE)); - addString(env, serializer.get(), jinstanceid); - addString(env, serializer.get(), jfunction); - - // get temp data, such as js bundle - jobject jArg = env->GetObjectArrayElement(jargs,1); - jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;"); - jobject jDataObj = env->GetObjectField(jArg, jDataId); - jstring jscript = (jstring) jDataObj; - addString(env, serializer.get(), jscript); - jstring opts = getJsonData(env, jargs, 2); - addJSONString(env, serializer.get(), opts); - // init jsonData - jstring initData = getJsonData(env, jargs, 3); - addJSONString(env, serializer.get(), initData); - - // get extend api data, such as rax-api - jArg = env->GetObjectArrayElement(jargs, 4); - jDataObj = env->GetObjectField(jArg, jDataId); - jstring japi = (jstring) jDataObj; - addString(env, serializer.get(), japi); - - std::unique_ptr<IPCBuffer> buffer = serializer->finish(); - std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); - env->DeleteLocalRef(jArg); - env->DeleteLocalRef(jDataObj); - env->DeleteLocalRef(opts); - if (result->getType() != IPCType::INT32) { - LOGE("createInstanceContext Unexpected result type"); - return false; - } - return result->get<jint>(); - } catch (IPCException& e) { - LOGE("%s", e.msg()); - // report crash here - reportServerCrash(jinstanceid); - return false; - } - return true; -} - -jint WeexProxy::destoryInstance(JNIEnv *env, jobject jcaller, jstring jinstanceid, jstring jnamespace, - jstring jfunction, jobjectArray jargs) { - int ret = execJS(env, nullptr, jinstanceid, jnamespace, jfunction, jargs); - if (jfunction == NULL || jinstanceid == NULL) { - LOGE("native_destoryInstance function is NULL"); - return false; - } - try { - std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::DESTORYINSTANCE)); - addString(env, serializer.get(), jinstanceid); - - std::unique_ptr<IPCBuffer> buffer = serializer->finish(); - std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); - if (result->getType() != IPCType::INT32) { - LOGE("destoryInstance Unexpected result type"); - return false; - } - return result->get<jint>(); - } catch (IPCException& e) { - LOGE("%s", e.msg()); - // report crash here - reportServerCrash(jinstanceid); - return false; - } - return true; -} - -jstring -WeexProxy::execJSOnInstance(JNIEnv *env, jobject jcaller, jstring instanceId, jstring script, - jint type) { - if (instanceId == NULL || script == NULL) { - return env->NewStringUTF(""); - } - try { - // base::debug::TraceScope traceScope("weex", "native_execJSOnInstance"); - std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJSONINSTANCE)); - - addString(env, serializer.get(), instanceId); - addString(env, serializer.get(), script); - - std::unique_ptr<IPCBuffer> buffer = serializer->finish(); - std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); - if (result->getType() != IPCType::BYTEARRAY) { - // LOGE("native_execJSOnInstance return type error"); - return env->NewStringUTF(""); - } - return env->NewStringUTF(result->getByteArrayContent()); - } catch (IPCException& e) { - LOGE("%s", e.msg()); - // report crash here - reportServerCrash(instanceId); - return env->NewStringUTF(""); - } -} - -jint WeexProxy::initAppFramework(JNIEnv* env, - jobject jcaller, - jstring jinstanceid, - jstring jframwork, - jobjectArray jargs) { - if (!sSender) { - LOGE("have not connected to a js server"); - return false; - } - if (jframwork == NULL && jargs == NULL) { - LOGE("native_initAppFramework jframwork is NULL"); - return false; - } - int length = 0; - if (jargs != NULL) { - length = env->GetArrayLength(jargs); - } - try { - - std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::INITAPPFRAMEWORK)); - addString(env, serializer.get(), jinstanceid); - addString(env, serializer.get(), jframwork); - for (int i = 0; i < length; i++) { - jobject jArg = env->GetObjectArrayElement(jargs, i); - - jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I"); - jint jTypeInt = env->GetIntField(jArg, jTypeId); - - jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;"); - jobject jDataObj = env->GetObjectField(jArg, jDataId); - - jfieldID jKeyId = env->GetFieldID(jWXJSObject, "key", "Ljava/lang/String;"); - jobject jKeyObj = env->GetObjectField(jArg, jKeyId); - addString(env, serializer.get(), (jstring) jKeyObj); - - if (jTypeInt == 1) { - if (jDoubleValueMethodId == NULL) { - jclass jDoubleClazz = env->FindClass("java/lang/Double"); - jDoubleValueMethodId = env->GetMethodID(jDoubleClazz, "doubleValue", "()D"); - env->DeleteLocalRef(jDoubleClazz); - } - jdouble jDoubleObj = env->CallDoubleMethod(jDataObj, jDoubleValueMethodId); - serializer->add(jDoubleObj); - } else if (jTypeInt == 2) { - jstring jDataStr = (jstring)jDataObj; - addString(env, serializer.get(), jDataStr); - } else if (jTypeInt == 3) { - jstring jDataStr = (jstring)jDataObj; - addJSONString(env, serializer.get(), jDataStr); - } + + jint WeexProxy::initAppFramework(JNIEnv *env, + jobject jcaller, + jstring jinstanceid, + jstring jframwork, + jobjectArray jargs) { + if (!sSender && js_server_api_functions == nullptr) { + LOGE("have not connected to a js server"); + return false; + } + if (jframwork == NULL && jargs == NULL) { + LOGE("native_initAppFramework jframwork is NULL"); + return false; + } + int length = 0; + if (jargs != NULL) { + length = env->GetArrayLength(jargs); + } + try { + std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); + std::vector<INIT_FRAMEWORK_PARAMS *> params; + if (js_server_api_functions == nullptr) { + serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::INITAPPFRAMEWORK)); + addString(env, serializer.get(), jinstanceid); + addString(env, serializer.get(), jframwork); + } + + + for (int i = 0; i < length; i++) { + jobject jArg = env->GetObjectArrayElement(jargs, i); + + jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I"); + jint jTypeInt = env->GetIntField(jArg, jTypeId); + + jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;"); + jobject jDataObj = env->GetObjectField(jArg, jDataId); + + jfieldID jKeyId = env->GetFieldID(jWXJSObject, "key", "Ljava/lang/String;"); + jobject jKeyObj = env->GetObjectField(jArg, jKeyId); + jstring jKeyStr = (jstring) jKeyObj; + if (js_server_api_functions == nullptr) { + + addByteArrayString(env, serializer.get(), jKeyStr); + } + + if (jTypeInt == 1) { + if (jDoubleValueMethodId == NULL) { + jclass jDoubleClazz = env->FindClass("java/lang/Double"); + jDoubleValueMethodId = env->GetMethodID(jDoubleClazz, "doubleValue", "()D"); + env->DeleteLocalRef(jDoubleClazz); + } + jdouble jDoubleObj = env->CallDoubleMethod(jDataObj, jDoubleValueMethodId); + + serializer->add(jDoubleObj); + + } else if (jTypeInt == 2) { + jstring jDataStr = (jstring) jDataObj; + if (js_server_api_functions == nullptr) { + addByteArrayString(env, serializer.get(), jDataStr); + } else { + params.push_back(genInitFrameworkParams(env->GetStringUTFChars(jKeyStr, + nullptr), + env->GetStringUTFChars(jDataStr, + nullptr))); + } + } else if (jTypeInt == 3) { + jstring jDataStr = (jstring) jDataObj; + if (js_server_api_functions == nullptr) { + addByteArrayString(env, serializer.get(), jDataStr); + } else { + params.push_back(genInitFrameworkParams(env->GetStringUTFChars(jKeyStr, + nullptr), + env->GetStringUTFChars(jDataStr, + nullptr))); + } + } // else if (jTypeInt == 4) { // jbyteArray array = (jbyteArray)jDataObj; // addWSONByteArray(env, serializer.get(), array); // } - else { - serializer->addJSUndefined(); - } - - env->DeleteLocalRef(jKeyObj); - env->DeleteLocalRef(jDataObj); - env->DeleteLocalRef(jArg); - } - - std::unique_ptr<IPCBuffer> buffer = serializer->finish(); - std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); - return result->get<jint>(); - } catch (IPCException& e) { - LOGE("initAppFramework error %s", e.msg()); - // report crash here - reportServerCrash(jinstanceid); - return false; - } - return true; -} - -jint WeexProxy::destoryAppContext(JNIEnv* env, - jobject jcaller, - jstring jinstanceid) { - if (!sSender) { - LOGE("have not connected to a js server"); - return false; - } - if (jinstanceid == NULL) { - LOGE("createAppContext jbundle is NULL"); - return false; - } - try { - std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::DESTORYAPPCONTEXT)); - addString(env, serializer.get(), jinstanceid); - std::unique_ptr<IPCBuffer> buffer = serializer->finish(); - std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); - return true; - } catch (IPCException& e) { - LOGE("%s", e.msg()); - // report crash here - reportServerCrash(jinstanceid); - return false; - } - return true; -} - -jint WeexProxy::createAppContext(JNIEnv* env, - jobject jcaller, - jstring jinstanceid, - jstring jbundle, - jobject jargs) { - if (!sSender) { - LOGE("have not connected to a js server"); - return false; - } - if (jinstanceid == NULL || jbundle == NULL) { - LOGE("createAppContext jbundle is NULL"); - return false; - } - try { - std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::CREATEAPPCONTEXT)); - addString(env, serializer.get(), jinstanceid); - addString(env, serializer.get(), jbundle); - std::unique_ptr<IPCBuffer> buffer = serializer->finish(); - std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); - return result->get<jint>(); - } catch (IPCException& e) { - LOGE("%s", e.msg()); - // report crash here - reportServerCrash(jinstanceid); - return false; - } - return true; -} - -jbyteArray WeexProxy::execJsOnAppWithResult(JNIEnv* env, - jobject jcaller, - jstring jinstanceid, - jstring jbundle, - jobject jargs) { - if (!sSender) { - LOGE("have not connected to a js server"); - return NULL; - } - if (jinstanceid == NULL || jbundle == NULL) { - LOGE("native_execJsOnApp jbundle is NULL"); - return NULL; - } - try { - std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::EXECJSONAPPWITHRESULT)); - addString(env, serializer.get(), jinstanceid); - addString(env, serializer.get(), jbundle); - std::unique_ptr<IPCBuffer> buffer = serializer->finish(); - std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); - if (result->getType() != IPCType::BYTEARRAY) { - return NULL; - } - if(result->getByteArrayLength() == 0){ - return NULL; - } - jbyteArray array = env->NewByteArray(result->getByteArrayLength()); - env->SetByteArrayRegion(array, 0, result->getByteArrayLength(), - reinterpret_cast<const jbyte*>(result->getByteArrayContent())); - return array; - } catch (IPCException& e) { - LOGE("%s", e.msg()); - // report crash here - reportServerCrash(jinstanceid); - return NULL; - } - return NULL; -} - -jint WeexProxy::execJsOnApp(JNIEnv* env, - jobject jcaller, - jstring jinstanceid, - jstring jfunction, - jobjectArray jargs) { - if (!sSender) { - LOGE("have not connected to a js server"); - return false; - } - if (jinstanceid == NULL || jfunction == NULL) { - LOGE("native_execJsOnApp jbundle is NULL"); - return false; - } - int length = 0; - if (jargs != NULL) { - length = env->GetArrayLength(jargs); - } - try { - std::unique_ptr <IPCSerializer> serializer(createIPCSerializer()); - serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::CALLJSONAPPCONTEXT)); - addString(env, serializer.get(), jinstanceid); - addString(env, serializer.get(), jfunction); - - for (int i = 0; i < length; i++) { - jobject jArg = env->GetObjectArrayElement(jargs, i); - - jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I"); - jint jTypeInt = env->GetIntField(jArg, jTypeId); - - jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;"); - jobject jDataObj = env->GetObjectField(jArg, jDataId); - if (jTypeInt == 1) { - if (jDoubleValueMethodId == NULL) { - jclass jDoubleClazz = env->FindClass("java/lang/Double"); - jDoubleValueMethodId = env->GetMethodID(jDoubleClazz, "doubleValue", "()D"); - env->DeleteLocalRef(jDoubleClazz); - } - jdouble jDoubleObj = env->CallDoubleMethod(jDataObj, jDoubleValueMethodId); - serializer->add(jDoubleObj); - } else if (jTypeInt == 2) { - jstring jDataStr = (jstring)jDataObj; - addString(env, serializer.get(), jDataStr); - } else if (jTypeInt == 3) { - jstring jDataStr = (jstring)jDataObj; - addJSONString(env, serializer.get(), jDataStr); - } + else { + serializer->addJSUndefined(); + } + + env->DeleteLocalRef(jKeyObj); + env->DeleteLocalRef(jDataObj); + env->DeleteLocalRef(jArg); + } + + if (js_server_api_functions != nullptr) { + ScopedJStringUTF8 idChar(env, jinstanceid); + ScopedJStringUTF8 frameworkChar(env, jframwork); + return js_server_api_functions->funcInitAppFramework( + idChar.getChars(), + frameworkChar.getChars(), + params); + } else { + std::unique_ptr<IPCBuffer> buffer = serializer->finish(); + std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); + return result->get<jint>(); + } + + } catch (IPCException &e) { + LOGE("initAppFramework error %s", e.msg()); + // report crash here + reportServerCrash(jinstanceid); + return false; + } + return true; + } + + jint WeexProxy::destoryAppContext(JNIEnv *env, + jobject jcaller, + jstring jinstanceid) { + if (!sSender && js_server_api_functions == nullptr) { + LOGE("have not connected to a js server"); + return false; + } + if (jinstanceid == NULL) { + LOGE("createAppContext jbundle is NULL"); + return false; + } + + if (js_server_api_functions != nullptr) { + ScopedJStringUTF8 scopedJStringUTF8(env, jinstanceid); + js_server_api_functions->funcDestroyAppContext(scopedJStringUTF8.getChars()); + return true; + } else { + try { + std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); + serializer->setMsg(static_cast<uint32_t>(IPCJSMsg::DESTORYAPPCONTEXT)); + addString(env, serializer.get(), jinstanceid); + std::unique_ptr<IPCBuffer> buffer = serializer->finish(); + std::unique_ptr<IPCResult> result = sSender->send(buffer.get()); + return true; + } catch (IPCException &e) { + LOGE("%s", e.msg()); + // report crash here + reportServerCrash(jinstanceid); + return false; + } + } + return true; + } + + jint WeexProxy::createAppContext(JNIEnv *env, + jobject jcaller, + jstring jinstanceid, + jstring jbundle, + jobject jargs) { + if (!sSender && js_server_api_functions == nullptr) { + LOGE("have not connected to a js server"); + return false; + } + if (jinstanceid == NULL || jbundle == NULL) { + LOGE("createAppContext jbundle is NULL"); + return false; + } + + if (js_server_api_functions != nullptr) { + ScopedJStringUTF8 instanceIdChar(env, jinstanceid); +
<TRUNCATED>