You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ky...@apache.org on 2018/04/28 06:53:46 UTC

[18/48] incubator-weex git commit: * [android] Merge WeexCore-master to master.

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.cpp b/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.cpp
new file mode 100644
index 0000000..4afb185
--- /dev/null
+++ b/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.cpp
@@ -0,0 +1,662 @@
+#include <android/base/string/string_utils.h>
+#include <base/ViewUtils.h>
+#include "ExtendJSApi.h"
+
+using namespace WeexCore;
+
+static WeexCore::FunType gCanvasFunc = nullptr;
+
+static WeexCore::FunTypeT3d t3dFunc = nullptr;
+
+/**
+* This class aim to extend JS Api
+**/
+ExtendJSApi::ExtendJSApi() {
+}
+
+void ExtendJSApi::initFunction(IPCHandler *handler) {
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::SETJSFVERSION),
+                           handleSetJSVersion);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::REPORTEXCEPTION),
+                           handleReportException);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLNATIVE),
+                           handleCallNative);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLNATIVEMODULE),
+                           handleCallNativeModule);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLNATIVECOMPONENT),
+                           handleCallNativeComponent);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLADDELEMENT),
+                           handleCallAddElement);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::SETTIMEOUT),
+                           handleSetTimeout);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::NATIVELOG),
+                           handleCallNativeLog);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLCREATEBODY),
+                           functionCallCreateBody);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLUPDATEFINISH),
+                           functionCallUpdateFinish);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLCREATEFINISH),
+                           functionCallCreateFinish);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLREFRESHFINISH),
+                           functionCallRefreshFinish);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLUPDATEATTRS),
+                           functionCallUpdateAttrs);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLUPDATESTYLE),
+                           functionCallUpdateStyle);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLREMOVEELEMENT),
+                           functionCallRemoveElement);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLMOVEELEMENT),
+                           functionCallMoveElement);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLADDEVENT),
+                           functionCallAddEvent);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLREMOVEEVENT),
+                           functionCallRemoveEvent);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::SETINTERVAL),
+                           handleSetInterval);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CLEARINTERVAL),
+                           handleClearInterval);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLGCANVASLINK),
+                           handleCallGCanvasLinkNative);
+  handler->registerHandler(static_cast<uint32_t>(IPCProxyMsg::CALLT3DLINK),
+                           handleT3DLinkNative);
+}
+
+std::unique_ptr<IPCResult> handleSetJSVersion(IPCArguments *arguments) {
+  const char* version = getArumentAsCStr(arguments, 0);
+  LOGA("init JSFrm version %s", version);
+  Bridge_Impl_Android::getInstance()->setJSVersion(version);
+  return createVoidResult();
+}
+
+void reportException(const char* pageId, const char *func, const char *exception_string) {
+  Bridge_Impl_Android::getInstance()->reportException(pageId, func, exception_string);
+}
+
+std::unique_ptr<IPCResult> handleReportException(IPCArguments *arguments) {
+  const char *pageId = nullptr;
+  const char *func = nullptr;
+  const char *exceptionInfo = nullptr;
+
+  if (arguments->getType(0) == IPCType::BYTEARRAY) {
+    const IPCByteArray *instanceIDBA = arguments->getByteArray(0);
+    pageId = instanceIDBA->content;
+  }
+
+  if (arguments->getType(1) == IPCType::BYTEARRAY) {
+    const IPCByteArray *funcBA = arguments->getByteArray(1);
+    func = funcBA->content;
+  }
+
+  if (arguments->getType(2) == IPCType::BYTEARRAY) {
+    const IPCByteArray *exceptionInfoBA = arguments->getByteArray(2);
+    exceptionInfo = exceptionInfoBA->content;
+  }
+
+  LOGE(" ReportException : %s", exceptionInfo);
+  reportException(pageId, func, exceptionInfo);
+  return createVoidResult();
+}
+
+std::unique_ptr<IPCResult> handle(IPCArguments *arguments) {
+  const char* str_array = getArumentAsCStr(arguments, 0);
+  Bridge_Impl_Android::getInstance()->callNativeLog(str_array);
+  return createInt32Result(static_cast<int32_t>(true));
+}
+
+std::unique_ptr<IPCResult> handleCallNativeLog(IPCArguments *arguments) {
+  const char* str_array = getArumentAsCStr(arguments, 0);
+  Bridge_Impl_Android::getInstance()->callNativeLog(str_array);
+  return createInt32Result(static_cast<int32_t>(true));
+}
+
+std::unique_ptr<IPCResult> handleSetTimeout(IPCArguments *arguments) {
+  char* callbackID = getArumentAsCStr(arguments, 0);
+  char* time = getArumentAsCStr(arguments, 1);
+
+  if (callbackID == nullptr || time == nullptr)
+    return createInt32Result(static_cast<int32_t>(false));
+
+  Bridge_Impl_Android::getInstance()->setTimeout(callbackID, time);
+
+  if (callbackID != nullptr) {
+    delete[]callbackID;
+    callbackID = nullptr;
+  }
+  if (time != nullptr) {
+    delete[]time;
+    time = nullptr;
+  }
+  return createInt32Result(static_cast<int32_t>(true));
+}
+
+std::unique_ptr<IPCResult> handleSetInterval(IPCArguments *arguments) {
+  const char *pageId = getArumentAsCStr(arguments, 0);
+  const char *callbackID = getArumentAsCStr(arguments, 1);
+  const char *_time = getArumentAsCStr(arguments, 2);
+  if (pageId == nullptr || callbackID == nullptr || _time == nullptr)
+    return createInt32Result(-1);
+
+  long time_ = atoi(_time);
+  int _timerId = (atoi(pageId) << 16) | (atoi(callbackID));
+
+  if (pageId != nullptr) {
+    delete[]pageId;
+    pageId = nullptr;
+  }
+  if (callbackID != nullptr) {
+    delete[]callbackID;
+    callbackID = nullptr;
+  }
+  if (_time != nullptr) {
+    delete[]_time;
+    _time = nullptr;
+  }
+  return createInt32Result(_timerId);
+}
+
+std::unique_ptr<IPCResult> handleClearInterval(IPCArguments *arguments) {
+  const char *pageId = getArumentAsCStr(arguments, 0);
+  const char *callbackID = getArumentAsCStr(arguments, 1);
+  long id = atoi(callbackID);
+
+  if (pageId != nullptr) {
+    delete[]pageId;
+    pageId = nullptr;
+  }
+  if (callbackID != nullptr) {
+    delete[]callbackID;
+    callbackID = nullptr;
+  }
+  return createVoidResult();
+}
+
+std::unique_ptr<IPCResult> handleCallNative(IPCArguments *arguments) {
+  char* pageId = getArumentAsCStr(arguments, 0);
+  char* task = getArumentAsCStr(arguments, 1);
+  char* callback = getArumentAsCStr(arguments, 2);
+
+  if (pageId != nullptr && task != nullptr) {
+#if JSAPI_LOG
+    LOGD("[ExtendJSApi] handleCallNative >>>> pageId: %s, task: %s", pageId, task);
+#endif
+
+    if (strcmp(task, "[{\"module\":\"dom\",\"method\":\"createFinish\",\"args\":[]}]") == 0) {
+      RenderManager::GetInstance()->CreateFinish(pageId) ? 0 : -1;
+    } else {
+      Bridge_Impl_Android::getInstance()->callNative(pageId, task, callback);
+    }
+  }
+
+  if (pageId != nullptr) {
+    delete[]pageId;
+    pageId = nullptr;
+  }
+  if (task != nullptr) {
+    delete[]task;
+    task = nullptr;
+  }
+  if (callback != nullptr) {
+    delete[]callback;
+    callback = nullptr;
+  }
+  return createInt32Result(0);
+}
+
+static std::unique_ptr<IPCResult> handleCallGCanvasLinkNative(IPCArguments *arguments) {
+  JNIEnv *env = getJNIEnv();
+  jstring jPageId = getArgumentAsJString(env, arguments, 0);
+  const char *pageId = env->GetStringUTFChars(jPageId, NULL);
+  int type = getArgumentAsInt32(env, arguments, 1);
+  jstring val = getArgumentAsJString(env, arguments, 2);
+  const char *args = env->GetStringUTFChars(val, NULL);
+
+#if JSAPI_LOG
+  LOGD("[ExtendJSApi] handleCallGCanvasLinkNative >>>> pageId: %s, type: %d, args: %s", pageId, type, args);
+#endif
+
+  const char *retVal = NULL;
+  if (gCanvasFunc) {
+    retVal = callGCanvasFun(gCanvasFunc, pageId, type, args);
+  }
+
+  std::unique_ptr<IPCResult> ret = createVoidResult();
+  if (retVal) {
+    jstring jDataStr = env->NewStringUTF(retVal);
+    ret = std::move(createStringResult(env, jDataStr));
+    env->DeleteLocalRef(jDataStr);
+    retVal = NULL;
+  }
+  env->DeleteLocalRef(jPageId);
+  env->DeleteLocalRef(val);
+  return ret;
+}
+
+static std::unique_ptr<IPCResult> handleT3DLinkNative(IPCArguments* arguments)
+{
+  JNIEnv* env = getJNIEnv();
+  int type = getArgumentAsInt32(env, arguments, 0);
+  jstring val = getArgumentAsJString(env, arguments, 1);
+  const char* args = env->GetStringUTFChars(val, NULL);
+
+#if JSAPI_LOG
+  LOGD("[ExtendJSApi] handleT3DLinkNative >>>> type: %d, args: %s", type, args);
+#endif
+
+  const char* retVal = NULL;
+  if (t3dFunc) {
+    retVal = WeexCore::weexCallT3dFunc(t3dFunc, type, args);
+  }
+
+
+
+  std::unique_ptr<IPCResult> ret = createVoidResult();
+  if (retVal) {
+    jstring jDataStr = env->NewStringUTF(retVal);
+    ret = std::move(createStringResult(env, jDataStr));
+    env->DeleteLocalRef(jDataStr);
+    retVal = NULL;
+  }
+  env->DeleteLocalRef(val);
+  return ret;
+}
+
+std::unique_ptr<IPCResult> handleCallNativeModule(IPCArguments *arguments) {
+  char* pageId = getArumentAsCStr(arguments, 0);
+  char* module = getArumentAsCStr(arguments, 1);
+  char* method = getArumentAsCStr(arguments, 2);
+  char* argString = getArumentAsCStr(arguments, 3);
+  char* optString = getArumentAsCStr(arguments, 4);
+
+  std::unique_ptr<IPCResult> ret = createInt32Result(-1);
+
+  if (pageId != nullptr && module != nullptr && method != nullptr) {
+#if JSAPI_LOG
+    LOGD("[ExtendJSApi] handleCallNativeModule >>>> pageId: %s, module: %s, method: %s, arg: %s, opt: %s",
+         pageId, module, method, argString, optString);
+#endif
+
+    // add for android support
+    jobject result;
+    result = Bridge_Impl_Android::getInstance()->callNativeModule(pageId, module, method,
+                                                                  argString, optString);
+
+    if (result == nullptr)
+      return ret;
+
+    JNIEnv *env = getJNIEnv();
+    jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I");
+    jint jTypeInt = env->GetIntField(result, jTypeId);
+    jfieldID jDataId = env->GetFieldID(jWXJSObject, "data", "Ljava/lang/Object;");
+    jobject jDataObj = env->GetObjectField(result, 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);
+      ret = std::move(createDoubleResult(jDoubleObj));
+
+    } else if (jTypeInt == 2) {
+      jstring jDataStr = (jstring) jDataObj;
+      ret = std::move(createStringResult(env, jDataStr));
+    } else if (jTypeInt == 3) {
+      jstring jDataStr = (jstring) jDataObj;
+      ret = std::move(createJSONStringResult(env, jDataStr));
+    }
+    env->DeleteLocalRef(jDataObj);
+  }
+
+  if (pageId != nullptr) {
+    delete[]pageId;
+    pageId = nullptr;
+  }
+  if (module != nullptr) {
+    delete[]module;
+    module = nullptr;
+  }
+  if (method != nullptr) {
+    delete[]method;
+    method = nullptr;
+  }
+  if (argString != nullptr) {
+    delete[]argString;
+    argString = nullptr;
+  }
+  if (optString != nullptr) {
+    delete[]optString;
+    optString = nullptr;
+  }
+  return ret;
+}
+
+std::unique_ptr<IPCResult> handleCallNativeComponent(IPCArguments *arguments) {
+  char* pageId = getArumentAsCStr(arguments, 0);
+  char* ref = getArumentAsCStr(arguments, 1);
+  char* method = getArumentAsCStr(arguments, 2);
+  char* argString = getArumentAsCStr(arguments, 3);
+  char* optString = getArumentAsCStr(arguments, 4);
+
+  if (pageId != nullptr && ref != nullptr && method != nullptr) {
+
+#if JSAPI_LOG
+    LOGD("[ExtendJSApi] handleCallNativeComponent >>>> pageId: %s, ref: %s, method: %s, arg: %s, opt: %s",
+         pageId, ref, method, argString, optString);
+#endif
+
+    Bridge_Impl_Android::getInstance()->callNativeComponent(pageId, ref, method, argString, optString);
+  }
+
+  if (pageId != nullptr) {
+    delete[]pageId;
+    pageId = nullptr;
+  }
+  if (ref != nullptr) {
+    delete[]ref;
+    ref = nullptr;
+  }
+  if (method != nullptr) {
+    delete[]method;
+    method = nullptr;
+  }
+  if (argString != nullptr) {
+    delete[]argString;
+    argString = nullptr;
+  }
+  if (optString != nullptr) {
+    delete[]optString;
+    optString = nullptr;
+  }
+  return createInt32Result(static_cast<int32_t>(true));
+}
+
+std::unique_ptr<IPCResult> functionCallCreateBody(IPCArguments *arguments) {
+
+  char *pageId = getArumentAsCStr(arguments, 0);
+  char *domStr = getArumentAsCStr(arguments, 1);
+
+  if (pageId == nullptr || domStr == nullptr)
+    return createInt32Result(0);
+
+#if JSAPI_LOG
+  LOGD("[ExtendJSApi] functionCallCreateBody >>>> pageId: %s, domStr: %s", pageId, domStr);
+#endif
+
+  RenderManager::GetInstance()->CreatePage(pageId, domStr) ? 0 : -1;
+
+  delete[]pageId;
+  delete[]domStr;
+  return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> handleCallAddElement(IPCArguments *arguments) {
+
+  char *pageId = getArumentAsCStr(arguments, 0);
+  char *parentRef = getArumentAsCStr(arguments, 1);
+  char *domStr = getArumentAsCStr(arguments, 2);
+  char *index_cstr = getArumentAsCStr(arguments, 3);
+  int index = atoi(index_cstr);
+
+  if (pageId == nullptr || parentRef == nullptr || domStr == nullptr || index_cstr == nullptr ||
+      index < -1)
+    return createInt32Result(0);
+
+#if JSAPI_LOG
+
+  std::string log = "";
+  log.append("pageId: ").append(pageId).append(", parentRef: ").append(parentRef).append(", domStr: ").append(domStr);
+  int log_index = 0;
+  int maxLength = 800;
+  std::string sub;
+  while (log_index < log.length()) {
+    if (log.length() <= log_index + maxLength) {
+      sub = log.substr(log_index);
+    } else {
+      sub = log.substr(log_index, maxLength);
+    }
+
+
+    if (log_index == 0)
+      LOGD("[ExtendJSApi] functionCallAddElement >>>> %s", sub.c_str());
+    else
+      LOGD("      [ExtendJSApi] functionCallAddElement >>>> %s", sub.c_str());
+
+    log_index += maxLength;
+  }
+#endif
+
+  RenderManager::GetInstance()->AddRenderObject(pageId, parentRef, index, domStr);
+
+  delete[]pageId;
+  delete[]parentRef;
+  delete[]domStr;
+  delete[]index_cstr;
+  return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallRemoveElement(IPCArguments *arguments) {
+
+  char *pageId = getArumentAsCStr(arguments, 0);
+  char *ref = getArumentAsCStr(arguments, 1);
+
+  if (pageId == nullptr || ref == nullptr)
+    return createInt32Result(0);
+
+#if JSAPI_LOG
+  LOGD("[ExtendJSApi] functionCallRemoveElement >>>> pageId: %s, ref: %s", pageId,
+       ref);
+#endif
+
+  RenderManager::GetInstance()->RemoveRenderObject(pageId, ref);
+
+  delete[]pageId;
+  delete[]ref;
+  return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallMoveElement(IPCArguments *arguments) {
+
+  char *pageId = getArumentAsCStr(arguments, 0);
+  char *ref = getArumentAsCStr(arguments, 1);
+  char *parentRef = getArumentAsCStr(arguments, 2);
+  char *index_str = getArumentAsCStr(arguments, 3);
+  int index = atoi(index_str);
+
+  if (pageId == nullptr || ref == nullptr || parentRef == nullptr || index_str == nullptr ||
+      index < -1)
+    return createInt32Result(0);
+
+#if JSAPI_LOG
+  LOGD("[ExtendJSApi] functionCallRemoveElement >>>> pageId: %s, ref: %s, parentRef: %s, index: %d",
+       pageId, ref, parentRef, index);
+#endif
+
+  RenderManager::GetInstance()->MoveRenderObject(pageId, ref, parentRef, index);
+
+  delete[]pageId;
+  delete[]ref;
+  delete[]parentRef;
+  delete[]index_str;
+  return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallAddEvent(IPCArguments *arguments) {
+
+  char *pageId = getArumentAsCStr(arguments, 0);
+  char *ref = getArumentAsCStr(arguments, 1);
+  char *event = getArumentAsCStr(arguments, 2);
+
+  if (pageId == nullptr || ref == nullptr || event == nullptr)
+    return createInt32Result(0);
+
+#if JSAPI_LOG
+  LOGD("[ExtendJSApi] functionCallAddEvent >>>> pageId: %s, ref: %s, event: %s", pageId,
+       ref, event);
+#endif
+
+  RenderManager::GetInstance()->AddEvent(pageId, ref, event);
+
+  delete[]pageId;
+  delete[]ref;
+  delete[]event;
+  return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallRemoveEvent(IPCArguments *arguments) {
+
+  char *pageId = getArumentAsCStr(arguments, 0);
+  char *ref = getArumentAsCStr(arguments, 1);
+  char *event = getArumentAsCStr(arguments, 2);
+
+  if (pageId == nullptr || ref == nullptr || event == nullptr)
+    return createInt32Result(0);
+
+#if JSAPI_LOG
+  LOGD("[ExtendJSApi] functionCallRemoveEvent >>>> pageId: %s, ref: %s, event: %s", pageId,
+       ref, event);
+#endif
+
+  RenderManager::GetInstance()->RemoveEvent(pageId, ref, event);
+
+  delete[]pageId;
+  delete[]ref;
+  delete[]event;
+  return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallUpdateStyle(IPCArguments *arguments) {
+
+  char *pageId = getArumentAsCStr(arguments, 0);
+  char *ref = getArumentAsCStr(arguments, 1);
+  char *data = getArumentAsCStr(arguments, 2);
+
+  if (pageId == nullptr || ref == nullptr || data == nullptr)
+    return createInt32Result(0);
+
+#if JSAPI_LOG
+  LOGD("[ExtendJSApi] functionCallUpdateStyle >>>> pageId: %s, ref: %s, data: %s", pageId,
+       ref, data);
+#endif
+
+  RenderManager::GetInstance()->UpdateStyle(pageId, ref, data);
+
+  delete[] pageId;
+  delete[] ref;
+  delete[] data;
+  return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallUpdateAttrs(IPCArguments *arguments) {
+
+  char *pageId = getArumentAsCStr(arguments, 0);
+  char *ref = getArumentAsCStr(arguments, 1);
+  char *data = getArumentAsCStr(arguments, 2);
+
+  if (pageId == nullptr || ref == nullptr || data == nullptr)
+    return createInt32Result(0);
+
+#if JSAPI_LOG
+  LOGD("[ExtendJSApi] functionCallUpdateAttrs >>>> pageId: %s, ref: %s, data: %s", pageId,
+       ref, data);
+#endif
+
+  RenderManager::GetInstance()->UpdateAttr(pageId, ref, data);
+
+  delete[] pageId;
+  delete[] ref;
+  delete[] data;
+  return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallCreateFinish(IPCArguments *arguments) {
+
+  char *pageId = getArumentAsCStr(arguments, 0);
+
+  if (pageId == nullptr)
+    return createInt32Result(0);
+
+#if JSAPI_LOG
+  LOGD("[ExtendJSApi] functionCallCreateFinish >>>> pageId: %s", pageId);
+#endif
+
+  RenderManager::GetInstance()->CreateFinish(pageId);
+
+  delete[]pageId;
+  return createInt32Result(0);
+}
+
+std::unique_ptr<IPCResult> functionCallUpdateFinish(IPCArguments *arguments) {
+  char *pageId = getArumentAsCStr(arguments, 0);
+  char *task = getArumentAsCStr(arguments, 1);
+  char *callback = getArumentAsCStr(arguments, 2);
+
+  int flag = 0;
+
+  if (pageId == nullptr || task == nullptr)
+    return createInt32Result(flag);
+
+  flag = Bridge_Impl_Android::getInstance()->callUpdateFinish(pageId, task, callback);
+
+  if (pageId != nullptr) {
+    delete[]pageId;
+    pageId = nullptr;
+  }
+  if (task != nullptr) {
+    delete[]task;
+    task = nullptr;
+  }
+  if (callback != nullptr) {
+    delete[]callback;
+    callback = nullptr;
+  }
+  return createInt32Result(flag);
+}
+
+std::unique_ptr<IPCResult> functionCallRefreshFinish(IPCArguments *arguments) {
+  char *pageId = getArumentAsCStr(arguments, 0);
+  char *task = getArumentAsCStr(arguments, 1);
+  char *callback = getArumentAsCStr(arguments, 2);
+
+  int flag = 0;
+
+  if (pageId == nullptr)
+    return createInt32Result(flag);
+
+  flag = Bridge_Impl_Android::getInstance()->callRefreshFinish(pageId, task, callback);
+
+  if (pageId != nullptr) {
+    delete[]pageId;
+    pageId = nullptr;
+  }
+  if (task != nullptr) {
+    delete[]task;
+    task = nullptr;
+  }
+  if (callback != nullptr) {
+    delete[]callback;
+    callback = nullptr;
+  }
+  return createInt32Result(flag);
+}
+
+namespace WeexCore {
+
+  extern "C" void Inject_GCanvasFunc(FunType fp) {
+    gCanvasFunc = fp;
+    LOGE("weexjsc injectGCanvasFunc gCanvasFunc");
+  }
+
+  const char *callGCanvasFun(FunType fp, const char *conextId, int x, const char *args) {
+    return fp(conextId, x, args);
+  }
+
+  extern "C" void Inject_T3dFunc(FunTypeT3d fp) {
+    t3dFunc = fp;
+    LOGE("weexjsc Inject_T3dFunc t3d Func");
+  }
+
+const char* weexCallT3dFunc(FunTypeT3d fp, int x, const char* args) {
+  return fp(x, args);
+}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.h b/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.h
new file mode 100644
index 0000000..d23cda1
--- /dev/null
+++ b/weex_core/Source/android/jsengine/multiprocess/ExtendJSApi.h
@@ -0,0 +1,87 @@
+#ifndef _EXTEND_JSAPI_H_
+#define _EXTEND_JSAPI_H_
+
+#include <android/base/log_utils.h>
+#include <android/bridge/impl/bridge_impl_android.h>
+#include "IPC/IPCHandler.h"
+#include "IPC/IPCMessageJS.h"
+#include "IPC/IPCResult.h"
+#include "IPC/IPCSender.h"
+#include "IPC/IPCString.h"
+#include "IPC/Serializing/IPCSerializer.h"
+#include <core/render/manager/render_manager.h>
+#include <jni.h>
+#include <sys/types.h>
+
+
+static std::unique_ptr<IPCResult> handleSetJSVersion(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleReportException(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleCallNative(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleCallNativeModule(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleCallNativeComponent(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleCallAddElement(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleSetTimeout(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleCallNativeLog(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallCreateBody(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallUpdateFinish(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallCreateFinish(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallRefreshFinish(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallUpdateAttrs(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallUpdateStyle(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallRemoveElement(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallMoveElement(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallAddEvent(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> functionCallRemoveEvent(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleSetInterval(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleClearInterval(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleCallGCanvasLinkNative(IPCArguments *arguments);
+
+static std::unique_ptr<IPCResult> handleT3DLinkNative(IPCArguments *arguments);
+
+
+static void reportException(const int instanceID, const char *func, const char *exception_string);
+
+namespace WeexCore {
+
+  typedef const char *(*FunType)(const char *, int, const char *);
+
+  const char *callGCanvasFun(FunType fp, const char *conextId, int x, const char *args);
+
+  extern "C" void Inject_GCanvasFunc(FunType fp);
+
+  typedef const char* (*FunTypeT3d)(int, const char*);
+
+  const char* weexCallT3dFunc(FunTypeT3d fp, int x, const char* args);
+
+  extern "C" void Inject_T3dFunc(FunTypeT3d fp);
+
+  class ExtendJSApi {
+  public:
+    ExtendJSApi();
+
+    void initFunction(IPCHandler *handler);
+  };
+
+} //WeexCore
+
+#endif // _EXTENSION_JSAPI_H_
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp b/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp
new file mode 100644
index 0000000..420cbb8
--- /dev/null
+++ b/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp
@@ -0,0 +1,411 @@
+#include "WeexJSConnection.h"
+
+#include "ashmem.h"
+#include <dirent.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <IPC/IPCFutexPageQueue.h>
+#include <IPC/IPCException.h>
+#include <IPC/IPCSender.h>
+#include <unistd.h>
+#include <android/base/log_utils.h>
+
+extern const char *s_cacheDir;
+extern bool s_start_pie;
+
+static void doExec(int fd, bool traceEnable, bool startupPie = true);
+
+static int copyFile(const char *SourceFile, const char *NewFile);
+
+static void closeAllButThis(int fd);
+
+static void printLogOnFile(const char *log);
+
+#if PRINT_LOG_CACHEFILE
+static std::string logFilePath = "/data/data/com.taobao.taobao/cache";
+#endif
+
+struct WeexJSConnection::WeexJSConnectionImpl {
+    std::unique_ptr<IPCSender> serverSender;
+    std::unique_ptr<IPCFutexPageQueue> futexPageQueue;
+    pid_t child{0};
+};
+
+WeexJSConnection::WeexJSConnection()
+        : m_impl(new WeexJSConnectionImpl) {
+}
+
+WeexJSConnection::~WeexJSConnection() {
+  end();
+}
+
+IPCSender *WeexJSConnection::start(IPCHandler *handler, bool reinit) {
+  int fd = ashmem_create_region("WEEX_IPC", IPCFutexPageQueue::ipc_size);
+  if (-1 == fd) {
+    throw IPCException("failed to create ashmem region: %s", strerror(errno));
+  }
+  void *base = mmap(nullptr, IPCFutexPageQueue::ipc_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+                    fd, 0);
+  if (base == MAP_FAILED) {
+    int _errno = errno;
+    close(fd);
+    throw IPCException("failed to map ashmem region: %s", strerror(_errno));
+  }
+  std::unique_ptr<IPCFutexPageQueue> futexPageQueue(
+          new IPCFutexPageQueue(base, IPCFutexPageQueue::ipc_size, 0));
+  std::unique_ptr<IPCSender> sender(createIPCSender(futexPageQueue.get(), handler));
+  m_impl->serverSender = std::move(sender);
+  m_impl->futexPageQueue = std::move(futexPageQueue);
+#if PRINT_LOG_CACHEFILE
+  if (s_cacheDir) {
+    logFilePath = s_cacheDir;
+  }
+  logFilePath.append("/jsserver_start.log");
+  std::ofstream mcfile;
+  if (reinit) {
+    mcfile.open(logFilePath, std::ios::app);
+    mcfile << "restart fork a process" << std::endl;
+  } else {
+    mcfile.open(logFilePath);
+    mcfile << "start fork a process" << std::endl;
+  }
+#endif
+
+  static bool startupPie = s_start_pie;
+  LOGE("startupPie :%d", startupPie);
+
+  pid_t child;
+  if (reinit) {
+#if PRINT_LOG_CACHEFILE
+    mcfile << "reinit is ture use vfork" << std::endl;
+    mcfile.close();
+#endif
+    child = vfork();
+  } else {
+#if PRINT_LOG_CACHEFILE
+    mcfile << "reinit is false use fork" << std::endl;
+    mcfile.close();
+#endif
+    child = fork();
+  }
+  if (child == -1) {
+    int myerrno = errno;
+    munmap(base, IPCFutexPageQueue::ipc_size);
+    close(fd);
+    throw IPCException("failed to fork: %s", strerror(myerrno));
+  } else if (child == 0) {
+    // the child
+    closeAllButThis(fd);
+    // implements close all but handles[1]
+    // do exec
+    doExec(fd, true, startupPie);
+    LOGE("exec Failed completely.");
+    // failed to exec
+    _exit(1);
+  } else {
+    printLogOnFile("fork success on main process and start m_impl->futexPageQueue->spinWaitPeer()");
+    close(fd);
+    m_impl->child = child;
+    try {
+      m_impl->futexPageQueue->spinWaitPeer();
+    } catch (IPCException &e) {
+      LOGE("WeexJSConnection catch: %s", e.msg());
+      // TODO throw exception
+      return nullptr;
+    }
+  }
+  return m_impl->serverSender.get();
+}
+
+void WeexJSConnection::end() {
+  m_impl->serverSender.reset();
+  m_impl->futexPageQueue.reset();
+  if (m_impl->child) {
+    int wstatus;
+    pid_t child;
+    kill(m_impl->child, 9);
+    while (true) {
+      child = waitpid(m_impl->child, &wstatus, 0);
+      if (child != -1)
+        break;
+      if (errno != EINTR)
+        break;
+    }
+  }
+}
+
+void printLogOnFile(const char *log) {
+#if PRINT_LOG_CACHEFILE
+  std::ofstream mcfile;
+  mcfile.open(logFilePath, std::ios::app);
+  mcfile << log << std::endl;
+  mcfile.close();
+#endif
+}
+
+static std::string __attribute__((noinline)) findPath();
+
+static void findPath(std::string &executablePath, std::string &icuDataPath) {
+  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))) {
+    if (icuDataPath.empty() && strstr(line, "icudt")) {
+      icuDataPath.assign(strstr(line, "/"));
+      icuDataPath = icuDataPath.substr(0, icuDataPath.length() - 1);
+      continue;
+    }
+    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) {
+      executablePath.assign(strstr(end, "/"));
+      std::size_t found = executablePath.rfind('/');
+      if (found != std::string::npos) {
+        executablePath = executablePath.substr(0, found);
+      }
+    }
+    if (!executablePath.empty()
+        && !icuDataPath.empty()) {
+      break;
+    }
+  }
+  fclose(f);
+  return;
+}
+
+class EnvPBuilder {
+public:
+    EnvPBuilder();
+
+    ~EnvPBuilder() = default;
+
+    void addNew(const char *n);
+
+    std::unique_ptr<const char *[]> build();
+
+private:
+    std::vector<const char *> m_vec;
+};
+
+EnvPBuilder::EnvPBuilder() {
+  for (char **env = environ; *env; env++) {
+    // fixme:add for ANDROID_ROOT envp
+    // if cannot find some env, can use such as
+    // PATH/ANDROID_BOOTLOGO/ANDROID_ASSETS/ANDROID_DATA/ASEC_MOUNTPOINT
+    // LOOP_MOUNTPOINT/BOOTCLASSPATH and etc
+    // but don't use LD_LIBRARY_PATH env may cause so cannot be found
+    const char *android_root_env = "ANDROID_ROOT=";
+    if (strstr(*env, android_root_env) != nullptr) {
+      addNew(*env);
+      break;
+    }
+  }
+}
+
+void EnvPBuilder::addNew(const char *n) {
+  m_vec.emplace_back(n);
+}
+
+std::unique_ptr<const char *[]> EnvPBuilder::build() {
+  std::unique_ptr<const char *[]> ptr(new const char *[m_vec.size() + 1]);
+  for (size_t i = 0; i < m_vec.size(); ++i) {
+    ptr.get()[i] = m_vec[i];
+  }
+  ptr.get()[m_vec.size()] = nullptr;
+  return ptr;
+}
+
+void doExec(int fd, bool traceEnable, bool startupPie) {
+  std::string executablePath;
+  std::string icuDataPath;
+  findPath(executablePath, icuDataPath);
+#if PRINT_LOG_CACHEFILE
+  std::ofstream mcfile;
+  mcfile.open(logFilePath, std::ios::app);
+  mcfile << "jsengine WeexJSConnection::doExec executablePath:" << executablePath << std::endl;
+  mcfile << "jsengine WeexJSConnection::doExec icuDataPath:" << icuDataPath << std::endl;
+#endif
+
+  if (executablePath.empty()) {
+    LOGE("executablePath is empty");
+
+#if PRINT_LOG_CACHEFILE
+    mcfile << "jsengine WeexJSConnection::doExec executablePath is empty and return" << std::endl;
+    mcfile.close();
+#endif
+
+    return;
+  }
+  if (icuDataPath.empty()) {
+    LOGE("icuDataPath is empty");
+#if PRINT_LOG_CACHEFILE
+    mcfile << "jsengine WeexJSConnection::doExec icuDataPath is empty and return" << std::endl;
+    mcfile.close();
+#endif
+    return;
+  }
+  std::string ldLibraryPathEnv("LD_LIBRARY_PATH=");
+  std::string icuDataPathEnv("ICU_DATA_PATH=");
+  std::string crashFilePathEnv("CRASH_FILE_PATH=");
+  ldLibraryPathEnv.append(executablePath);
+  icuDataPathEnv.append(icuDataPath);
+#if PRINT_LOG_CACHEFILE
+  mcfile << "jsengine ldLibraryPathEnv:" << ldLibraryPathEnv << " icuDataPathEnv:" << icuDataPathEnv
+         << std::endl;
+#endif
+  if (!s_cacheDir) {
+    crashFilePathEnv.append("/data/data/com.taobao.taobao/cache");
+  } else {
+    crashFilePathEnv.append(s_cacheDir);
+  }
+  crashFilePathEnv.append("/jsserver_crash");
+  char fdStr[16];
+  snprintf(fdStr, 16, "%d", fd);
+  EnvPBuilder envpBuilder;
+  envpBuilder.addNew(ldLibraryPathEnv.c_str());
+  envpBuilder.addNew(icuDataPathEnv.c_str());
+  envpBuilder.addNew(crashFilePathEnv.c_str());
+  auto envp = envpBuilder.build();
+  {
+    std::string executableName = executablePath + '/' + "libweexjsb64.so";
+    chmod(executableName.c_str(), 0755);
+    const char *argv[] = {executableName.c_str(), fdStr, traceEnable ? "1" : "0", nullptr};
+    if (-1 == execve(argv[0], const_cast<char *const *>(&argv[0]),
+                     const_cast<char *const *>(envp.get()))) {
+    }
+  }
+
+  std::string start_so = "";
+  if (startupPie) {
+    start_so = "libweexjsb.so";
+  } else {
+    start_so = "libweexjst.so";
+  }
+
+  {
+    std::string executableName = executablePath + '/' + start_so;
+    chmod(executableName.c_str(), 0755);
+    int result = access(executableName.c_str(), 01);
+
+#if PRINT_LOG_CACHEFILE
+    mcfile << "jsengine WeexJSConnection::doExec file exsist result:"
+           << result << " startupPie:" << startupPie << std::endl;
+#endif
+    if (result == -1) {
+      executableName = std::string(s_cacheDir) + '/' + start_so;
+      int result_cache = access(executableName.c_str(), 00);
+      if (result_cache == -1) {
+        std::string sourceSo = executablePath + '/' + start_so;
+        int ret = copyFile(sourceSo.c_str(), executableName.c_str());
+#if PRINT_LOG_CACHEFILE
+        mcfile << "jsengine WeexJSConnection::doExec copy so from:" << sourceSo
+               << " to:" << executableName << ", success: " << ret << std::endl;
+#endif
+      }
+      chmod(executableName.c_str(), 0755);
+#if PRINT_LOG_CACHEFILE
+      mcfile << "jsengine WeexJSConnection::doExec start path on sdcard, start execve so name:"
+             << executableName << std::endl;
+#endif
+      const char *argv[] = {executableName.c_str(), fdStr, traceEnable ? "1" : "0", nullptr};
+      if (-1 == execve(argv[0], const_cast<char *const *>(&argv[0]),
+                       const_cast<char *const *>(envp.get()))) {
+#if PRINT_LOG_CACHEFILE
+        mcfile << "execve failed11:" << strerror(errno) << std::endl;
+#endif
+      }
+    } else {
+      // std::string executableName = executablePath + '/' + "libweexjsb.so";
+      chmod(executableName.c_str(), 0755);
+#if PRINT_LOG_CACHEFILE
+      mcfile << "jsengine WeexJSConnection::doExec start execve so name:" << executableName
+             << std::endl;
+#endif
+      const char *argv[] = {executableName.c_str(), fdStr, traceEnable ? "1" : "0", nullptr};
+      if (-1 == execve(argv[0], const_cast<char *const *>(&argv[0]),
+                       const_cast<char *const *>(envp.get()))) {
+#if PRINT_LOG_CACHEFILE
+        mcfile << "execve failed:" << strerror(errno) << std::endl;
+#endif
+      }
+    }
+
+  }
+#if PRINT_LOG_CACHEFILE
+  mcfile.close();
+#endif
+}
+
+static void closeAllButThis(int exceptfd) {
+  DIR *dir = opendir("/proc/self/fd");
+  if (!dir) {
+    return;
+  }
+  int dirFd = dirfd(dir);
+  struct dirent *cur;
+  struct timespec start;
+  clock_gettime(CLOCK_MONOTONIC, &start);
+  while ((cur = readdir(dir))) {
+    struct timespec now;
+    clock_gettime(CLOCK_MONOTONIC, &now);
+    if ((now.tv_sec - start.tv_sec) > 6) {
+      break;
+    }
+    if (!strcmp(cur->d_name, ".")
+        || !strcmp(cur->d_name, "..")) {
+      continue;
+    }
+    errno = 0;
+    unsigned long curFd = strtoul(cur->d_name, nullptr, 10);
+    if (errno)
+      continue;
+    if (curFd <= 2)
+      continue;
+    if ((curFd != dirFd) && (curFd != exceptfd)) {
+      close(curFd);
+    }
+  }
+  closedir(dir);
+}
+
+int copyFile(const char *SourceFile, const char *NewFile) {
+  std::ifstream in;
+  std::ofstream out;
+  in.open(SourceFile, std::ios::binary);
+  if (in.fail()) {
+    in.close();
+    out.close();
+    return 0;
+  }
+  out.open(NewFile, std::ios::binary);
+  if (out.fail()) {
+    out.close();
+    in.close();
+    return 0;
+  } else {
+    out << in.rdbuf();
+    out.close();
+    in.close();
+    return 1;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.h b/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.h
new file mode 100644
index 0000000..e09a51c
--- /dev/null
+++ b/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.h
@@ -0,0 +1,25 @@
+#ifndef WEEXJSCONNECTION_H
+#define WEEXJSCONNECTION_H
+
+#include <memory>
+
+class IPCSender;
+class IPCHandler;
+
+class WeexJSConnection {
+public:
+    WeexJSConnection();
+
+    ~WeexJSConnection();
+
+    IPCSender *start(IPCHandler *handler, bool reinit = false);
+
+    void end();
+
+private:
+    struct WeexJSConnectionImpl;
+
+    std::unique_ptr<WeexJSConnectionImpl> m_impl;
+};
+
+#endif /* WEEXJSCONNECTION_H */

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/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
new file mode 100644
index 0000000..5bb2a8a
--- /dev/null
+++ b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp
@@ -0,0 +1,690 @@
+// Copyright [2017-12-07] <WeexCore>
+#include "WeexProxy.h"
+
+#include <android/base/log_utils.h>
+#include <android/base/string/string_utils.h>
+#include <core/config/core_environment.h>
+#include <android/jsengine/multiprocess/ExtendJSApi.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;
+
+
+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");
+        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);
+  }
+#define ADDSTRING(name)                                     \
+    {                                                       \
+        const char* myname = #name;                         \
+        serializer->add(myname, strlen(myname));            \
+        ScopedJStringUTF8 scopedString(env, (jstring)name); \
+        const char* chars = scopedString.getChars();        \
+        int charLength = strlen(chars);                     \
+        serializer->add(chars, charLength);                 \
+    }
+  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("");
+  }
+}
+
+}  // namespace WeexCore

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h
new file mode 100644
index 0000000..942f619
--- /dev/null
+++ b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h
@@ -0,0 +1,76 @@
+#ifndef _WEEX_PROXY_H_
+#define _WEEX_PROXY_H_
+
+
+#include <jni.h>
+#include <unistd.h>
+#include <IPC/Serializing/IPCSerializer.h>
+#include <IPC/IPCHandler.h>
+#include <android/bridge/impl/bridge_impl_android.h>
+#include <IPC/Buffering/IPCBuffer.h>
+#include <IPC/IPCArguments.h>
+#include <IPC/IPCByteArray.h>
+#include <IPC/IPCException.h>
+#include <IPC/IPCHandler.h>
+#include <IPC/IPCMessageJS.h>
+#include <IPC/IPCResult.h>
+#include <IPC/IPCSender.h>
+#include <IPC/IPCString.h>
+#include <IPC/Serializing/IPCSerializer.h>
+
+namespace WeexCore {
+
+class WeexProxy {
+private:
+public:
+    static void reset();
+
+    static jint doInitFramework(JNIEnv *env, jobject object, jstring script, jobject params,
+                                jstring cacheDir, jboolean pieSupport);
+
+    static jint doInitFramework(JNIEnv *env, jobject object, jstring script, jobject params);
+
+    static void
+    initFromParam(JNIEnv *env, jstring script, jobject params, IPCSerializer *serializer);
+
+    static const char *getCacheDir(JNIEnv *env);
+
+    static void setCacheDir(JNIEnv *env);
+
+    static bool execJSService(JNIEnv *env, jobject object, jstring script);
+
+    static bool
+    execJS(JNIEnv *env, jobject jthis, jstring jinstanceid, jstring jnamespace, jstring jfunction,
+           jobjectArray jargs);
+
+    static void
+    reportException(const char *instanceID, const char *func, const char *exception_string);
+
+    static void reportServerCrash(jstring jinstanceid);
+
+    static jbyteArray execJSWithResult(JNIEnv* env, jobject jthis,
+                                       jstring jinstanceid,
+                                       jstring jnamespace,
+                                       jstring jfunction,
+                                       jobjectArray jargs);
+
+    static void updateGlobalConfig(JNIEnv* env, jobject jcaller,
+                                 jstring config);
+    static jint createInstanceContext(JNIEnv* env, jobject jcaller, jstring instanceId,
+                                             jstring name,
+                                             jstring function,
+                                             jobjectArray args);
+
+    static jint destoryInstance(JNIEnv* env, jobject jcaller,
+                                jstring instanceId,
+                                jstring name,
+                                jstring function,
+                                jobjectArray args);
+
+    static jstring execJSOnInstance(JNIEnv* env, jobject jcaller,
+                                    jstring instanceId,
+                                    jstring script,
+                                    jint type);
+};
+}
+#endif //_WEEX_PROXY_H_

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/Compatible.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/Compatible.cpp b/weex_core/Source/base/Compatible.cpp
new file mode 100644
index 0000000..3fb0e5c
--- /dev/null
+++ b/weex_core/Source/base/Compatible.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <grp.h>
+#include <math.h>
+#include <mntent.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+namespace WeexCore {
+int sigemptyset(sigset_t *set) {
+  if (set == NULL) {
+    errno = EINVAL;
+    return -1;
+  }
+  memset(set, 0, sizeof(sigset_t));
+  return 0;
+}
+
+int sigfillset(sigset_t *set) {
+  if (set == NULL) {
+    errno = EINVAL;
+    return -1;
+  }
+  memset(set, ~0, sizeof(sigset_t));
+  return 0;
+}
+
+int sigaddset(sigset_t *set, int signum) {
+  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+  unsigned long *local_set = reinterpret_cast<unsigned long *>(set);
+  if (set == NULL || bit < 0 || bit >= static_cast<int>(8 * sizeof(sigset_t))) {
+    errno = EINVAL;
+    return -1;
+  }
+  local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
+  return 0;
+}
+
+int sigdelset(sigset_t *set, int signum) {
+  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+  unsigned long *local_set = reinterpret_cast<unsigned long *>(set);
+  if (set == NULL || bit < 0 || bit >= static_cast<int>(8 * sizeof(sigset_t))) {
+    errno = EINVAL;
+    return -1;
+  }
+  local_set[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT));
+  return 0;
+}
+
+int getpagesize() {
+  // We dont use sysconf(3) here because that drags in stdio, which makes static binaries fat.
+  return PAGE_SIZE;
+}
+
+void srandom(unsigned int __s) { srand48(__s); }
+
+int isinf(double n) {
+  return __builtin_isinf(n);
+}
+
+int posix_memalign(void **memptr, size_t alignment, size_t bytes) {
+  if (!memptr)
+    return EINVAL;
+  *memptr = memalign(alignment, bytes);
+  if (!*memptr)
+    return ENOMEM;
+  return 0;
+}
+
+int sigismember(const sigset_t *set, int signum) {
+  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+  const unsigned long *local_set = reinterpret_cast<const unsigned long *>(set);
+  if (set == NULL || bit < 0 || bit >= static_cast<int>(8 * sizeof(sigset_t))) {
+    errno = EINVAL;
+    return -1;
+  }
+  return static_cast<int>((local_set[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1);
+}
+
+int abs(int j) {
+  return (j < 0 ? -j : j);
+}
+
+long labs(long j) {
+  return (j < 0 ? -j : j);
+}
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/CoreConstants.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/CoreConstants.h b/weex_core/Source/base/CoreConstants.h
new file mode 100644
index 0000000..d918a7c
--- /dev/null
+++ b/weex_core/Source/base/CoreConstants.h
@@ -0,0 +1,10 @@
+
+#ifndef WEEXV8_CONSTANTSNAME_H
+#define WEEXV8_CONSTANTSNAME_H
+
+#include <string>
+
+const std::string OS_Android = "android";
+const std::string OS_iOS = "iOS";
+
+#endif //WEEXV8_CONSTANTSNAME_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/TimeUtils.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/TimeUtils.h b/weex_core/Source/base/TimeUtils.h
new file mode 100644
index 0000000..072d9be
--- /dev/null
+++ b/weex_core/Source/base/TimeUtils.h
@@ -0,0 +1,12 @@
+#ifndef WEEX_PROJECT_TIMEUTILS_H
+#define WEEX_PROJECT_TIMEUTILS_H
+
+#include <sys/time.h>
+
+static long long getCurrentTime() {
+  struct timeval tv;
+  gettimeofday(&tv, NULL);
+  return (long long) tv.tv_sec * 1000 + (long long) tv.tv_usec / 1000;
+}
+
+#endif //WEEX_PROJECT_TIMEUTILS_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/ViewUtils.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/ViewUtils.h b/weex_core/Source/base/ViewUtils.h
new file mode 100644
index 0000000..624c510
--- /dev/null
+++ b/weex_core/Source/base/ViewUtils.h
@@ -0,0 +1,102 @@
+#ifndef WEEX_PROJECT_VIEWUTILS_H
+#define WEEX_PROJECT_VIEWUTILS_H
+
+#include <core/config/core_environment.h>
+#include <cmath>
+#include <cstdlib>
+
+namespace WeexCore {
+
+  const std::string WX("wx");
+  const std::string PX("px");
+  const std::string UNDEFINE("undefined");
+  const std::string SCALE("scale");
+  const std::string AUTO_UNIT("auto");
+  const std::string NONE("none");
+
+  inline std::string &Trim(std::string &s) {
+    if (s.empty()) {
+      return s;
+    }
+    s.erase(0, s.find_first_not_of(" "));
+    s.erase(s.find_last_not_of(" ") + 1);
+    return s;
+  }
+
+  inline float getFloat(const char* src) {
+    char *end;
+    float ret = strtof(src, &end);
+    if(*end != '\0'){
+      ret = NAN;
+    }
+    return ret;
+  }
+
+  inline float getFloat(const float &src, const float &viewport) {
+    if (isnan(src))
+      return NAN;
+
+    float realPx = (src * WXCoreEnvironment::getInstance()->DeviceWidth() /
+                    viewport);
+    float result = realPx > 0.005 && realPx < 1 ? 1 : rint(realPx);
+    return result;
+  }
+
+  inline float getFloat(const std::string &src, const float &viewport) {
+    float ret = NAN;
+    if (UNDEFINE == src
+        || AUTO_UNIT == src
+        || NONE == src
+        || src.empty()) {
+      return ret;
+    }
+    float original_value = getFloat(src.c_str());
+    ret = getFloat(original_value, viewport);
+    return ret;
+  }
+
+  inline bool endWidth(const std::string &src, const std::string &suffix) {
+    return src.size() > suffix.size() &&
+           src.compare(src.size() - suffix.size(), suffix.size(), suffix) == 0;
+  }
+
+  inline float transferWx(const std::string &stringWithWXPostfix, const float &viewport) {
+    std::string temp = stringWithWXPostfix;
+    if (endWidth(stringWithWXPostfix, WX)) {
+      temp = stringWithWXPostfix.substr(0, stringWithWXPostfix.size() - WX.size());
+    }
+    float f = getFloat(temp.c_str());
+    float density = getFloat(WXCoreEnvironment::getInstance()->GetOption(SCALE).c_str());
+    return density * f * viewport / WXCoreEnvironment::getInstance()->DeviceWidth();
+  }
+
+  inline static float getFloatByViewport(std::string src, const float &viewport) {
+    float ret = NAN;
+    if (UNDEFINE == src
+        || AUTO_UNIT == src
+        || NONE == src
+        || src.empty()) {
+      return ret;
+    }
+    Trim(src);
+    if (endWidth(src, WX)) {
+      ret = getFloat(transferWx(src, viewport), viewport);
+    } else if (endWidth(src, PX)) {
+      ret = getFloat(src.substr(0, src.size() - PX.size()), viewport);
+    } else {
+      ret = getFloat(src, viewport);
+    }
+    return ret;
+  }
+
+  inline static float getWebPxByWidth(float pxValue, float customViewport) {
+    if (isnan(pxValue))
+      return NAN;
+
+    float realPx = (pxValue * customViewport / WXCoreEnvironment::getInstance()->DeviceWidth());
+    float result = realPx > 0.005 && realPx < 1 ? 1 : rint(realPx);
+    return result;
+  }
+}
+
+#endif //WEEX_PROJECT_VIEWUTILS_H

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/fpconv.cpp
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/fpconv.cpp b/weex_core/Source/base/fpconv.cpp
new file mode 100755
index 0000000..3fbd55a
--- /dev/null
+++ b/weex_core/Source/base/fpconv.cpp
@@ -0,0 +1,332 @@
+#include <stdbool.h>
+#include <string.h>
+
+#include "fpconv.h"
+#include "powers.h"
+
+#define fracmask  0x000FFFFFFFFFFFFFU
+#define expmask   0x7FF0000000000000U
+#define hiddenbit 0x0010000000000000U
+#define signmask  0x8000000000000000U
+#define expbias   (1023 + 52)
+
+#define absv(n) ((n) < 0 ? -(n) : (n))
+#define minv(a, b) ((a) < (b) ? (a) : (b))
+
+static uint64_t tens[] = {
+    10000000000000000000U, 1000000000000000000U, 100000000000000000U,
+    10000000000000000U, 1000000000000000U, 100000000000000U,
+    10000000000000U, 1000000000000U, 100000000000U,
+    10000000000U, 1000000000U, 100000000U,
+    10000000U, 1000000U, 100000U,
+    10000U, 1000U, 100U,
+    10U, 1U
+};
+
+static inline uint64_t get_dbits(double d)
+{
+    union {
+        double   dbl;
+        uint64_t i;
+    } dbl_bits = { d };
+
+    return dbl_bits.i;
+}
+
+static Fp build_fp(double d)
+{
+    uint64_t bits = get_dbits(d);
+
+    Fp fp;
+    fp.frac = bits & fracmask;
+    fp.exp = (bits & expmask) >> 52;
+
+    if(fp.exp) {
+        fp.frac += hiddenbit;
+        fp.exp -= expbias;
+
+    } else {
+        fp.exp = -expbias + 1;
+    }
+
+    return fp;
+}
+
+static void normalize(Fp* fp)
+{
+    while ((fp->frac & hiddenbit) == 0) {
+        fp->frac <<= 1;
+        fp->exp--;
+    }
+
+    int shift = 64 - 52 - 1;
+    fp->frac <<= shift;
+    fp->exp -= shift;
+}
+
+static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper)
+{
+    upper->frac = (fp->frac << 1) + 1;
+    upper->exp  = fp->exp - 1;
+
+    while ((upper->frac & (hiddenbit << 1)) == 0) {
+        upper->frac <<= 1;
+        upper->exp--;
+    }
+
+    int u_shift = 64 - 52 - 2;
+
+    upper->frac <<= u_shift;
+    upper->exp = upper->exp - u_shift;
+
+
+    int l_shift = fp->frac == hiddenbit ? 2 : 1;
+
+    lower->frac = (fp->frac << l_shift) - 1;
+    lower->exp = fp->exp - l_shift;
+
+
+    lower->frac <<= lower->exp - upper->exp;
+    lower->exp = upper->exp;
+}
+
+static Fp multiply(Fp* a, Fp* b)
+{
+    const uint64_t lomask = 0x00000000FFFFFFFF;
+
+    uint64_t ah_bl = (a->frac >> 32)    * (b->frac & lomask);
+    uint64_t al_bh = (a->frac & lomask) * (b->frac >> 32);
+    uint64_t al_bl = (a->frac & lomask) * (b->frac & lomask);
+    uint64_t ah_bh = (a->frac >> 32)    * (b->frac >> 32);
+
+    uint64_t tmp = (ah_bl & lomask) + (al_bh & lomask) + (al_bl >> 32); 
+    /* round up */
+    tmp += 1U << 31;
+
+    Fp fp = {
+        ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32),
+        a->exp + b->exp + 64
+    };
+
+    return fp;
+}
+
+static void round_digit(char* digits, int ndigits, uint64_t delta, uint64_t rem, uint64_t kappa, uint64_t frac)
+{
+    while (rem < frac && delta - rem >= kappa &&
+           (rem + kappa < frac || frac - rem > rem + kappa - frac)) {
+
+        digits[ndigits - 1]--;
+        rem += kappa;
+    }
+}
+
+static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
+{
+    uint64_t wfrac = upper->frac - fp->frac;
+    uint64_t delta = upper->frac - lower->frac;
+
+    Fp one;
+    one.frac = 1ULL << -upper->exp;
+    one.exp  = upper->exp;
+
+    uint64_t part1 = upper->frac >> -one.exp;
+    uint64_t part2 = upper->frac & (one.frac - 1);
+
+    int idx = 0, kappa = 10;
+    uint64_t* divp;
+    /* 1000000000 */
+    for(divp = tens + 10; kappa > 0; divp++) {
+
+        uint64_t div = *divp;
+        unsigned digit = part1 / div;
+
+        if (digit || idx) {
+            digits[idx++] = digit + '0';
+        }
+
+        part1 -= digit * div;
+        kappa--;
+
+        uint64_t tmp = (part1 <<-one.exp) + part2;
+        if (tmp <= delta) {
+            *K += kappa;
+            round_digit(digits, idx, delta, tmp, div << -one.exp, wfrac);
+
+            return idx;
+        }
+    }
+
+    /* 10 */
+    uint64_t* unit = tens + 18;
+
+    while(true) {
+        part2 *= 10;
+        delta *= 10;
+        kappa--;
+
+        unsigned digit = part2 >> -one.exp;
+        if (digit || idx) {
+            digits[idx++] = digit + '0';
+        }
+
+        part2 &= one.frac - 1;
+        if (part2 < delta) {
+            *K += kappa;
+            round_digit(digits, idx, delta, part2, one.frac, wfrac * *unit);
+
+            return idx;
+        }
+
+        unit--;
+    }
+}
+
+static int grisu2(double d, char* digits, int* K)
+{
+    Fp w = build_fp(d);
+
+    Fp lower, upper;
+    get_normalized_boundaries(&w, &lower, &upper);
+
+    normalize(&w);
+
+    int k;
+    Fp cp = find_cachedpow10(upper.exp, &k);
+
+    w     = multiply(&w,     &cp);
+    upper = multiply(&upper, &cp);
+    lower = multiply(&lower, &cp);
+
+    lower.frac++;
+    upper.frac--;
+
+    *K = -k;
+
+    return generate_digits(&w, &upper, &lower, digits, K);
+}
+
+static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg)
+{
+    int exp = absv(K + ndigits - 1);
+
+    /* write plain integer */
+    if(K >= 0 && (exp < (ndigits + 7))) {
+        memcpy(dest, digits, ndigits);
+        memset(dest + ndigits, '0', K);
+
+        return ndigits + K;
+    }
+
+    /* write decimal w/o scientific notation */
+    if(K < 0 && (K > -7 || exp < 4)) {
+        int offset = ndigits - absv(K);
+        /* fp < 1.0 -> write leading zero */
+        if(offset <= 0) {
+            offset = -offset;
+            dest[0] = '0';
+            dest[1] = '.';
+            memset(dest + 2, '0', offset);
+            memcpy(dest + offset + 2, digits, ndigits);
+
+            return ndigits + 2 + offset;
+
+        /* fp > 1.0 */
+        } else {
+            memcpy(dest, digits, offset);
+            dest[offset] = '.';
+            memcpy(dest + offset + 1, digits + offset, ndigits - offset);
+
+            return ndigits + 1;
+        }
+    }
+
+    /* write decimal w/ scientific notation */
+    ndigits = minv(ndigits, 18 - neg);
+
+    int idx = 0;
+    dest[idx++] = digits[0];
+
+    if(ndigits > 1) {
+        dest[idx++] = '.';
+        memcpy(dest + idx, digits + 1, ndigits - 1);
+        idx += ndigits - 1;
+    }
+
+    dest[idx++] = 'e';
+
+    char sign = K + ndigits - 1 < 0 ? '-' : '+';
+    dest[idx++] = sign;
+
+    int cent = 0;
+
+    if(exp > 99) {
+        cent = exp / 100;
+        dest[idx++] = cent + '0';
+        exp -= cent * 100;
+    }
+    if(exp > 9) {
+        int dec = exp / 10;
+        dest[idx++] = dec + '0';
+        exp -= dec * 10;
+
+    } else if(cent) {
+        dest[idx++] = '0';
+    }
+
+    dest[idx++] = exp % 10 + '0';
+
+    return idx;
+}
+
+static int filter_special(double fp, char* dest)
+{
+    if(fp == 0.0) {
+        dest[0] = '0';
+        return 1;
+    }
+
+    uint64_t bits = get_dbits(fp);
+
+    bool nan = (bits & expmask) == expmask;
+
+    if(!nan) {
+        return 0;
+    }
+
+    if(bits & fracmask) {
+        dest[0] = 'n'; dest[1] = 'a'; dest[2] = 'n';
+
+    } else {
+        dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f';
+    }
+
+    return 3;
+}
+
+int fpconv_dtoa(double d, char dest[24])
+{
+    char digits[18];
+
+    int str_len = 0;
+    bool neg = false;
+
+    if(get_dbits(d) & signmask) {
+        dest[0] = '-';
+        str_len++;
+        neg = true;
+    }
+
+    int spec = filter_special(d, dest + str_len);
+
+    if(spec) {
+        return str_len + spec;
+    }
+
+    int K = 0;
+    int ndigits = grisu2(d, digits, &K);
+
+    str_len += emit_digits(digits, ndigits, dest + str_len, K, neg);
+
+    return str_len;
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/fpconv.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/fpconv.h b/weex_core/Source/base/fpconv.h
new file mode 100755
index 0000000..58bbccc
--- /dev/null
+++ b/weex_core/Source/base/fpconv.h
@@ -0,0 +1,33 @@
+#ifndef FPCONV_H
+#define FPCONV_H
+
+/* Fast and accurate double to string conversion based on Florian Loitsch's
+ * Grisu-algorithm[1].
+ *
+ * Input:
+ * fp -> the double to convert, dest -> destination buffer.
+ * The generated string will never be longer than 24 characters.
+ * Make sure to pass a pointer to at least 24 bytes of memory.
+ * The emitted string will not be null terminated.
+ *
+ * Output:
+ * The number of written characters.
+ *
+ * Exemplary usage:
+ *
+ * void print(double d)
+ * {
+ *      char buf[24 + 1] // plus null terminator
+ *      int str_len = fpconv_dtoa(d, buf);
+ *
+ *      buf[str_len] = '\0';
+ *      printf("%s", buf);
+ * }
+ *
+ */
+
+int fpconv_dtoa(double fp, char dest[24]);
+
+#endif
+
+/* [1] http://florian.loitsch.com/publications/dtoa-pldi2010.pdf */

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/2f8caedb/weex_core/Source/base/powers.h
----------------------------------------------------------------------
diff --git a/weex_core/Source/base/powers.h b/weex_core/Source/base/powers.h
new file mode 100755
index 0000000..52e5da5
--- /dev/null
+++ b/weex_core/Source/base/powers.h
@@ -0,0 +1,129 @@
+#include <stdint.h>
+
+#define npowers     87
+#define steppowers  8
+#define firstpower -348 /* 10 ^ -348 */
+
+#define expmax     -32
+#define expmin     -60
+
+
+typedef struct Fp {
+    uint64_t frac;
+    int exp;
+} Fp;
+
+static Fp powers_ten[] = {
+        {18054884314459144840U, -1220},
+        {13451937075301367670U, -1193},
+        {10022474136428063862U, -1166},
+        {14934650266808366570U, -1140},
+        {11127181549972568877U, -1113},
+        {16580792590934885855U, -1087},
+        {12353653155963782858U, -1060},
+        {18408377700990114895U, -1034},
+        {13715310171984221708U, -1007},
+        {10218702384817765436U, -980},
+        {15227053142812498563U, -954},
+        {11345038669416679861U, -927},
+        {16905424996341287883U, -901},
+        {12595523146049147757U, -874},
+        {9384396036005875287U,  -847},
+        {13983839803942852151U, -821},
+        {10418772551374772303U, -794},
+        {15525180923007089351U, -768},
+        {11567161174868858868U, -741},
+        {17236413322193710309U, -715},
+        {12842128665889583758U, -688},
+        {9568131466127621947U,  -661},
+        {14257626930069360058U, -635},
+        {10622759856335341974U, -608},
+        {15829145694278690180U, -582},
+        {11793632577567316726U, -555},
+        {17573882009934360870U, -529},
+        {13093562431584567480U, -502},
+        {9755464219737475723U,  -475},
+        {14536774485912137811U, -449},
+        {10830740992659433045U, -422},
+        {16139061738043178685U, -396},
+        {12024538023802026127U, -369},
+        {17917957937422433684U, -343},
+        {13349918974505688015U, -316},
+        {9946464728195732843U,  -289},
+        {14821387422376473014U, -263},
+        {11042794154864902060U, -236},
+        {16455045573212060422U, -210},
+        {12259964326927110867U, -183},
+        {18268770466636286478U, -157},
+        {13611294676837538539U, -130},
+        {10141204801825835212U, -103},
+        {15111572745182864684U, -77},
+        {11258999068426240000U, -50},
+        {16777216000000000000U, -24},
+        {12500000000000000000U, 3},
+        {9313225746154785156U,  30},
+        {13877787807814456755U, 56},
+        {10339757656912845936U, 83},
+        {15407439555097886824U, 109},
+        {11479437019748901445U, 136},
+        {17105694144590052135U, 162},
+        {12744735289059618216U, 189},
+        {9495567745759798747U,  216},
+        {14149498560666738074U, 242},
+        {10542197943230523224U, 269},
+        {15709099088952724970U, 295},
+        {11704190886730495818U, 322},
+        {17440603504673385349U, 348},
+        {12994262207056124023U, 375},
+        {9681479787123295682U,  402},
+        {14426529090290212157U, 428},
+        {10748601772107342003U, 455},
+        {16016664761464807395U, 481},
+        {11933345169920330789U, 508},
+        {17782069995880619868U, 534},
+        {13248674568444952270U, 561},
+        {9871031767461413346U,  588},
+        {14708983551653345445U, 614},
+        {10959046745042015199U, 641},
+        {16330252207878254650U, 667},
+        {12166986024289022870U, 694},
+        {18130221999122236476U, 720},
+        {13508068024458167312U, 747},
+        {10064294952495520794U, 774},
+        {14996968138956309548U, 800},
+        {11173611982879273257U, 827},
+        {16649979327439178909U, 853},
+        {12405201291620119593U, 880},
+        {9242595204427927429U,  907},
+        {13772540099066387757U, 933},
+        {10261342003245940623U, 960},
+        {15290591125556738113U, 986},
+        {11392378155556871081U, 1013},
+        {16975966327722178521U, 1039},
+        {12648080533535911531U, 1066}
+};
+
+static Fp find_cachedpow10(int exp, int *k) {
+  const double one_log_ten = 0.30102999566398114;
+
+  int approx = -(exp + npowers) * one_log_ten;
+  int idx = (approx - firstpower) / steppowers;
+
+  while (1) {
+    int current = exp + powers_ten[idx].exp + 64;
+
+    if (current < expmin) {
+      idx++;
+      continue;
+    }
+
+    if (current > expmax) {
+      idx--;
+      continue;
+    }
+
+    *k = (firstpower + idx * steppowers);
+
+    return powers_ten[idx];
+  }
+}