/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.weex.bridge;

import static org.apache.weex.bridge.WXModuleManager.createDomModule;

import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RestrictTo;
import android.support.annotation.RestrictTo.Scope;
import android.support.annotation.UiThread;
import android.support.v4.util.ArrayMap;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.weex.Script;
import org.apache.weex.WXEnvironment;
import org.apache.weex.WXSDKEngine;
import org.apache.weex.WXSDKInstance;
import org.apache.weex.WXSDKManager;
import org.apache.weex.adapter.IWXConfigAdapter;
import org.apache.weex.adapter.IWXJSExceptionAdapter;
import org.apache.weex.adapter.IWXJsFileLoaderAdapter;
import org.apache.weex.adapter.IWXJscProcessManager;
import org.apache.weex.adapter.IWXUserTrackAdapter;
import org.apache.weex.common.IWXBridge;
import org.apache.weex.common.IWXDebugConfig;
import org.apache.weex.common.WXConfig;
import org.apache.weex.common.WXErrorCode;
import org.apache.weex.common.WXException;
import org.apache.weex.common.WXJSBridgeMsgType;
import org.apache.weex.common.WXJSExceptionInfo;
import org.apache.weex.common.WXRefreshData;
import org.apache.weex.common.WXRenderStrategy;
import org.apache.weex.common.WXRuntimeException;
import org.apache.weex.common.WXThread;
import org.apache.weex.dom.CSSShorthand;
import org.apache.weex.jsEngine.JSEngine;
import org.apache.weex.layout.ContentBoxMeasurement;
import org.apache.weex.performance.WXInstanceApm;
import org.apache.weex.performance.WXStateRecord;
import org.apache.weex.ui.WXComponentRegistry;
import org.apache.weex.ui.WXRenderManager;
import org.apache.weex.ui.action.ActionReloadPage;
import org.apache.weex.ui.action.BasicGraphicAction;
import org.apache.weex.ui.action.GraphicActionAddChildToRichtext;
import org.apache.weex.ui.action.GraphicActionAddElement;
import org.apache.weex.ui.action.GraphicActionAddEvent;
import org.apache.weex.ui.action.GraphicActionAppendTreeCreateFinish;
import org.apache.weex.ui.action.GraphicActionCreateBody;
import org.apache.weex.ui.action.GraphicActionCreateFinish;
import org.apache.weex.ui.action.GraphicActionLayout;
import org.apache.weex.ui.action.GraphicActionMoveElement;
import org.apache.weex.ui.action.GraphicActionRefreshFinish;
import org.apache.weex.ui.action.GraphicActionRemoveChildFromRichtext;
import org.apache.weex.ui.action.GraphicActionRemoveElement;
import org.apache.weex.ui.action.GraphicActionRemoveEvent;
import org.apache.weex.ui.action.GraphicActionRenderSuccess;
import org.apache.weex.ui.action.GraphicActionUpdateAttr;
import org.apache.weex.ui.action.GraphicActionUpdateRichtextAttr;
import org.apache.weex.ui.action.GraphicActionUpdateRichtextStyle;
import org.apache.weex.ui.action.GraphicActionUpdateStyle;
import org.apache.weex.ui.action.GraphicPosition;
import org.apache.weex.ui.action.GraphicSize;
import org.apache.weex.ui.component.WXComponent;
import org.apache.weex.ui.module.WXDomModule;
import org.apache.weex.utils.WXExceptionUtils;
import org.apache.weex.utils.WXFileUtils;
import org.apache.weex.utils.WXJsonUtils;
import org.apache.weex.utils.WXLogUtils;
import org.apache.weex.utils.WXUtils;
import org.apache.weex.utils.WXViewUtils;
import org.apache.weex.utils.WXWsonJSONSwitch;
import org.apache.weex.utils.batch.BactchExecutor;
import org.apache.weex.utils.batch.Interceptor;
import org.apache.weex.utils.tools.LogDetail;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * Manager class for communication between JavaScript and Android.
 * <ol>
 * <li>
 * Handle Android to JavaScript call, can be one of the following
 * <ul>
 * <li>{@link #createInstance(String, String, Map, String)}</li>
 * <li>{@link #destroyInstance(String)}</li>
 * <li>{@link #refreshInstance(String, WXRefreshData)}</li>
 * <li>{@link #registerModules(Map)}</li>
 * <li>{@link #registerComponents(List)}</li>
 * <li>{@link #invokeCallJSBatch(Message)}</li>
 * </ul>
 * </li>
 * <li>
 * Handle JavaScript to Android call
 * </li>
 * <li>
 * Handle next tick of message.
 * </li>
 * </ol>
 */
public class WXBridgeManager implements Callback, BactchExecutor {

  private static Class clazz_debugProxy = null;
  public static final String METHOD_CREATE_INSTANCE = "createInstance";
  public static final String METHOD_CREATE_PAGE_WITH_CONTENT = "CreatePageWithContent";
  public static final String METHOD_UPDATE_COMPONENT_WITH_DATA = "UpdateComponentData";
  private static final String METHOD_POST_TASK_TO_MSG_LOOP = "PostTaskToMsgLoop";
  private static final String METHOD_JSFM_NOT_INIT_IN_EAGLE_MODE = "JsfmNotInitInEagleMode";
  private static final String METHOD_MOVE_RENDER_OBJECT = "RenderPage::MoveRenderObject";
  public static final String METHOD_DESTROY_INSTANCE = "destroyInstance";
  public static final String METHOD_CALL_JS = "callJS";
  public static final String METHOD_SET_TIMEOUT = "setTimeoutCallback";
  public static final String METHOD_REGISTER_MODULES = "registerModules";
  public static final String METHOD_REGISTER_COMPONENTS = "registerComponents";
  public static final String METHOD_FIRE_EVENT = "fireEvent";
  public static final String METHD_FIRE_EVENT_SYNC = "fireEventSync";
  public static final String METHD_COMPONENT_HOOK_SYNC = "componentHook";
  public static final String METHOD_CALLBACK = "callback";
  public static final String METHOD_REFRESH_INSTANCE = "refreshInstance";
  public static final String METHOD_FIRE_EVENT_ON_DATA_RENDER_NODE = "fireEventOnDataRenderNode";
  public static final String METHOD_NOTIFY_TRIM_MEMORY = "notifyTrimMemory";
  public static final String METHOD_NOTIFY_SERIALIZE_CODE_CACHE =
          "notifySerializeCodeCache";
  public static final String METHOD_CREATE_INSTANCE_CONTEXT = "createInstanceContext";

  public static final String KEY_METHOD = "method";
  public static final String KEY_ARGS = "args";

  // args
  public static final String COMPONENT = "component";
  public static final String REF = "ref";
  public static final String MODULE = "module";
  public static final String METHOD = "method";
  public static final String KEY_PARAMS = "params";
  public static final String ARGS = "args";
  public static final String OPTIONS = "options";
  public static final String INITLOGFILE = "/jsserver_start.log";
  private static final String NON_CALLBACK = "-1";
  private static final String UNDEFINED = "undefined";
  private static final String BUNDLE_TYPE = "bundleType";
  private static final String RENDER_STRATEGY = "renderStrategy";
  private static final int INIT_FRAMEWORK_OK = 1;
  private static final int CRASHREINIT = 50;
  static volatile WXBridgeManager mBridgeManager;
  private static long LOW_MEM_VALUE = 120;
  public volatile static int reInitCount = 1;
  private volatile static int sInitFrameWorkCount = 0;
  private static String crashUrl = null;
  private static long lastCrashTime = 0;

  private static String mRaxApi = null;
//  private static String mRaxExtApi = null;

  // add for clound setting, default value is true
  // can use it to control weex sandbox
  // if true will open weex sandbox for multi context
  private volatile static boolean isSandBoxContext = true;

  // add for cloud setting, default value is false.
  // weexcore use single process or not
  private static boolean isUseSingleProcess = false;
  // add for cloud setting, default value is false.
  // jsEngine use multiThread or not
  private volatile static boolean isJsEngineMultiThreadEnable = false;

  public enum BundType {
    Vue,
    Rax,
    Others
  };

  private static final boolean BRIDGE_LOG_SWITCH = false;

  /**
   * Whether JS Framework(main.js) has been initialized.
   */
  private volatile static boolean mInit = false;

  private static String globalConfig = "none";
  private static String GLOBAL_CONFIG_KEY = "global_switch_config";

  private static Map<String, String> mWeexCoreEnvOptions = new HashMap<>();

  /**
   * package
   **/
  Handler mJSHandler;
  /**
   * next tick tasks, can set priority
   */
  private WXHashMap<String, ArrayList<WXHashMap<String, Object>>> mNextTickTasks = new WXHashMap<>();
  /**
   * JSThread
   */
  private WXThread mJSThread;
  private IWXBridge mWXBridge;
  private Object mWxDebugProxy;

  private boolean mMock = false;

  private List<Map<String, Object>> mRegisterComponentFailList = new ArrayList<>(8);
  private List<Map<String, Object>> mRegisterModuleFailList = new ArrayList<>(8);
  private List<String> mRegisterServiceFailList = new ArrayList<>(8);
  private HashSet<String> mDestroyedInstanceId = new HashSet<>();
  private StringBuilder mLodBuilder = new StringBuilder(50);
  private Interceptor mInterceptor;
  private WXParams mInitParams;

  private WXBridgeManager() {
    initWXBridge(WXEnvironment.sRemoteDebugMode);
    mJSThread = new WXThread("WeexJSBridgeThread", this);
    mJSHandler = mJSThread.getHandler();
  }

  public static WXBridgeManager getInstance() {
    if (mBridgeManager == null) {
      synchronized (WXBridgeManager.class) {
        if (mBridgeManager == null) {
          mBridgeManager = new WXBridgeManager();
        }
      }
    }
    return mBridgeManager;
  }

  public void setUseSingleProcess(final boolean flag) {
    if (flag != isUseSingleProcess) {
      isUseSingleProcess = flag;
//      //we should reinit framework if js framework has been initialized
//      if (isJSFrameworkInit()) {
//        if (isJSThread()) {
//          WXSDKEngine.reload();
//        } else {
//          post(new Runnable() {
//            @Override
//            public void run() {
//              WXSDKEngine.reload();
//            }
//          });
//        }
//      }
    }
  }

  public void onInteractionTimeUpdate(final String instanceId){
    post(new Runnable() {
      @Override
      public void run() {
        if (mWXBridge instanceof WXBridge ){
          ((WXBridge)mWXBridge).nativeOnInteractionTimeUpdate(instanceId);
        }
      }
    });
  }

  public boolean jsEngineMultiThreadEnable() {
    return isJsEngineMultiThreadEnable;
  }

  public void checkJsEngineMultiThread() {
    boolean flag = false;
    IWXJscProcessManager wxJscProcessManager = WXSDKManager.getInstance().getWXJscProcessManager();
    if(wxJscProcessManager!=null) {
      flag = wxJscProcessManager.enableBackupThread();
    }

    if(flag == WXBridgeManager.isJsEngineMultiThreadEnable) {
        return;
    }

    WXBridgeManager.isJsEngineMultiThreadEnable = flag;
    //we should reinit framework if js framework has been initialized
    if (isJSFrameworkInit()) {
      if (isJSThread()) {
        WXSDKEngine.reload();
      } else {
        post(new Runnable() {
          @Override
          public void run() {
            WXSDKEngine.reload();
          }
        });
      }
    }
  }
  public void setSandBoxContext(final boolean flag) {
    if (flag != isSandBoxContext) {
      isSandBoxContext = flag;
      // use diff context reinit jsf
      if (isJSThread()) {

        setJSFrameworkInit(false);
        WXModuleManager.resetAllModuleState();
        String jsf = "";
        if (!isSandBoxContext) {
          jsf = WXFileUtils.loadAsset("main.js", WXEnvironment.getApplication());
        } else {
          jsf = WXFileUtils.loadAsset("weex-main-jsfm.js", WXEnvironment.getApplication());
        }
        initFramework(jsf);
        WXServiceManager.reload();
        WXModuleManager.reload();
        WXComponentRegistry.reload();
      } else {
        post(new Runnable() {
          @Override
          public void run() {
            setJSFrameworkInit(false);
            WXModuleManager.resetAllModuleState();
            String jsf = "";
            if (!isSandBoxContext) {
              jsf = WXFileUtils.loadAsset("main.js", WXEnvironment.getApplication());
            } else {
              jsf = WXFileUtils.loadAsset("weex-main-jsfm.js", WXEnvironment.getApplication());
            }
            initFramework(jsf);
            WXServiceManager.reload();
            WXModuleManager.reload();
            WXComponentRegistry.reload();
          }
        });
      }
    }
  }

  // setJSFrameworkInit and isJSFrameworkInit may use on diff thread
  // use volatile
  @RestrictTo(Scope.LIBRARY)
  boolean isJSFrameworkInit() {
    return mInit;
  }

  private void setJSFrameworkInit(boolean init) {
    mInit = init;
    WXStateRecord.getInstance().recoreJsfmInitHistory("setJsfmInitFlag:"+init);
    if (init == true) {
      onJsFrameWorkInitSuccees();
      JSEngine.getInstance().engineInitFinished();
    }
  }

  private void initWXBridge(boolean remoteDebug) {
    if (remoteDebug && WXEnvironment.isApkDebugable()) {
      WXEnvironment.sDebugServerConnectable = true;
    }

    if (WXEnvironment.sDebugServerConnectable && (WXEnvironment.isApkDebugable() || WXEnvironment.sForceEnableDevTool)) {
      if (WXEnvironment.getApplication() != null) {
        try {
          if (clazz_debugProxy == null) {
            clazz_debugProxy = Class.forName("com.taobao.weex.devtools.debug.DebugServerProxy");
          }
          if (clazz_debugProxy != null) {
            Constructor constructor = clazz_debugProxy.getConstructor(Context.class, IWXDebugConfig.class);
            if (constructor != null) {
              mWxDebugProxy = constructor.newInstance(WXEnvironment.getApplication(),
                      new IWXDebugConfig() {
                        @Override
                        public WXBridgeManager getWXJSManager() {
                          return WXBridgeManager.this;
                        }

                        @Override
                        public WXDebugJsBridge getWXDebugJsBridge() {
                          return new WXDebugJsBridge();
                        }
                      });
              if (mWxDebugProxy != null) {
                Method method_start = clazz_debugProxy.getMethod("start");
                if (method_start != null) {
                  method_start.invoke(mWxDebugProxy);
                }
              }
            }
          }
        } catch (Throwable e) {
          //Ignore, It will throw Exception on Release environment
        }
        WXServiceManager.execAllCacheJsService();
      } else {
        WXLogUtils.e("WXBridgeManager", "WXEnvironment.sApplication is null, skip init Inspector");
      }
    }
    if (remoteDebug && mWxDebugProxy != null) {
      try {
        if (clazz_debugProxy == null ) {
          clazz_debugProxy = Class.forName("com.taobao.weex.devtools.debug.DebugServerProxy");
        }
        if (clazz_debugProxy != null) {
          Method method_getWXBridge = clazz_debugProxy.getMethod("getWXBridge");
          if (method_getWXBridge != null) {
            mWXBridge = (IWXBridge) method_getWXBridge.invoke(mWxDebugProxy);
          }
        }
      } catch (Throwable e) {
        //Ignore, It will throw Exception on Release environment
      }
    } else {
      mWXBridge = new WXBridge();
    }
  }

  public String dumpIpcPageInfo(){
    if (mWXBridge instanceof WXBridge){
      return ((WXBridge)mWXBridge).nativeDumpIpcPageQueueInfo();
    }
    return "";
  }

  public boolean isRebootExceedLimit(){
    return reInitCount > CRASHREINIT;
  }

  public void stopRemoteDebug() {
    if (mWxDebugProxy != null) {
      try {
        if (clazz_debugProxy == null) {
          clazz_debugProxy = Class.forName("com.taobao.weex.devtools.debug.DebugServerProxy");
        }
        if (clazz_debugProxy != null) {
          Method method_stop = clazz_debugProxy.getMethod("stop", boolean.class);
          if (method_stop != null) {
            method_stop.invoke(mWxDebugProxy, true);
          }
        }
      } catch (Throwable e) {
        //Ignore, It will throw Exception on Release environment
      }
    }
  }

  public Object callModuleMethod(String instanceId, String moduleStr, String methodStr, JSONArray args) {
    return callModuleMethod(instanceId, moduleStr, methodStr, args, null);
  }

  public Object callModuleMethod(String instanceId, String moduleStr, String methodStr, JSONArray args, JSONObject options) {
    WXSDKInstance wxsdkInstance = WXSDKManager.getInstance()
            .getSDKInstance(instanceId);
    if (wxsdkInstance == null) {
      return null;
    }
    if (wxsdkInstance.isNeedValidate()
            && WXSDKManager.getInstance().getValidateProcessor() != null) {
      WXValidateProcessor.WXModuleValidateResult validateResult = WXSDKManager
              .getInstance().getValidateProcessor()
              .onModuleValidate(wxsdkInstance, moduleStr, methodStr, args, options);
      if (validateResult == null) {
        return null;
      }
      if (validateResult.isSuccess) {
        return WXModuleManager.callModuleMethod(instanceId, moduleStr, methodStr,
                args);
      } else {
        JSONObject validateInfo = validateResult.validateInfo;
        if (validateInfo != null) {
          WXLogUtils.e("[WXBridgeManager] module validate fail. >>> " + validateInfo.toJSONString());
        }
        return validateInfo;
      }
    }
    try {
      return WXModuleManager.callModuleMethod(instanceId, moduleStr, methodStr, args);
    }catch(NumberFormatException e){
      ArrayMap<String, String> ext = new ArrayMap<>();
      ext.put("moduleName", moduleStr);
      ext.put("methodName", methodStr);
      ext.put("args", args.toJSONString());
      WXLogUtils.e("[WXBridgeManager] callNative : numberFormatException when parsing string to numbers in args", ext.toString());
      return null;
    }
  }

  /**
   * Model switch. For now, debug model and release model are supported
   */
  public void restart() {
    setJSFrameworkInit(false);
    WXModuleManager.resetAllModuleState();
    initWXBridge(WXEnvironment.sRemoteDebugMode);
    mWXBridge.resetWXBridge(WXEnvironment.sRemoteDebugMode);
  }

  /**
   * Set current Instance
   *
   * @param instanceId {@link WXSDKInstance#getInstanceId()}
   */
  public synchronized void setStackTopInstance(final String instanceId) {
    post(new Runnable() {

      @Override
      public void run() {
        mNextTickTasks.setStackTopInstance(instanceId);
      }
    },instanceId, null, null);
  }

  @Override
  public void post(Runnable r) {
      postWithName(r,null,null);
  }

  public void postWithName(Runnable r, WXSDKInstance instance, String runnableName) {
   Runnable secure = WXThread.secure(r,instance, runnableName);
    if (mInterceptor != null && mInterceptor.take(secure)) {
      //task is token by the interceptor
      return;
    }
    if (mJSHandler == null) {
      return;
    }

    mJSHandler.post(secure);
  }

  @Override
  public void setInterceptor(Interceptor interceptor) {
    mInterceptor = interceptor;
  }

  public void post(Runnable r, Object token, WXSDKInstance instance, String runnableName) {
    if (mJSHandler == null) {
      return;
    }

    Message m = Message.obtain(mJSHandler, WXThread.secure(r, instance, runnableName));
    m.obj = token;
    m.sendToTarget();
  }

  public void post(Runnable r, Object token) {
    post(r, token, null, null);
  }

  public void postDelay(Runnable r,long delayMillis){
    if (mJSHandler == null) {
      return;
    }
    mJSHandler.postDelayed(WXThread.secure(r),delayMillis);
  }

  void setTimeout(String callbackId, String time) {
    Message message = Message.obtain();
    message.what = WXJSBridgeMsgType.SET_TIMEOUT;
    TimerInfo timerInfo = new TimerInfo();
    timerInfo.callbackId = callbackId;
    timerInfo.time = (long) Float.parseFloat(time);
    message.obj = timerInfo;

    mJSHandler.sendMessageDelayed(message, timerInfo.time);
  }

  public void sendMessageDelayed(Message message, long delayMillis) {
    if (message == null || mJSHandler == null || mJSThread == null
            || !mJSThread.isWXThreadAlive() || mJSThread.getLooper() == null) {
      return;
    }
    mJSHandler.sendMessageDelayed(message, delayMillis);
  }

  public void removeMessage(int what, Object obj) {
    if (mJSHandler == null || mJSThread == null
            || !mJSThread.isWXThreadAlive() || mJSThread.getLooper() == null) {
      return;
    }
    mJSHandler.removeMessages(what, obj);
  }

  public Object callNativeModule(String instanceId, String module, String method, JSONArray arguments, Object options) {

    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(module) || TextUtils.isEmpty(method)) {
      WXLogUtils.d("[WXBridgeManager] call callNativeModule arguments is null");
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callNativeModule",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callNativeModule >>>> instanceId:").append(instanceId)
              .append(", module:").append(module).append(", method:").append(method).append(", arguments:").append(arguments);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    try {
      if (WXDomModule.WXDOM.equals(module)) {
        WXDomModule dom = WXModuleManager.getDomModule(instanceId);
        return dom.callDomMethod(method, arguments);
      } else {
        return callModuleMethod(instanceId, module,
              method, arguments);
      }
    } catch (Exception e) {
      String err = "[WXBridgeManager] callNative exception: " + WXLogUtils.getStackTrace(e);
      WXLogUtils.e(err);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callNativeModule",
              err, null);
    }

    return null;
  }

  public Object callNativeModule(String instanceId, String module, String method, JSONArray arguments, JSONObject options) {

    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(module) || TextUtils.isEmpty(method)) {
      WXLogUtils.d("[WXBridgeManager] call callNativeModule arguments is null");
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callNativeModule",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callNativeModule >>>> instanceId:").append(instanceId)
              .append(", module:").append(module).append(", method:").append(method).append(", arguments:").append(arguments);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    try {
      if (WXDomModule.WXDOM.equals(module)) {
        WXDomModule dom = WXModuleManager.getDomModule(instanceId);
        if(dom != null){
          return dom.callDomMethod(method, arguments);
        } else {
          createDomModule(WXSDKManager.getInstance().getSDKInstance(instanceId));
        }
      } else {
        return callModuleMethod(instanceId, module,
              method, arguments, options);
      }
    } catch (Exception e) {
      String err = "[WXBridgeManager] callNativeModule exception: " + WXLogUtils.getStackTrace(e);
      WXLogUtils.e(err);
    }

    return null;
  }

  public Object callNativeComponent(String instanceId, String componentRef, String method, JSONArray arguments, Object options) {

    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(componentRef) || TextUtils.isEmpty(method)) {
      WXLogUtils.d("[WXBridgeManager] call callNativeComponent arguments is null");
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callNativeComponent",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callNativeComponent >>>> instanceId:").append(instanceId)
              .append(", componentRef:").append(componentRef).append(", method:").append(method).append(", arguments:").append(arguments);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    try {
      WXDomModule dom = WXModuleManager.getDomModule(instanceId);
      if (null != dom){
        dom.invokeMethod(componentRef, method, arguments);
      }else {
        WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
        if(null == instance || !instance.isDestroy()){
          WXLogUtils.e("WXBridgeManager","callNativeComponent exception :null == dom ,method:"+method);
        }
      }

    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callNativeComponent exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callNativeComponent",
              WXLogUtils.getStackTrace(e), null);
    }
    return null;
  }

  /**
   * Dispatch the native task to be executed.
   *
   * @param instanceId {@link WXSDKInstance#getInstanceId()}
   * @param tasks      tasks to be executed
   * @param callback   next tick id
   */
  public int callNative(String instanceId, JSONArray tasks, String callback) {

    if (TextUtils.isEmpty(instanceId) || tasks == null) {
      WXLogUtils.d("[WXBridgeManager] call callNative arguments is null");
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callNative",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callNative >>>> instanceId:").append(instanceId)
              .append(", tasks:").append(tasks).append(", callback:").append(callback);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }


    long parseNanos = System.nanoTime();
    JSONArray array = tasks;
    parseNanos = System.nanoTime() - parseNanos;

    if (null != array && array.size() > 0) {
      int size = array.size();
      try {
        JSONObject task;
        for (int i = 0; i < size; ++i) {
          task = (JSONObject) array.get(i);
          if (task != null && WXSDKManager.getInstance().getSDKInstance(instanceId) != null) {
            Object module = task.get(MODULE);
            if (module != null) {
              if (WXDomModule.WXDOM.equals(module)) {
                WXDomModule dom = WXModuleManager.getDomModule(instanceId);
                dom.callDomMethod(task, parseNanos);
              } else {
                JSONObject optionObj = task.getJSONObject(OPTIONS);
                WXStateRecord.getInstance().recordAction(instanceId,"callModuleMethod:"+instanceId+","+module+","+task.get(METHOD));
                callModuleMethod(instanceId, (String) module,
                        (String) task.get(METHOD), (JSONArray) task.get(ARGS), optionObj);
              }
            } else if (task.get(COMPONENT) != null) {
              WXDomModule dom = WXModuleManager.getDomModule(instanceId);
              WXStateRecord.getInstance().recordAction(instanceId,"callDomMethod:"+instanceId+","+task.get(METHOD));
              dom.invokeMethod((String) task.get(REF), (String) task.get(METHOD), (JSONArray) task.get(ARGS));
            } else {
              throw new IllegalArgumentException("unknown callNative");
            }
          }
        }
      } catch (Exception e) {
        WXLogUtils.e("[WXBridgeManager] callNative exception: ", e);
        WXExceptionUtils.commitCriticalExceptionRT(instanceId,
                WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callNative",
                WXLogUtils.getStackTrace(e) , null);
      }
    }

    if (UNDEFINED.equals(callback) || NON_CALLBACK.equals(callback)) {
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }
    // get next tick
    getNextTick(instanceId, callback);
    return IWXBridge.INSTANCE_RENDERING;
  }

  // callUpdateFinish
  public int callUpdateFinish(String instanceId, String callback) {

    if (TextUtils.isEmpty(instanceId)) {
      WXLogUtils.d("[WXBridgeManager] call callUpdateFinish arguments is null");
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callUpdateFinish",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callUpdateFinish >>>> instanceId:").append(instanceId)
              .append(", callback:").append(callback);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      if (WXSDKManager.getInstance().getSDKInstance(instanceId) != null) {
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callUpdateFinish exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callUpdateFinish",
              WXLogUtils.getStackTrace(e), null);
    }

    if (callback == null || callback.isEmpty() || UNDEFINED.equals(callback) || NON_CALLBACK.equals(callback)) {
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }
    // get next tick
    getNextTick(instanceId, callback);
    return IWXBridge.INSTANCE_RENDERING;
  }

  // callRefreshFinish
  public int callRefreshFinish(String instanceId, String callback) {

    if (TextUtils.isEmpty(instanceId)) {
      WXLogUtils.d("[WXBridgeManager] call callRefreshFinish arguments is null");
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callRefreshFinish",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callRefreshFinish >>>> instanceId:").append(instanceId)
              .append(", callback:").append(callback);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
        WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
        if (instance != null) {
          GraphicActionRefreshFinish action = new GraphicActionRefreshFinish(instance);
          WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(instanceId, action);
        }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callRefreshFinish exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callRefreshFinish",
              WXLogUtils.getStackTrace(e), null);
    }

    if (UNDEFINED.equals(callback) || NON_CALLBACK.equals(callback)) {
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }
    // get next tick
    getNextTick(instanceId, callback);
    return IWXBridge.INSTANCE_RENDERING;

  }

  public int callReportCrashReloadPage(String instanceId, String crashFile) {
    boolean isCrashFileEmpty = TextUtils.isEmpty(crashFile);
    try {
      String url = null;
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        url = instance.getBundleUrl();
        instance.setHasException(true);
      }
      Map<String,String> extInfo = new HashMap<>(2);
      extInfo.put("weexCoreThreadStackTrace:",WXBridgeManager.getInstance().getWeexCoreThreadStackTrace());
      extInfo.put("wxStateInfo",WXStateRecord.getInstance().getStateInfo().toString());

      if(!isCrashFileEmpty) {
        try {
            if (WXEnvironment.getApplication() != null) {
                crashFile = mInitParams.getCrashFilePath() + crashFile;
                Log.d("jsengine", "callReportCrashReloadPage crashFile:" + crashFile);
            }
        } catch (Throwable e) {
          WXLogUtils.e(WXLogUtils.getStackTrace(e));
        }
        WXStateRecord.getInstance().onJSCCrash(TextUtils.isEmpty(instanceId)?"null":instanceId);
        callReportCrash(crashFile, instanceId, url,extInfo);
      } else {
        WXStateRecord.getInstance().onJSEngineReload(TextUtils.isEmpty(instanceId)?"null":instanceId);
         commitJscCrashAlarmMonitor(IWXUserTrackAdapter.JS_BRIDGE, WXErrorCode.WX_ERR_RELOAD_PAGE, "reboot jsc Engine", instanceId, url,extInfo);
      }
      JSEngine.getInstance().engineCrashed();
      WXLogUtils.e("reInitCount:"+reInitCount);

      if (reInitCount > CRASHREINIT) {
        WXExceptionUtils.commitCriticalExceptionRT("jsEngine", WXErrorCode.WX_ERR_RELOAD_PAGE_EXCEED_LIMIT,
            "callReportCrashReloadPage","reInitCount:"+reInitCount,extInfo);
        return IWXBridge.INSTANCE_RENDERING_ERROR;
      }
      reInitCount++;
      // reinit frame work
      setJSFrameworkInit(false);
      WXModuleManager.resetAllModuleState();
      initScriptsFramework("");

      if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
        return IWXBridge.DESTROY_INSTANCE;
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callReportCrashReloadPage exception: ", e);
    }
    try {

      if (WXSDKManager.getInstance().getSDKInstance(instanceId) != null) {
        boolean reloadThisInstance = shouldReloadCurrentInstance(
                WXSDKManager.getInstance().getSDKInstance(instanceId).getBundleUrl());
        new ActionReloadPage(instanceId, reloadThisInstance).executeAction();
      }

    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callReloadPage exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callReportCrashReloadPage",
              WXLogUtils.getStackTrace(e), null);
    }
    return IWXBridge.INSTANCE_RENDERING_ERROR;
  }

  public boolean shouldReloadCurrentInstance(String aUrl) {
    long time = System.currentTimeMillis();
    String bizUrl = aUrl;
    IWXConfigAdapter adapter = WXSDKManager.getInstance().getWxConfigAdapter();
    if (adapter != null) {
        boolean check_biz_url = Boolean.parseBoolean(adapter
                .getConfig("android_weex_ext_config",
                        "check_biz_url",
                        "true"));
        WXLogUtils.e("check_biz_url : " + check_biz_url);
        if(check_biz_url && !TextUtils.isEmpty(aUrl)) {
            Uri uri = Uri.parse(aUrl);
            if(uri != null) {
                bizUrl = uri.buildUpon().clearQuery().build().toString();
            }
        }
    }

    if (crashUrl == null ||
            (crashUrl != null && !crashUrl.equals(bizUrl)) ||
            ((time - lastCrashTime) > 15000)) {
      crashUrl = bizUrl;
      lastCrashTime = time;
      return true;
    }
    lastCrashTime = time;
    return false;
  }

  public void callReportCrash(String crashFile, final String instanceId, final String url,final Map<String,String> extInfo) {
    // statistic weex core process crash
    Date date = new Date();
    DateFormat format = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
    String time = format.format(date);
    final String origin_filename = crashFile + "." + time;
    File oldfile = new File(crashFile);
    File newfile = new File(origin_filename);
    if (oldfile.exists()) {
      oldfile.renameTo(newfile);
    }
    Thread t = new Thread(new Runnable() {
      public void run() {
        try {
          File file = new File(origin_filename);
          if (file.exists()) {
            if (file.length() > 0) {
              StringBuilder result = new StringBuilder();
              try {
                BufferedReader br = new BufferedReader(new FileReader(origin_filename));
                String s = null;
                // boolean foundStart = false;
                while ((s = br.readLine()) != null) {
                  if ("".equals(s)) {
                    continue;
                  }
                  // if (("r0:").equals(s)) {
                  //  break;
                  // }
                  result.append(s + "\n");
                }
                commitJscCrashAlarmMonitor(IWXUserTrackAdapter.JS_BRIDGE, WXErrorCode.WX_ERR_JSC_CRASH, result.toString(), instanceId, url,extInfo);
                br.close();
              } catch (Exception e) {
                WXLogUtils.e(WXLogUtils.getStackTrace(e));
              }
            } else {
              WXLogUtils.e("[WXBridgeManager] callReportCrash crash file is empty");
            }
            if(!WXEnvironment.isApkDebugable())
              file.delete();
          }
        } catch (Throwable throwable) {
          WXLogUtils.e("[WXBridgeManager] callReportCrash exception: ", throwable);
        }
      }
    });
    t.start();
  }

  private void getNextTick(final String instanceId, final String callback) {
    addJSTask(METHOD_CALLBACK, instanceId, callback, "{}");
    sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH);
  }

  private void getNextTick(final String instanceId) {
    addJSTask(METHOD_CALLBACK, instanceId, "", "{}");
    sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH);
  }

  public String syncExecJsOnInstanceWithResult(final String instanceId, final String js, final int type) {
    final CountDownLatch waitLatch = new CountDownLatch(1);
    EventResult callback = new EventResult(){
      @Override
      public void onCallback(Object result) {
        super.onCallback(result);
        waitLatch.countDown();
      }
    };
    try{
      execJSOnInstance(callback, instanceId, js, type);
      waitLatch.await(100, TimeUnit.MILLISECONDS);
      if (callback != null && callback.getResult() != null) {
        return  callback.getResult().toString();
      }
      return "";
    }catch (Throwable e){
      WXLogUtils.e("syncCallExecJsOnInstance", e);
      return  "";
    }
  }

  public void loadJsBundleInPreInitMode(final String instanceId, final String js){
    post(new Runnable() {
      @Override
      public void run() {
        invokeExecJSOnInstance(instanceId, js, -1);
        WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId);
        if (null != instance && instance.isPreInitMode()){
          instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_END);
          instance.getApmForInstance().onStageWithTime(WXInstanceApm.KEY_PAGE_STAGES_END_EXCUTE_BUNDLE,WXUtils.getFixUnixTime()+600);
        }
      }
    });
  }

  /**
   * ref, type, data, domChanges
   * */
  public EventResult syncCallJSEventWithResult(final String method, final String instanceId, final List<Object> params, final Object... args) {
    final CountDownLatch waitLatch = new CountDownLatch(1);
    EventResult callback = new EventResult(){
      @Override
      public void onCallback(Object result) {
        super.onCallback(result);
        waitLatch.countDown();
      }
    };
    try{
      asyncCallJSEventWithResult(callback, method, instanceId, params, args);
      waitLatch.await(100, TimeUnit.MILLISECONDS);
      return  callback;
    }catch (Exception e){
      WXLogUtils.e("syncCallJSEventWithResult", e);
      return  callback;
    }
  }

  public void asyncCallJSEventVoidResult(final String method, final String instanceId, final List<Object> params, final Object... args) {
    post(new Runnable() {
      @Override
      public void run() {
        try{
          if (args == null || args.length == 0) {
            return;
          }

          ArrayList<Object> argsList = new ArrayList<>();
          for (Object arg : args) {
            argsList.add(arg);
          }
          if (params != null) {
            ArrayMap map = new ArrayMap(4);
            map.put(KEY_PARAMS, params);
            argsList.add(map);
          }

          WXHashMap<String, Object> task = new WXHashMap<>();
          task.put(KEY_METHOD, method);
          task.put(KEY_ARGS, argsList);
          Object[] tasks = {task};
          WXJSObject[] jsArgs = {
                  new WXJSObject(WXJSObject.String, instanceId),
                  WXWsonJSONSwitch.toWsonOrJsonWXJSObject(tasks)};
          invokeExecJS(String.valueOf(instanceId), null, METHOD_CALL_JS, jsArgs, true);
          jsArgs[0] = null;
          jsArgs = null;
        }catch (Exception e){
          WXLogUtils.e("asyncCallJSEventVoidResult" , e);
        }
      }
    });
  }

  /**
   * aync call js event and return result in eventResult callback
   * */
  private void asyncCallJSEventWithResult(final EventResult eventCallback, final String method, final String instanceId, final List<Object> params, final Object... args) {
    post(new Runnable() {
      @Override
      public void run() {
        Object result = null;
        try{
          if (args == null || args.length == 0) {
            return;
          }

          ArrayList<Object> argsList = new ArrayList<>();
          for (Object arg : args) {
            argsList.add(arg);
          }
          if (params != null) {
            ArrayMap map = new ArrayMap(4);
            map.put(KEY_PARAMS, params);
            argsList.add(map);
          }

          WXHashMap<String, Object> task = new WXHashMap<>();
          task.put(KEY_METHOD, method);
          task.put(KEY_ARGS, argsList);
          Object[] tasks = {task};
          WXJSObject[] jsArgs = {
                  new WXJSObject(WXJSObject.String, instanceId),
                  WXWsonJSONSwitch.toWsonOrJsonWXJSObject(tasks)};
          ResultCallback<byte[]> resultCallback = null;
          if (eventCallback != null) {
            resultCallback = new ResultCallback<byte[]>() {
              @Override
              public void onReceiveResult(byte[] result) {
                JSONArray arrayResult = (JSONArray) WXWsonJSONSwitch.parseWsonOrJSON(result);
                if(arrayResult != null && arrayResult.size() > 0){
                  eventCallback.onCallback(arrayResult.get(0));
                }
              }
            };
          }
          invokeExecJSWithCallback(String.valueOf(instanceId), null, METHOD_CALL_JS,
                  jsArgs, resultCallback, true);
          jsArgs[0] = null;
        }catch (Exception e){
          WXLogUtils.e("asyncCallJSEventWithResult" , e);
        }
      }
    });
  }

  private void addJSEventTask(final String method, final String instanceId, final List<Object> params, final Object... args) {
    post(new Runnable() {
      @Override
      public void run() {
        if (args == null || args.length == 0) {
          return;
        }

        ArrayList<Object> argsList = new ArrayList<>();
        for (Object arg : args) {
          argsList.add(arg);
        }
        if (params != null) {
          ArrayMap map = new ArrayMap(4);
          map.put(KEY_PARAMS, params);
          argsList.add(map);
        }

        WXHashMap<String, Object> task = new WXHashMap<>();
        task.put(KEY_METHOD, method);
        task.put(KEY_ARGS, argsList);


        if (mNextTickTasks.get(instanceId) == null) {
          ArrayList<WXHashMap<String, Object>> list = new ArrayList<>();
          list.add(task);
          mNextTickTasks.put(instanceId, list);
        } else {
          mNextTickTasks.get(instanceId).add(task);
        }
      }
    });
  }

  private void addJSTask(final String method, final String instanceId, final Object... args) {
    addJSEventTask(method, instanceId, null, args);
  }

  private void sendMessage(String instanceId, int what) {
    Message msg = Message.obtain(mJSHandler);
    msg.obj = instanceId;
    msg.what = what;
    msg.sendToTarget();
  }

  /**
   * Initialize JavaScript framework
   *
   * @param framework String representation of the framework to be init.
   */
  public synchronized void initScriptsFramework(String framework) {
    Message msg = mJSHandler.obtainMessage();
    msg.obj = framework;
    msg.what = WXJSBridgeMsgType.INIT_FRAMEWORK;
    msg.setTarget(mJSHandler);
    msg.sendToTarget();
  }

  @Deprecated
  public void fireEvent(final String instanceId, final String ref,
                        final String type, final Map<String, Object> data) {
    this.fireEvent(instanceId, ref, type, data, null);
  }

  /**
   * Do not direct invoke this method in Components, use {@link WXSDKInstance#fireEvent(String, String, Map, Map)} instead.
   *
   * @param instanceId
   * @param ref
   * @param type
   * @param data
   * @param domChanges
   */
  @Deprecated
  public void fireEvent(final String instanceId, final String ref,
                        final String type, final Map<String, Object> data, final Map<String, Object> domChanges) {
    fireEventOnNode(instanceId, ref, type, data, domChanges);
  }

  /**
   * Notify the JavaScript about the event happened on Android
   */
  public void fireEventOnNode(final String instanceId, final String ref,
                              final String type, final Map<String, Object> data, final Map<String, Object> domChanges) {
    fireEventOnNode(instanceId, ref, type, data, domChanges, null, null);
  }

  /**
   * Notify the JavaScript about the event happened on Android
   */
  public void fireEventOnNode(final String instanceId, final String ref,
                              final String type, final Map<String, Object> data,
                              final Map<String, Object> domChanges, List<Object> params){
    fireEventOnNode(instanceId, ref, type, data, domChanges, params, null);
  }

  public void fireEventOnNode(final String instanceId, final String ref,
                              final String type, final Map<String, Object> data,
                              final Map<String, Object> domChanges, List<Object> params,  EventResult callback) {
    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)
            || TextUtils.isEmpty(type) || mJSHandler == null) {
      return;
    }
    if (!checkMainThread()) {
      throw new WXRuntimeException(
              "fireEvent must be called by main thread");
    }
    WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId);
    if (instance != null && instance.isUsingEaglePlugin()) {
      int mode = instance.getEaglePlugin().isSupportFireEvent(instanceId);
      if (mode == WXEaglePlugin.NOT_SUPPORT){
        return;
      }
      fireEventOnDataRenderNode(instance.getEaglePlugin(), instanceId, ref, type, data, domChanges);
      if (mode == WXEaglePlugin.EAGLE_ONLY){
        return;
      }
      //assert mode == WXEaglePlugin.EAGLE_AND_SCRIPT
    }

    if (callback == null) {
      addJSEventTask(METHOD_FIRE_EVENT, instanceId, params, ref, type, data, domChanges);
      sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH);
    } else {
      asyncCallJSEventWithResult(callback, METHD_FIRE_EVENT_SYNC, instanceId, params, ref, type, data, domChanges);
    }
  }

  private void fireEventOnDataRenderNode(final WXEaglePlugin eaglePlugin, final String instanceId, final String ref,
                                         final String type, final Map<String, Object> data, final Map<String, Object> domChanges) {
    mJSHandler.postDelayed(WXThread.secure(new Runnable() {
      @Override
      public void run() {
        try {
          long start = System.currentTimeMillis();
          if (WXEnvironment.isApkDebugable()) {
            WXLogUtils.d("fireEventOnDataRenderNode >>>> instanceId:" + instanceId
                + ", data:" + data);
          }
          eaglePlugin.fireEvent(instanceId, ref, type,
              (data == null || data.isEmpty()) ? "{}" : JSON.toJSONString(data),
              (domChanges == null || domChanges.isEmpty()) ? "{}" : JSON.toJSONString(domChanges));
          WXLogUtils.renderPerformanceLog("fireEventOnDataRenderNode", System.currentTimeMillis() - start);
        } catch (Throwable e) {
          String err = "[WXBridgeManager] fireEventOnDataRenderNode " + WXLogUtils.getStackTrace(e);
          WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "fireEventOnDataRenderNode",
              err, null);
          WXLogUtils.e(err);
        }
      }
    }), 0);
  }

  private boolean checkMainThread() {
    return Looper.myLooper() == Looper.getMainLooper();
  }


  /**
   * Invoke JavaScript callback. Use {@link JSCallback} instead.
   *
   * @see #callback(String, String, String)
   */
  @Deprecated
  public void callback(String instanceId, String callback, String data) {
    callback(instanceId, callback, data, false);
  }

  /**
   * Invoke JavaScript callback. Use {@link JSCallback} instead.
   */
  @Deprecated
  public void callback(final String instanceId, final String callback,
                       final Map<String, Object> data) {
    callback(instanceId, callback, data, false);
  }

  /**
   * Use {@link JSCallback} instead.
   *
   * @param instanceId Weex Instance Id
   * @param callback   callback referenece handle
   * @param data       callback data
   * @param keepAlive  if keep callback instance alive for later use
   */
  @Deprecated
  public void callback(final String instanceId, final String callback,
                       final Object data, boolean keepAlive) {
    callbackJavascript(instanceId, callback, data, keepAlive);
  }

  /**
   * Callback to Javascript function.
   *
   * @param instanceId Weex Instance Id
   * @param callback   callback referenece handle
   * @param data       callback data
   * @param keepAlive  if keep callback instance alive for later use
   */
  void callbackJavascript(final String instanceId, final String callback,
                          final Object data, boolean keepAlive) {
    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(callback)
        || mJSHandler == null) {
      return;
    }

    WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId);
    if (instance != null && instance.isUsingEaglePlugin()) {
      int mode = instance.getEaglePlugin().isSupportJSCallback(instanceId);
      if (mode == WXEaglePlugin.NOT_SUPPORT) {
        return;
      }
      callbackJavascriptOnDataRender(instance.getEaglePlugin(), instanceId, callback, data, keepAlive);
      if (mode == WXEaglePlugin.EAGLE_ONLY) {
        return;
      }
      //assert mode == WXEaglePlugin.EAGLE_AND_SCRIPT
    }


    addJSTask(METHOD_CALLBACK, instanceId, callback, data, keepAlive);
    sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH);
  }

  void callbackJavascriptOnDataRender(final WXEaglePlugin eaglePlugin, final String instanceId, final String callback, final Object data, final boolean keepAlive){
    mJSHandler.postDelayed(WXThread.secure(new Runnable() {
      @Override
      public void run() {
        try {
          long start = System.currentTimeMillis();
          String data_str = JSON.toJSONString(data);
          if (WXEnvironment.isApkDebugable()) {
            WXLogUtils.d("callbackJavascriptOnDataRender >>>> instanceId:" + instanceId
                + ", data:" + data_str);
          }
          eaglePlugin.invokeJSCallback(instanceId, callback, data_str, keepAlive);
          WXLogUtils.renderPerformanceLog("callbackJavascriptOnDataRender", System.currentTimeMillis() - start);
        } catch (Throwable e) {
          String err = "[WXBridgeManager] callbackJavascriptOnDataRender " + WXLogUtils.getStackTrace(e);
          WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callbackJavascriptOnDataRender",
              err, null);
          WXLogUtils.e(err);
        }
      }
    }), 0);
  }

  /**
   * Refresh instance
   */
  public void refreshInstance(final String instanceId, final WXRefreshData jsonData) {
    if (TextUtils.isEmpty(instanceId) || jsonData == null) {
      return;
    }
    mJSHandler.postDelayed(WXThread.secure(new Runnable() {
      @Override
      public void run() {
        invokeRefreshInstance(instanceId, jsonData);
      }
    }), 0);
  }

  private void invokeRefreshInstance(String instanceId, WXRefreshData refreshData) {
    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (!isSkipFrameworkInit(instanceId) && !isJSFrameworkInit()) {
        if (instance != null) {
          instance.onRenderError(
                  WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(),
                  WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg()
                          + "invokeRefreshInstance FAILED for JSFrameworkInit FAILED, intance will invoke instance.onRenderError"
          );
        }
        String err = "[WXBridgeManager] invokeRefreshInstance: framework.js uninitialized.";
        WXLogUtils.e(err);
        return;
      }
      long start = System.currentTimeMillis();
      if (WXEnvironment.isApkDebugable()) {
        WXLogUtils.d("refreshInstance >>>> instanceId:" + instanceId
                + ", data:" + refreshData.data + ", isDirty:" + refreshData.isDirty);
      }

      if (refreshData.isDirty) {
        return;
      }
      WXJSObject instanceIdObj = new WXJSObject(WXJSObject.String,
              instanceId);
      WXJSObject dataObj = new WXJSObject(WXJSObject.JSON,
              refreshData.data == null ? "{}" : refreshData.data);
      WXJSObject[] args = {instanceIdObj, dataObj};
      mWXBridge.refreshInstance(instanceId, null, METHOD_REFRESH_INSTANCE, args);
    } catch (Throwable e) {
      String err = "[WXBridgeManager] invokeRefreshInstance " + WXLogUtils.getStackTrace(e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "invokeRefreshInstance",
              err, null);
      WXLogUtils.e(err);
    }
  }

  public void commitJscCrashAlarmMonitor(final String type, final WXErrorCode errorCode, String errMsg,
                                         String instanceId, String url,Map<String, String> extInfo) {
    if (TextUtils.isEmpty(type) || errorCode == null) {
      return;
    }

    Log.d("ReportCrash", " commitJscCrashAlarmMonitor errMsg " + errMsg);
    String method = "callReportCrash";
    String exception = "weex core process crash and restart exception";
    Map<String, String> extParams = new HashMap<String, String>();
    extParams.put("jscCrashStack", errMsg);
    if (null != extInfo){
      extParams.putAll(extInfo);
    }
    IWXJSExceptionAdapter adapter = WXSDKManager.getInstance().getIWXJSExceptionAdapter();
    if (adapter != null) {
      WXJSExceptionInfo jsException = new WXJSExceptionInfo(instanceId, url, errorCode, method, exception, extParams);
      adapter.onJSException(jsException);
      // if (WXEnvironment.isApkDebugable()) {
      WXLogUtils.e(jsException.toString());
      // }
    }
  }

  private boolean isSkipFrameworkInit(String instanceId) {
    final WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    return isSkipFrameworkInit(instance);
  }

  private boolean isSkipFrameworkInit(WXSDKInstance instance) {
    if (instance == null) {
      return false;
    }
    return instance.skipFrameworkInit();
  }

  /**
   * Create instance.
   */
  public void createInstance(final String instanceId, final String template,
                             final Map<String, Object> options, final String data) {
    createInstance(instanceId, new Script(template), options, data);
  }

  public void setLogLevel(final int level, final boolean isPerf) {
    post(new Runnable() {
      @Override
      public void run() {
        if(mWXBridge != null) {
          mWXBridge.setLogType(level, isPerf);
        }
      }
    });
  }

  public void createInstance(final String instanceId, final Script template,
                             final Map<String, Object> options, final String data) {
    final WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if (instance == null) {
      WXLogUtils.e("WXBridgeManager", "createInstance failed, SDKInstance does not exist");
      return;
    }
    if (TextUtils.isEmpty(instanceId) || template == null || template.isEmpty() || mJSHandler == null) {
      instance.onRenderError(
              WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(),
              WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg() +
                      " instanceId==" + instanceId + " template ==" + template + " mJSHandler== " + mJSHandler.toString()
      );

      instance.getApmForInstance().onStage("createInstance failed return; "+TextUtils.isEmpty(instanceId)+ ","+template.isEmpty()+","+(mJSHandler ==null));
      return;
    }

    if (!isSkipFrameworkInit(instanceId) && !isJSFrameworkInit() && reInitCount == 1 && !WXEnvironment.sDebugServerConnectable) {
      instance.onRenderError(
              WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(),
              WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg() +
                      " isJSFrameworkInit==" + isJSFrameworkInit() + " reInitCount == 1" );
      instance.getApmForInstance().onStage("createInstance failed jsfm isn't init return;");
      post(new Runnable() {
        @Override
        public void run() {
          initFramework("");
        }
      }, instanceId, instance,"initFrameworkInCreateInstance");
      return;
    }

    WXModuleManager.createDomModule(instance);
    instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_START);
    post(new Runnable() {
      @Override
      public void run() {
        instance.getApmForInstance().onStage("wxLoadBundleStartOnJsThread");
        long start = System.currentTimeMillis();
        mWXBridge.setPageArgument(instanceId, "renderTimeOrigin", String.valueOf(instance.getWXPerformance().renderTimeOrigin));
        mWXBridge.setInstanceRenderType(instance.getInstanceId(), instance.getRenderType());
        invokeCreateInstance(instance, template, options, data);
        long end = System.currentTimeMillis();
        instance.getWXPerformance().callCreateInstanceTime = end - start;
        instance.getWXPerformance().communicateTime =  instance.getWXPerformance().callCreateInstanceTime;
      }
    }, instanceId, instance,"createInstance");
  }

  private void invokeCreateInstance(@NonNull WXSDKInstance instance, Script template,
                                    Map<String, Object> options, String data) {
    // add for sandbox, will delete on sandbox ok
    if (!isSkipFrameworkInit(instance)){
      initFramework("");
    }

    if (mMock) {
      mock(instance.getInstanceId());
    } else {
      if (!isSkipFrameworkInit(instance) && !isJSFrameworkInit()) {
        String err = "[WXBridgeManager] invokeCreateInstance: framework.js uninitialized.";
        instance.onRenderError(
                WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(),
                WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg()
        );
        WXLogUtils.e(err);
        instance.getApmForInstance().onStage("framework.js uninitialized and return");
        return;
      }

      WXModuleManager.registerWhenCreateInstance();

      try {
        BundType type = BundType.Others;
        try {
          long start = System.currentTimeMillis();
          type = getBundleType(instance.getBundleUrl(), template.getContent());

          if (WXEnvironment.isOpenDebugLog()) {
            long end = System.currentTimeMillis();
            WXLogUtils.e("end getBundleType type:" + type.toString() + " time:" + (end - start));
          }
        } catch (Throwable e) {
          WXLogUtils.e(WXLogUtils.getStackTrace(e));
        }

        try {
          if (options == null) {
            options = new HashMap<>();
          }
          // on file there is { "framework": "Vue" } or others
          if (options.get(BUNDLE_TYPE) == null) {
            // may vue or Rax
            if (type == BundType.Vue) {
              options.put(BUNDLE_TYPE, "Vue");
            } else if (type == BundType.Rax) {
              options.put(BUNDLE_TYPE, "Rax");
            } else {
              options.put(BUNDLE_TYPE, "Others");
            }
            Object recordBundleType = options.get(BUNDLE_TYPE);
            if (recordBundleType instanceof String && "Others".equalsIgnoreCase((String)recordBundleType)){
              //same as iOS record
              recordBundleType = "other";
            }
            if (null != recordBundleType){
              instance.getApmForInstance().addProperty(WXInstanceApm.KEY_PAGE_PROPERTIES_BUNDLE_TYPE, recordBundleType);
            }
          }
          if (options.get("env") == null) {
            options.put("env", mInitParams.toMap());
          }
        } catch (Throwable e) {
          WXLogUtils.e(WXLogUtils.getStackTrace(e));
        }
        instance.bundleType = type;
        if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
          WXLogUtils.d("createInstance >>>> instanceId:" + instance.getInstanceId()
                  + ", options:"
                  + WXJsonUtils.fromObjectToJSONString(options)
                  + ", data:" + data);
        }
        WXJSObject instanceIdObj = new WXJSObject(WXJSObject.String,
                instance.getInstanceId());
        WXJSObject instanceObj;
        WXJSObject scriptType;
        if (TextUtils.isEmpty(template.getContent())){
          //byte[]
          instanceObj = new WXJSObject(WXJSObject.String,
              template.getBinary());
          scriptType = new WXJSObject(WXJSObject.String, "binary");
        } else {
          //String
          instanceObj = new WXJSObject(WXJSObject.String,
              template.getContent());
          scriptType = new WXJSObject(WXJSObject.NUMBER, "string");
        }


        Object extraOption = null;
        if(options != null && options.containsKey("extraOption")) {
           extraOption = options.get("extraOption");
           options.remove("extraOption");
        }

        WXJSObject extraOptionObj = new WXJSObject(WXJSObject.JSON,
                extraOption == null ? "{}"
                        : WXJsonUtils.fromObjectToJSONString(extraOption));


        WXJSObject optionsObj = new WXJSObject(WXJSObject.JSON,
                options == null ? "{}"
                        : WXJsonUtils.fromObjectToJSONString(options));
        optionsObj = optionObjConvert(isSandBoxContext, type, optionsObj);
        WXJSObject dataObj = new WXJSObject(WXJSObject.JSON,
                data == null ? "{}" : data);

        WXJSObject apiObj;
        if (type == BundType.Rax || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER) {
          if (mRaxApi == null) {
            IWXJsFileLoaderAdapter iwxJsFileLoaderAdapter = WXSDKEngine.getIWXJsFileLoaderAdapter();
            if(iwxJsFileLoaderAdapter != null) {
              mRaxApi = iwxJsFileLoaderAdapter.loadRaxApi();
            }

            if(TextUtils.isEmpty(mRaxApi)) {
              mRaxApi =  WXFileUtils.loadAsset("weex-rax-api.js", WXEnvironment.getApplication());
            }
          }
          apiObj = new WXJSObject(WXJSObject.String,
                  mRaxApi);
        } else {
          apiObj = new WXJSObject(WXJSObject.String,
                  "");
        }

        // When render strategy is data_render, put it into options. Others keep null.
        WXJSObject renderStrategy = null;
        if (instance.isUsingEaglePlugin()) {
          //Eagle use plugin name as renderStrategy
          renderStrategy = new WXJSObject(WXJSObject.String, instance.getEaglePluginName());
        } else if (instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER) {
          //todo just for compat
          //using eagle mode without eagle plugin, will report exception in c if no plugin was found.
          renderStrategy = new WXJSObject(WXJSObject.String, "DATA_RENDER");
        } else if (instance.getRenderStrategy() == WXRenderStrategy.JSON_RENDER) {
          renderStrategy = new WXJSObject(WXJSObject.String, WXRenderStrategy.JSON_RENDER.getFlag());
        }

        WXJSObject[] args = {instanceIdObj, instanceObj, optionsObj,
                dataObj, apiObj, renderStrategy, extraOptionObj};

        instance.setTemplate(template.getContent());

        instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_END);

        // if { "framework": "Vue" } or  { "framework": "Rax" } will use invokeCreateInstanceContext
        // others will use invokeExecJS
        if (!isSandBoxContext) {
          instance.getApmForInstance().onStage("!isSandBoxContext,and excute");
          WXLogUtils.e("Instance " + instance.getInstanceId() + " Did Not Render in SandBox Mode");
          invokeExecJS(instance.getInstanceId(), null, METHOD_CREATE_INSTANCE, args, false);
          return;
        }
        if (type == BundType.Vue || type == BundType.Rax
                || instance.isUsingEaglePlugin()
                || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY //Todo only for compat when plugin not registered
                || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER
                || instance.getRenderStrategy() == WXRenderStrategy.JSON_RENDER) {
          instance.getApmForInstance().onStage("wxBeforeInvokeCreateInstanceContext");

          WXLogUtils.d("Instance " + instance.getInstanceId() + " Render in SandBox Mode And Render Type is "
                  + type + " Render Strategy is " + instance.getRenderStrategy());
          //extra args for create instance.
          args = Arrays.copyOf(args,args.length+1);
          args[args.length -1 ] = scriptType;

          int ret = invokeCreateInstanceContext(instance.getInstanceId(), null, "createInstanceContext", args, false);
          instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_END);
          if(ret == 0) {
            String err = "[WXBridgeManager] invokeCreateInstance : " + instance.getTemplateInfo();
            WXLogUtils.e("Instance " + instance.getInstanceId() + "Render error : " + err);
            instance.onRenderError(
                    WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(),
                    WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg() + err);
          }
          return;
        } else {
          //bad case for js bundle with out bundletype header //vue or rax
          //WXExceptionUtils.commitCriticalExceptionRT(
          //      instance.getInstanceId(),
          //      WXErrorCode.WX_KEY_EXCEPTION_NO_BUNDLE_TYPE,
          //      "invokeCreateInstance",
          //      WXErrorCode.WX_KEY_EXCEPTION_NO_BUNDLE_TYPE.getErrorMsg(),
          //      null
          //);

          WXLogUtils.d("Instance " + instance.getInstanceId() + "Did not Render in SandBox Mode And Render Type is "
                + type + " Render Strategy is " + instance.getRenderStrategy());
          instance.getApmForInstance().onStage("StartInvokeExecJSBadBundleType");
          invokeExecJS(instance.getInstanceId(), null, METHOD_CREATE_INSTANCE, args, false);
          instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_END);
          return;
        }
      } catch (Throwable e) {
        String err = "[WXBridgeManager] invokeCreateInstance " + e.getCause()
                + instance.getTemplateInfo();
        instance.getApmForInstance().onStage("createInstance error :"+e.toString());
        WXLogUtils.e("Instance " + instance.getInstanceId() + "Render error : " + err);
        instance.onRenderError(
                WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(),
                WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg() + err);
        WXLogUtils.e(err);
      }
    }
  }

  public WXJSObject optionObjConvert(boolean useSandBox, BundType type, WXJSObject opt) {
    if (!useSandBox) {
      return opt;
    }
    try {
      String data = opt.data.toString();
      JSONObject obj = JSON.parseObject(data);
      JSONObject optEnv;
      if ((optEnv = obj.getJSONObject("env")) != null) {
        JSONObject opts = optEnv.getJSONObject("options");
        if (opts != null) {
          for (String s : opts.keySet()) {
            optEnv.put(s, opts.getString(s));
          }
        }
      }
      return new WXJSObject(WXJSObject.JSON, obj.toString());
    } catch (Throwable e) {
      WXLogUtils.e(WXLogUtils.getStackTrace(e));
    }
    return opt;

  }

  /**
   * check bundleType
   * @param url
   * @param temp
   * @return
   */
  public BundType getBundleType(String url, String temp) {
    try {
      if (url != null) {
        Uri uri = Uri.parse(url);
        String type = uri.getQueryParameter(BUNDLE_TYPE);
        if ("Vue".equals(type) || "vue".equals(type)) {
          return BundType.Vue;
        } else if ("Rax".equals(type) || "rax".equals(type)) {
          return BundType.Rax;
        }
      }
      if (temp != null) {
        final String FRAMEWORK="framework", VUE="vue", RAX="rax";

        // Find the first line that starts with '//' and convert it to json
        int bundleTypeStart = temp.indexOf("//");
        int bundleTypeEnd = temp.indexOf("\n", bundleTypeStart);
        JSONObject bundleType = JSONObject.parseObject(
            temp.substring(bundleTypeStart+2, bundleTypeEnd));
        String type = bundleType.getString(FRAMEWORK);
        if(VUE.equalsIgnoreCase(type)){
          return BundType.Vue;
        }
        else if(RAX.equalsIgnoreCase(type)){
          return BundType.Rax;
        }
        else{
          // '//{ "framework": "Vue"}' is not found.
          String regEx = "(use)(\\s+)(weex:vue)";
          Pattern pattern = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
          if (pattern.matcher(temp).find()) {
            return BundType.Vue;
          }
          regEx = "(use)(\\s+)(weex:rax)";
          pattern = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
          if (pattern.matcher(temp).find()) {
            return BundType.Rax;
          }
        }
      }
      return BundType.Others;
    } catch (Throwable e) {
      WXLogUtils.e(WXLogUtils.getStackTrace(e));
      return BundType.Others;
    }
  }

  private void mock(String instanceId) {

  }

  public void destroyInstance(final String instanceId) {
    if (mJSHandler == null
            || TextUtils.isEmpty(instanceId)) {
      return;
    }
    if (mDestroyedInstanceId != null) {
      mDestroyedInstanceId.add(instanceId);
    }
    // clear message with instanceId
    mJSHandler.removeCallbacksAndMessages(instanceId);
    post(new Runnable() {
      @Override
      public void run() {
        removeTaskByInstance(instanceId);
        invokeDestroyInstance(instanceId);
      }
    }, instanceId, null, "destroyInstance");
  }

  private void removeTaskByInstance(String instanceId) {
    mNextTickTasks.removeFromMapAndStack(instanceId);
  }

  private void invokeDestroyInstance(String instanceId) {
    try {
      if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
        WXLogUtils.d("destroyInstance >>>> instanceId:" + instanceId);
      }
      WXJSObject instanceIdObj = new WXJSObject(WXJSObject.String,
              instanceId);
      WXJSObject[] args = {instanceIdObj};
      if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
        invokeDestoryInstance(instanceId, null, METHOD_DESTROY_INSTANCE, args, true);
        // invokeExecJS(instanceId, null, METHOD_DESTROY_INSTANCE, args);
      }
    } catch (Throwable e) {
      String err = "[WXBridgeManager] invokeDestroyInstance " + e.getCause();
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "invokeDestroyInstance", err, null);
      WXLogUtils.e(err);
    }
  }

  @Override
  public boolean handleMessage(Message msg) {
    if (msg == null) {
      return false;
    }

    int what = msg.what;
    switch (what) {
      case WXJSBridgeMsgType.INIT_FRAMEWORK:
        invokeInitFramework(msg);
        break;
      case WXJSBridgeMsgType.CALL_JS_BATCH:
        invokeCallJSBatch(msg);
        break;
      case WXJSBridgeMsgType.SET_TIMEOUT:
        TimerInfo timerInfo = (TimerInfo) msg.obj;
        if (timerInfo == null) {
          break;
        }
        WXJSObject obj = new WXJSObject(WXJSObject.String, timerInfo.callbackId);
        WXJSObject[] args = {obj};
        invokeExecJS("", null, METHOD_SET_TIMEOUT, args);
        break;
      case WXJSBridgeMsgType.TAKE_HEAP_SNAPSHOT:
        if (msg.obj != null) {
          String filename = (String) msg.obj;
          mWXBridge.takeHeapSnapshot(filename);
        }
        break;
      default:
        break;
    }
    return false;
  }

  private void invokeExecJS(String instanceId, String namespace, String function, WXJSObject[] args) {
    invokeExecJS(instanceId, namespace, function, args, true);
  }

  public void invokeExecJS(final String instanceId, final String namespace, final String function,
                           final WXJSObject[] args, boolean logTaskDetail) {
    if (WXEnvironment.isOpenDebugLog() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("callJS >>>> instanceId:").append(instanceId)
              .append("function:").append(function);
      if (logTaskDetail) {
        mLodBuilder.append(" tasks:").append(argsToJSON(args));
      }
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }
    final long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);

    if (instance != null && instance.isUsingEaglePlugin()) {
      final WXEaglePlugin eaglePlugin = instance.getEaglePlugin();
      int mode = eaglePlugin.isSupportInvokeExecJS(instanceId);
      if (mode == WXEaglePlugin.NOT_SUPPORT){
        return;
      }
      WXThread.secure(new Runnable() {
        @Override
        public void run() {
          eaglePlugin.invokeExecJS(instanceId, namespace, function,args );
        }
      }, instance, "ExecJsEagle").run();
      if (mode == WXEaglePlugin.EAGLE_ONLY){
        if (null != instance){
          long diff = System.currentTimeMillis()-start;
          instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_JS_NUM,1);
          instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_JS_TIME,diff);
          instance.callJsTime(diff);
        }
        return;
      }
      //assert mode == WXEaglePlugin.EAGLE_AND_SCRIPT
    }

    WXThread.secure(new Runnable() {
      @Override
      public void run() {
        mWXBridge.execJS(instanceId, namespace, function, args);
      }
    }, instance, "ExecJs").run();
    if (null != instance){
      long diff = System.currentTimeMillis()-start;
      instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_JS_NUM,1);
      instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_JS_TIME,diff);
      instance.callJsTime(diff);
    }
  }

  private Pair<Pair<String,Object>,Boolean> extractCallbackArgs(String data) {
    try {
      JSONArray obj = JSON.parseArray(data);
      JSONObject arg_obj = obj.getJSONObject(0);
      JSONArray args = arg_obj.getJSONArray("args");
      if (args.size()!=3){
        return null;
      }
      String method = arg_obj.getString("method");
      if (!"callback".equals(method)){
        return null;
      }

      return new Pair<Pair<String,Object>, Boolean>(new Pair<String, Object>(args.getString(0), args.getJSONObject(1)),args.getBooleanValue(2));
    } catch (Exception e) {
      return null;
    }
  }

  public int invokeCreateInstanceContext(String instanceId, String namespace, String function,
                                          WXJSObject[] args, boolean logTaskDetail) {
    WXLogUtils.d("invokeCreateInstanceContext instanceId:" + instanceId + " function:"
            + function + String.format(" isJSFrameworkInit：%b", isJSFrameworkInit()));
    mLodBuilder.append("createInstanceContext >>>> instanceId:").append(instanceId)
            .append("function:").append(function);
    if (logTaskDetail)
      mLodBuilder.append(" tasks:").append(WXJsonUtils.fromObjectToJSONString(args));
    WXLogUtils.d(mLodBuilder.substring(0));
    mLodBuilder.setLength(0);
    // }
    return mWXBridge.createInstanceContext(instanceId, namespace, function, args);
  }

  public void invokeDestoryInstance(String instanceId, String namespace, String function,
                                    WXJSObject[] args, boolean logTaskDetail) {
    // if (WXEnvironment.isApkDebugable()) {
    mLodBuilder.append("callJS >>>> instanceId:").append(instanceId)
            .append("function:").append(function);
    if (logTaskDetail)
      mLodBuilder.append(" tasks:").append(WXJsonUtils.fromObjectToJSONString(args));
    WXLogUtils.d(mLodBuilder.substring(0));
    mLodBuilder.setLength(0);
    // }
    mWXBridge.removeInstanceRenderType(instanceId);
    mWXBridge.destoryInstance(instanceId, namespace, function, args);
  }

  private void execJSOnInstance(final EventResult eventCallback, final String instanceId, final String js, final int type) {
    post(new Runnable() {
      @Override
      public void run() {
        String ret = invokeExecJSOnInstance(instanceId, js, type);
        eventCallback.onCallback(ret);
      }
    });
  }

  private String invokeExecJSOnInstance(String instanceId, String js, int type) {
    // if (WXEnvironment.isApkDebugable()) {
    mLodBuilder.append("execJSOnInstance >>>> instanceId:").append(instanceId);
    WXLogUtils.d(mLodBuilder.substring(0));
    mLodBuilder.setLength(0);
    // }
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      return mWXBridge.execJSOnInstance(instanceId, js, type);
    }
    return null;
  }

  private void invokeExecJSWithCallback(String instanceId, String namespace, String function,
                                        WXJSObject[] args , ResultCallback callback, boolean logTaskDetail){
    if (WXEnvironment.isOpenDebugLog() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("callJS >>>> instanceId:").append(instanceId)
              .append("function:").append(function);
      if(logTaskDetail) {
        mLodBuilder.append(" tasks:").append(argsToJSON(args));
      }
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.execJSWithCallback(instanceId, namespace, function, args, callback);
    }
  }

  public @NonNull static String argsToJSON(WXJSObject[] args) {
    StringBuilder builder = new StringBuilder();
    builder.append("[");
    for(WXJSObject object : args){
      builder.append(WXWsonJSONSwitch.fromObjectToJSONString(object));
      builder.append(",");
    }
    builder.append("]");
    return  builder.toString();
  }

  private void invokeInitFramework(Message msg) {
    String framework = "";
    if (msg.obj != null) {
      framework = (String) msg.obj;
    }

    if (WXUtils.getAvailMemory(WXEnvironment.getApplication()) > LOW_MEM_VALUE) {
      initFramework(framework);
    }
  }

  public static long sInitFrameWorkTimeOrigin;
  public static StringBuilder sInitFrameWorkMsg = new StringBuilder();

  private void initFramework(String framework) {
    LogDetail logDetail = new LogDetail();
    logDetail.name("initFramework");
    logDetail.taskStart();
    if (WXSDKEngine.isSoInitialized() && !isJSFrameworkInit()) {
      sInitFrameWorkTimeOrigin = System.currentTimeMillis();
      if (TextUtils.isEmpty(framework)) {
        // if (WXEnvironment.isApkDebugable()) {
        WXLogUtils.d("weex JS framework from assets");
        // }

        LogDetail logDetail2 = new LogDetail();
        logDetail2.name("loadJSFramework");
        logDetail2.taskStart();

        IWXJsFileLoaderAdapter wxJsFileLoaderAdapter = WXSDKEngine.getIWXJsFileLoaderAdapter();

        if (!isSandBoxContext) {
          if(wxJsFileLoaderAdapter != null) {
            framework = wxJsFileLoaderAdapter.loadJsFramework();
          }

          if(TextUtils.isEmpty(framework)) {
            framework = WXFileUtils.loadAsset("main.js", WXEnvironment.getApplication());
          }
        } else {
          if(wxJsFileLoaderAdapter != null) {
            framework = wxJsFileLoaderAdapter.loadJsFrameworkForSandBox();
          }

          if(TextUtils.isEmpty(framework)) {
            framework = WXFileUtils.loadAsset("weex-main-jsfm.js", WXEnvironment.getApplication());
          }
        }
        sInitFrameWorkMsg.append("| weex JS framework from assets, isSandBoxContext: ").append(isSandBoxContext);
        logDetail2.taskEnd();
      }
      if (TextUtils.isEmpty(framework)) {
        setJSFrameworkInit(false);
        sInitFrameWorkMsg.append("| framework isEmpty ");
        WXExceptionUtils.commitCriticalExceptionRT(null, WXErrorCode.WX_ERR_JS_FRAMEWORK,
                "initFramework", "framework is empty!! ", null);
        return;
      }
      try {
        if (WXSDKManager.getInstance().getWXStatisticsListener() != null) {
          long start = System.currentTimeMillis();
          WXSDKManager.getInstance().getWXStatisticsListener().onJsFrameworkStart();
          WXEnvironment.sJSFMStartListenerTime = System.currentTimeMillis() - start;
          try {
            IWXUserTrackAdapter adapter = WXSDKManager.getInstance().getIWXUserTrackAdapter();
            if (null != adapter){
              Map<String,Serializable> params = new HashMap<>(1);
              params.put("time",String.valueOf(WXEnvironment.sJSFMStartListenerTime));
              adapter.commit(WXEnvironment.getApplication(),"sJSFMStartListener",IWXUserTrackAdapter.COUNTER,null,params);
            }
          }catch (Exception e){
            WXLogUtils.e(WXLogUtils.getStackTrace(e));
          }
        }

        long start = System.currentTimeMillis();
        String crashFile = "";
        try {
          crashFile = WXEnvironment.getApplication().getApplicationContext().getCacheDir().getPath();
        } catch (Exception e) {
          WXLogUtils.e(WXLogUtils.getStackTrace(e));
        }
        boolean pieSupport = true;
        try {
          if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            pieSupport = false;
          }
        } catch (Exception e) {
          WXLogUtils.e(WXLogUtils.getStackTrace(e));
        }
        sInitFrameWorkMsg.append(" | pieSupport:").append(pieSupport);
        WXLogUtils.d("[WXBridgeManager] initFrameworkEnv crashFile:" + crashFile + " pieSupport:" + pieSupport);
        // extends initFramework
        LogDetail logDetail3 = new LogDetail();
        logDetail3.name("native initFrameworkEnv");
        logDetail3.taskStart();
        if (mWXBridge.initFrameworkEnv(framework, assembleDefaultOptions(), crashFile, pieSupport) == INIT_FRAMEWORK_OK) {
          logDetail3.taskEnd();
          WXEnvironment.sJSLibInitTime = System.currentTimeMillis() - start;
          WXEnvironment.sSDKInitTime = System.currentTimeMillis() - WXEnvironment.sSDKInitStart;
          setJSFrameworkInit(true);
          logDetail.taskEnd();
          if (WXSDKManager.getInstance().getWXStatisticsListener() != null) {
            WXSDKManager.getInstance().getWXStatisticsListener().onJsFrameworkReady();
          }

          execRegisterFailTask();
          WXEnvironment.JsFrameworkInit = true;
          sInitFrameWorkCount++;
          WXLogUtils.e("initFrameWorkCount :"+ sInitFrameWorkCount);
          registerDomModule();
          trackComponentAndModulesTime();
        } else {
          sInitFrameWorkMsg.append(" | ExecuteJavaScript fail, reInitCount").append(reInitCount);
          if (reInitCount > 1) {
            WXLogUtils.e("[WXBridgeManager] invokeReInitFramework  ExecuteJavaScript fail");
          } else {
            WXLogUtils.e("[WXBridgeManager] invokeInitFramework  ExecuteJavaScript fail");
          }
        }
      } catch (Throwable e) {
        sInitFrameWorkMsg.append(" | invokeInitFramework exception ").append(e.toString());
        if (reInitCount > 1) {
          WXLogUtils.e("[WXBridgeManager] invokeInitFramework ", e);
        } else {
          WXLogUtils.e("[WXBridgeManager] invokeInitFramework ", e);
        }
      }

    }
  }

  private void trackComponentAndModulesTime() {
    post(new Runnable() {
      @Override
      public void run() {
        WXEnvironment.sComponentsAndModulesReadyTime = System.currentTimeMillis() - WXEnvironment.sSDKInitStart;
      }
    });
  }

  @SuppressWarnings("unchecked")
  private void invokeCallJSBatch(Message message) {
    if (mNextTickTasks.isEmpty() || !isJSFrameworkInit()) {
      if (!isJSFrameworkInit()) {
        WXLogUtils.e("[WXBridgeManager] invokeCallJSBatch: framework.js uninitialized!!  message:" + message.toString());
      }
      return;
    }

    try {
      Object instanceId = message.obj;

      Object task = null;
      Stack<String> instanceStack = mNextTickTasks.getInstanceStack();
      int size = instanceStack.size();
      for (int i = size - 1; i >= 0; i--) {
        instanceId = instanceStack.get(i);
        task = mNextTickTasks.remove(instanceId);
        if (task != null && !((ArrayList) task).isEmpty()) {
          break;
        }
      }
      if (null != task){
        task = ((ArrayList) task).toArray();

        WXJSObject[] args = {
            new WXJSObject(WXJSObject.String, instanceId),
            WXWsonJSONSwitch.toWsonOrJsonWXJSObject(task)};

        invokeExecJS(String.valueOf(instanceId), null, METHOD_CALL_JS, args);
      }
    } catch (Throwable e) {
      WXLogUtils.e("WXBridgeManager", e);
      String err = "invokeCallJSBatch#" + WXLogUtils.getStackTrace(e);
      WXExceptionUtils.commitCriticalExceptionRT(null, WXErrorCode.WX_ERR_JS_FRAMEWORK,
              "invokeCallJSBatch", err, null);
    }

    // If task is not empty, loop until it is empty
    if (!mNextTickTasks.isEmpty()) {
      mJSHandler.sendEmptyMessage(WXJSBridgeMsgType.CALL_JS_BATCH);
    }
  }

  private WXParams assembleDefaultOptions() {
    checkJsEngineMultiThread();

    Map<String, String> config = WXEnvironment.getConfig();
    WXParams wxParams = new WXParams();
    wxParams.setPlatform(config.get(WXConfig.os));
    wxParams.setCacheDir(config.get(WXConfig.cacheDir));
    wxParams.setOsVersion(config.get(WXConfig.sysVersion));
    wxParams.setAppVersion(config.get(WXConfig.appVersion));
    wxParams.setWeexVersion(config.get(WXConfig.weexVersion));
    wxParams.setDeviceModel(config.get(WXConfig.sysModel));
    wxParams.setShouldInfoCollect(config.get("infoCollect"));
    wxParams.setLogLevel(config.get(WXConfig.logLevel));
    wxParams.setLayoutDirection(config.get(WXConfig.layoutDirection));
    wxParams.setUseSingleProcess(isUseSingleProcess ? "true" : "false");
    wxParams.setCrashFilePath(WXEnvironment.getCrashFilePath(WXEnvironment.getApplication().getApplicationContext()));
    wxParams.setLibJsbPath(WXEnvironment.CORE_JSB_SO_PATH);
    wxParams.setLibJssPath(WXEnvironment.getLibJssRealPath());
    wxParams.setLibIcuPath(WXEnvironment.getLibJssIcuPath());
    wxParams.setLibLdPath(WXEnvironment.getLibLdPath());
    String libJScRealPath = WXEnvironment.getLibJScRealPath();
    wxParams.setLibJscPath(TextUtils.isEmpty(libJScRealPath)? "" : new File(libJScRealPath).getParent());
    String appName = config.get(WXConfig.appName);
    if (!TextUtils.isEmpty(appName)) {
      wxParams.setAppName(appName);
    }
    wxParams.setDeviceWidth(TextUtils.isEmpty(config.get("deviceWidth")) ? String.valueOf(WXViewUtils.getScreenWidth(WXEnvironment.sApplication)) : config.get("deviceWidth"));
    wxParams.setDeviceHeight(TextUtils.isEmpty(config.get("deviceHeight")) ? String.valueOf(WXViewUtils.getScreenHeight(WXEnvironment.sApplication)) : config.get("deviceHeight"));
    Map<String, String> customOptions = WXEnvironment.getCustomOptions();
    customOptions.put("enableBackupThread", String.valueOf(jsEngineMultiThreadEnable()));
    IWXJscProcessManager wxJscProcessManager = WXSDKManager.getInstance().getWXJscProcessManager();
    if(wxJscProcessManager != null) {
      customOptions.put("enableBackupThreadCache", String.valueOf(wxJscProcessManager.enableBackUpThreadCache()));
    }

    if (!WXEnvironment.sUseRunTimeApi){
      customOptions.put("__enable_native_promise__","true");
    }

    String enableAlarmSignal = "true";
    IWXConfigAdapter adapter = WXSDKManager.getInstance().getWxConfigAdapter();
    if (null != adapter){
      try {
        if (adapter.checkMode("white_screen_fix_open")){
          WXEnvironment.isWsFixMode = true;
          enableAlarmSignal = "true";
        }else {
          enableAlarmSignal = adapter.getConfigWhenInit("wxapm","enableAlarmSignal",enableAlarmSignal);
          WXEnvironment.isWsFixMode = "true".equalsIgnoreCase(enableAlarmSignal);
        }
      }catch (Exception e){
        e.printStackTrace();
      }
    }
    if (null != enableAlarmSignal){
      customOptions.put("enableAlarmSignal",enableAlarmSignal);
    }
    WXLogUtils.e("weex","enableAlarmSignal:"+enableAlarmSignal);

    wxParams.setOptions(customOptions);
    wxParams.setNeedInitV8(WXSDKManager.getInstance().needInitV8());
    mInitParams = wxParams;
    return wxParams;
  }

  public WXParams getInitParams() {
    return mInitParams;
  }

  private void execRegisterFailTask() {

    if (mRegisterModuleFailList.size() > 0) {
      List<Map<String, Object>> moduleReceiver = new ArrayList<>();
      for (int i = 0, moduleCount = mRegisterModuleFailList.size(); i < moduleCount; ++i) {
        invokeRegisterModules(mRegisterModuleFailList.get(i), moduleReceiver);
      }
      mRegisterModuleFailList.clear();
      if (moduleReceiver.size() > 0) {
        mRegisterModuleFailList.addAll(moduleReceiver);
      }
    }

    if (mRegisterComponentFailList.size() > 0) {
      List<Map<String, Object>> receiver = new ArrayList<>();
      invokeRegisterComponents(mRegisterComponentFailList, receiver);
      mRegisterComponentFailList.clear();
      if (receiver.size() > 0) {
        mRegisterComponentFailList.addAll(receiver);
      }
    }

    if (mRegisterServiceFailList.size() > 0) {
      List<String> receiver = new ArrayList<>();
      for (String service : mRegisterServiceFailList) {
        invokeExecJSService(service, receiver);
      }
      mRegisterServiceFailList.clear();
      if (receiver.size() > 0) {
        mRegisterServiceFailList.addAll(receiver);
      }
    }
  }

  /**
   * Register Android module
   *
   * @param modules the format is like
   *                {'dom':['updateAttrs','updateStyle'],'event':['openUrl']}
   */

  public void registerModules(final Map<String, Object> modules) {
    if (modules != null && modules.size() != 0) {
      if (isJSThread()) {
        invokeRegisterModules(modules, mRegisterModuleFailList);
      } else {
        post(new Runnable() {
          @Override
          public void run() {
            invokeRegisterModules(modules, mRegisterModuleFailList);
          }
        });
      }
    }
  }

  /**
   * Registered component
   */
  public void registerComponents(final List<Map<String, Object>> components) {
    if (mJSHandler == null || components == null
            || components.size() == 0) {
      return;
    }
    Runnable runnable = new Runnable() {
      @Override
      public void run() {
        invokeRegisterComponents(components, mRegisterComponentFailList);
      }
    };

    if(isJSThread() && isJSFrameworkInit()){
      runnable.run();
    }else{
      post(runnable);
    }
  }

  public void execJSService(final String service) {
    postWithName(new Runnable() {
      @Override
      public void run() {
        invokeExecJSService(service, mRegisterServiceFailList);
      }
    },null,"execJSService");
  }

  private void invokeExecJSService(String service, List<String> receiver) {
    try {
      if (!isJSFrameworkInit()) {
        WXLogUtils.e("[WXBridgeManager] invoke execJSService: framework.js uninitialized.");
        receiver.add(service);
        return;
      }
      mWXBridge.execJSService(service);
    } catch (Throwable e) {
      WXLogUtils.e("[WXBridgeManager] invokeRegisterService:", e);

      Map<String, String> data = new HashMap<String, String>();
      data.put("inputParams",service + "||" + receiver.toString());

      WXExceptionUtils.commitCriticalExceptionRT("invokeExecJSService",
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_JSSERVICE_EXECUTE,
              "invokeExecJSService",
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_JSSERVICE_EXECUTE.getErrorMsg()
                      + "[WXBridgeManager] invokeRegisterService:"
                      + WXLogUtils.getStackTrace(e),
              data);
    }
  }

  public boolean isJSThread() {
    return mJSThread != null && mJSThread.getId() == Thread.currentThread().getId();
  }

  private void invokeRegisterModules(Map<String, Object> modules, List<Map<String, Object>> failReceiver) {
    if (modules == null || !isJSFrameworkInit()) {
      if (!isJSFrameworkInit()) {
        WXLogUtils.d("[WXinvokeRegisterModulesBridgeManager] invokeRegisterModules: framework.js uninitialized.");
      }
      failReceiver.add(modules);
      return;
    }

    WXJSObject[] args = {WXWsonJSONSwitch.toWsonOrJsonWXJSObject(modules)};
    String errorMsg = null;
    try {
        if(0 == mWXBridge.execJS("", null, METHOD_REGISTER_MODULES, args)) {
            errorMsg = "execJS error";
        }
      try {
        Iterator<String> iter = modules.keySet().iterator();
        while (iter.hasNext()) {
          String module = iter.next();
          if (module != null) {
            WXModuleManager.resetModuleState(module, true);
            //WXLogUtils.e("[WXBridgeManager]invokeRegisterModules METHOD_REGISTER_MODULES success module:" + module);
          }
        }
      } catch (Throwable e) {
        WXLogUtils.e("Weex [invokeRegisterModules]", e);
      }
    } catch (Throwable e) {
      errorMsg = WXErrorCode.WX_KEY_EXCEPTION_INVOKE_REGISTER_MODULES.getErrorMsg() +
                " \n " + e.getMessage() + modules.entrySet().toString();
    }

    if(!TextUtils.isEmpty(errorMsg)) {
        WXLogUtils.e("[WXBridgeManager] invokeRegisterModules:", errorMsg);
        WXExceptionUtils.commitCriticalExceptionRT(null,
                WXErrorCode.WX_KEY_EXCEPTION_INVOKE_REGISTER_MODULES,
                "invokeRegisterModules", errorMsg,
                null );
    }
  }

  private void invokeRegisterComponents(List<Map<String, Object>> components, List<Map<String, Object>> failReceiver) {
    if (components == failReceiver) {
      throw new RuntimeException("Fail receiver should not use source.");
    }
    if (!isJSFrameworkInit()) {
      //WXLogUtils.e("[WXBridgeManager] invokeRegisterComponents: framework.js uninitialized.");

      for (Map<String, Object> comp : components) {
        failReceiver.add(comp);
      }
      return;
    }
    if (components == null) {
      return;
    }

    WXJSObject[] args = {WXWsonJSONSwitch.toWsonOrJsonWXJSObject(components)};
    String errorMsg = null;
    try {
      if(0 == mWXBridge.execJS("", null, METHOD_REGISTER_COMPONENTS, args)) {
          errorMsg = "execJS error";
      }
    } catch (Throwable e) {
        errorMsg = WXErrorCode.WX_KEY_EXCEPTION_INVOKE_REGISTER_COMPONENT
                + args.toString()
                + WXLogUtils.getStackTrace(e);
    }

    if(!TextUtils.isEmpty(errorMsg)) {
        WXLogUtils.e("[WXBridgeManager] invokeRegisterComponents ", errorMsg);
        WXExceptionUtils.commitCriticalExceptionRT(null,
                WXErrorCode.WX_KEY_EXCEPTION_INVOKE_REGISTER_COMPONENT,
                METHOD_REGISTER_COMPONENTS, errorMsg,
                null);
    }
  }

  public void destroy() {
    if (mJSThread != null) {
      mJSThread.quit();
    }
    mBridgeManager = null;
    if (mDestroyedInstanceId != null) {
      mDestroyedInstanceId.clear();
    }

  }

  /**
   * Report JavaScript Exception
   */
  public void reportJSException(String instanceId, String function,
                                String exception) {
    WXLogUtils.e("reportJSException >>>> instanceId:" + instanceId
            + ", exception function:" + function + ", exception:"
            + exception);
    WXSDKInstance instance = null;
    WXErrorCode reportErrorCode = WXErrorCode.WX_ERR_JS_EXECUTE;
    if (instanceId != null && (instance = WXSDKManager.getInstance().getSDKInstance(instanceId)) != null) {
      instance.setHasException(true);
      exception +=   "\n getTemplateInfo==" +instance.getTemplateInfo();//add network header info
      if ((METHOD_CREATE_INSTANCE.equals(function)) || !instance.isContentMd5Match()) {
        try {
          //data render mode should report exception instead of reload page,
          // so we use !isSkipFrameworkInit(instanceId) to skip the positive branch of if clause.
          if (!isSkipFrameworkInit(instanceId) && isJSFrameworkInit() && (reInitCount > 1 && reInitCount < 10) && !instance.isNeedReLoad()) {
            new ActionReloadPage(instanceId, true).executeAction();
            instance.setNeedLoad(true);
            return;
          } else {
            String errorMsg = new StringBuilder()
                .append(WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg())
                .append(", exception function:").append(function)
                .append(", exception:").append(exception)
                .append(", extInitTime:").append(System.currentTimeMillis()-WXBridgeManager.sInitFrameWorkTimeOrigin).append("ms")
                .append(", extInitErrorMsg:").append(WXBridgeManager.sInitFrameWorkMsg.toString())
                .toString();
            instance.onRenderError(//DegradPassivity to H5
                     WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(),
                     errorMsg
            );
            if (!WXEnvironment.sInAliWeex){
              WXExceptionUtils.commitCriticalExceptionRT(instanceId, WXErrorCode.WX_RENDER_ERR_JS_CREATE_INSTANCE, function,exception,null);
            }
            return;
          }
        } catch (Exception e) {
          WXLogUtils.e(WXLogUtils.getStackTrace(e));
        }
      }
      if (METHOD_CREATE_INSTANCE.equals(function) && !instance.getApmForInstance().hasAddView){
        reportErrorCode = WXErrorCode.WX_RENDER_ERR_JS_CREATE_INSTANCE;
      } else if ( METHOD_CREATE_INSTANCE_CONTEXT.equals(function) && !instance.getApmForInstance().hasAddView){
        reportErrorCode = WXErrorCode.WX_RENDER_ERR_JS_CREATE_INSTANCE_CONTEXT;
      } else if (
          (METHOD_UPDATE_COMPONENT_WITH_DATA.equals(function) ||
          METHOD_CREATE_PAGE_WITH_CONTENT.equals(function) ||
          METHOD_POST_TASK_TO_MSG_LOOP.equals(function) ||
              METHOD_JSFM_NOT_INIT_IN_EAGLE_MODE.equals(function) )
          && !instance.getApmForInstance().hasAddView){
        reportErrorCode = WXErrorCode.WX_DEGRAD_EAGLE_RENDER_ERROR;
      } else if (METHOD_MOVE_RENDER_OBJECT.equals(function)) {
        reportErrorCode = WXErrorCode.WX_ERROR_MOVE_RENDER_OBJECT_OUT_OF_BOUNDS;
      }
      instance.onJSException(reportErrorCode.getErrorCode(), function, exception);
    }
    doReportJSException(instanceId,function,reportErrorCode,exception);
  }

  private void doReportJSException(String instanceId, String function,WXErrorCode reportCode, String exception){
    WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId);
    IWXJSExceptionAdapter adapter = WXSDKManager.getInstance().getIWXJSExceptionAdapter();
    if (adapter != null) {
      String exceptionId = instanceId;

      if (TextUtils.isEmpty(instanceId)) {
        exceptionId = "instanceIdisNull";
      }

      if (instance == null) {
        if (("initFramework").equals(function)) {
          String exceptionExt = null;
          try {
            if (WXEnvironment.getApplication() != null) {
              final String fileName = WXEnvironment.getApplication().getApplicationContext().getCacheDir().getPath() + INITLOGFILE;
              try {
                File file = new File(fileName);
                if (file.exists()) {
                  if (file.length() > 0) {
                    StringBuilder result = new StringBuilder();
                    try {
                      InputStreamReader read = new InputStreamReader(new FileInputStream(file), "UTF-8");
                      BufferedReader br = new BufferedReader(read);
                      String s = null;
                      while ((s = br.readLine()) != null) {
                        result.append(s + "\n");
                      }
                      exceptionExt = result.toString();
                      br.close();
                    } catch (Exception e) {
                      WXLogUtils.e(WXLogUtils.getStackTrace(e));
                    }
                  }
                  file.delete();
                }
              } catch (Throwable throwable) {
                WXLogUtils.e(WXLogUtils.getStackTrace(throwable));
              }
            }
          } catch (Throwable e) {
            WXLogUtils.e(WXLogUtils.getStackTrace(e));
          }
          exception += "\n" + exceptionExt;
          WXLogUtils.e("reportJSException:" + exception);

        }
      }


      WXExceptionUtils.commitCriticalExceptionRT(exceptionId, reportCode,
            function,
          reportCode.getErrorMsg() + exception,
            null);

    }
  }

  private void registerDomModule() throws WXException {
    /** Tell Javascript Framework what methods you have. This is Required.**/
    Map<String, Object> domMap = new HashMap<>();
    domMap.put(WXDomModule.WXDOM, WXDomModule.METHODS);
    registerModules(domMap);
  }

  //This method is deprecated because of performance issue.
  @Deprecated
  public void notifyTrimMemory() {

  }

  /**
   * update js server global config, current support turn wson off
   * by pass wson_off
   * */
  public static void  updateGlobalConfig(String config) {
    if(TextUtils.isEmpty(config)){
      config = "none";
    }
    if(!TextUtils.equals(config, globalConfig)){
      globalConfig = config;
      WXEnvironment.addCustomOptions(GLOBAL_CONFIG_KEY, globalConfig);
      Runnable runnable = new Runnable() {
        @Override
        public void run() {
          if(mBridgeManager != null){
            if(mBridgeManager.isJSFrameworkInit()){
              if(mBridgeManager.mWXBridge instanceof WXBridge) {
                final WXBridge bridge = (WXBridge) mBridgeManager.mWXBridge;
                bridge.nativeUpdateGlobalConfig(globalConfig);
              }
            }
          }
          if(globalConfig.contains(WXWsonJSONSwitch.WSON_OFF)){
            WXWsonJSONSwitch.USE_WSON = false;
          }else{
            WXWsonJSONSwitch.USE_WSON = true;
          }
        }
      };
      if(mBridgeManager != null && mBridgeManager.isJSFrameworkInit()){
        mBridgeManager.post(runnable);
      }else{
        runnable.run();
      }
    }
  }

  public
  @Nullable
  Looper getJSLooper() {
    Looper ret = null;
    if (mJSThread != null) {
      ret = mJSThread.getLooper();
    }
    return ret;
  }

  public void notifySerializeCodeCache() {
    post(new Runnable() {
      @Override
      public void run() {
        if (!isJSFrameworkInit())
          return;

        invokeExecJS("", null, METHOD_NOTIFY_SERIALIZE_CODE_CACHE, new WXJSObject[0]);
      }
    });
  }

  public void takeJSHeapSnapshot(String filename) {
    Message msg = mJSHandler.obtainMessage();
    msg.obj = filename;
    msg.what = WXJSBridgeMsgType.TAKE_HEAP_SNAPSHOT;
    msg.setTarget(mJSHandler);
    msg.sendToTarget();
  }

  public static class TimerInfo {

    public String callbackId;
    public long time;
    public String instanceId;
  }

  public int callCreateBody(String pageId, String componentType, String ref,
                            HashMap<String, String> styles, HashMap<String, String> attributes, HashSet<String> events,
                            float[] margins, float[] paddings, float[] borders) {

    if (TextUtils.isEmpty(pageId) || TextUtils.isEmpty(componentType) || TextUtils.isEmpty(ref)) {
      WXLogUtils.d("[WXBridgeManager] call callCreateBody arguments is null");
      WXExceptionUtils.commitCriticalExceptionRT(pageId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callCreateBody",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callCreateBody >>>> pageId:").append(pageId)
              .append(", componentType:").append(componentType).append(", ref:").append(ref)
              .append(", styles:").append(styles == null ? "{}" : styles.toString())
              .append(", attributes:").append(attributes)
              .append(", events:").append(events);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(pageId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(pageId);
      if (instance != null) {
        final BasicGraphicAction action = new GraphicActionCreateBody(instance, ref, componentType,
                styles, attributes, events, margins, paddings, borders);
        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callCreateBody exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(pageId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callCreateBody",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callAddElement(String pageId, String componentType, String ref, int index, String parentRef,
                            HashMap<String, String> styles, HashMap<String, String> attributes, HashSet<String> events,
                            float[] margins, float[] paddings, float[] borders,boolean willLayout) {
    if (TextUtils.isEmpty(pageId) || TextUtils.isEmpty(componentType) || TextUtils.isEmpty(ref)) {
      if (WXEnvironment.isApkDebugable()){
        WXLogUtils.d("[WXBridgeManager] call callAddElement arguments is null");
      }
      WXExceptionUtils.commitCriticalExceptionRT(pageId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callAddElement",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callAddElement >>>> pageId:").append(pageId)
              .append(", componentType:").append(componentType).append(", ref:").append(ref).append(", index:").append(index)
              .append(", parentRef:").append(parentRef)
              .append(", styles:").append(styles == null ? "{}" : styles.toString())
              .append(", attributes:").append(attributes)
              .append(", events:").append(events);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(pageId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(pageId);
      if (instance != null) {
        final GraphicActionAddElement action = new GraphicActionAddElement(instance, ref, componentType, parentRef, index,
            styles, attributes, events, margins, paddings, borders);
        if(willLayout) {
          instance.addInActiveAddElementAction(ref, action);
        }else{
          WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(pageId, action);
        }
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callAddElement exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(pageId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callAddElement",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callRemoveElement(String instanceId, String ref) {

    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) {
      if (WXEnvironment.isApkDebugable()){
        WXLogUtils.d("[WXBridgeManager] call callRemoveElement arguments is null");
      }
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callRemoveElement",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callRemoveElement >>>> instanceId:").append(instanceId)
              .append(", ref:").append(ref);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        final BasicGraphicAction action = new GraphicActionRemoveElement(instance, ref);
        if(instance.getInActiveAddElementAction(ref)!=null){
          instance.removeInActiveAddElmentAction(ref);
        }
        else {
          WXSDKManager.getInstance().getWXRenderManager()
              .postGraphicAction(action.getPageId(), action);
        }
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callRemoveElement exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callRemoveElement",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callMoveElement(String instanceId, String ref, String parentref, int index) {

    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref) || TextUtils.isEmpty(parentref)) {
      if (WXEnvironment.isApkDebugable()){
        WXLogUtils.d("[WXBridgeManager] call callMoveElement arguments is null");
      }
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callMoveElement",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callMoveElement >>>> instanceId:").append(instanceId)
              .append(", parentref:").append(parentref)
              .append(", index:").append(index)
              .append(", ref:").append(ref);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        final BasicGraphicAction action = new GraphicActionMoveElement(instance, ref, parentref, index);
        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callMoveElement exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callMoveElement",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callAddEvent(String instanceId, String ref, String event) {

    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref) || TextUtils.isEmpty(event)) {
      if (WXEnvironment.isApkDebugable()){
        WXLogUtils.d("[WXBridgeManager] call callAddEvent arguments is null");
      }
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callAddEvent",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callAddEvent >>>> instanceId:").append(instanceId)
              .append(", ref:").append(ref)
              .append(", event:").append(event);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        new GraphicActionAddEvent(instance, ref, event).executeActionOnRender();
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callAddEvent exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callAddEvent",
              WXLogUtils.getStackTrace(e), null);
    }

    // get next tick
    getNextTick(instanceId);
    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callRemoveEvent(String instanceId, String ref, String event) {

    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref) || TextUtils.isEmpty(event)) {
      if (WXEnvironment.isApkDebugable()){
        WXLogUtils.d("[WXBridgeManager] call callRemoveEvent arguments is null");
      }
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callRemoveEvent",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callRemoveEvent >>>> instanceId:").append(instanceId)
              .append(", ref:").append(ref)
              .append(", event:").append(event);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        new GraphicActionRemoveEvent(instance, ref, event).executeActionOnRender();
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callRemoveEvent exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callRemoveEvent",
              WXLogUtils.getStackTrace(e), null);
    }

    // get next tick
    getNextTick(instanceId);
    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callUpdateStyle(String instanceId, String ref, HashMap<String, Object> styles,
                             HashMap<String, String> paddings,
                             HashMap<String, String> margins,
                             HashMap<String, String> borders) {

    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) {
      if (WXEnvironment.isApkDebugable()){
        WXLogUtils.d("[WXBridgeManager] call callUpdateStyle arguments is null");
      }

      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callUpdateStyle",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callUpdateStyle >>>> instanceId:").append(instanceId)
              .append(", ref:").append(ref).append(", styles:").append(styles == null ? "{}" : styles.toString())
              .append(", paddings:").append(paddings.toString())
                      .append(", margins:").append(margins.toString())
                              .append(", borders:").append(borders.toString());
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        final BasicGraphicAction action = new GraphicActionUpdateStyle(instance, ref, styles, paddings, margins, borders);
        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callUpdateStyle exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callUpdateStyle",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callUpdateAttrs(String instanceId, String ref, HashMap<String, String> attrs) {

    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) {
      if (WXEnvironment.isApkDebugable()){
        WXLogUtils.d("[WXBridgeManager] call callUpdateAttrs arguments is null");
      }

      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callUpdateAttrs",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callUpdateAttrs >>>> instanceId:").append(instanceId)
              .append(", ref:").append(ref).append(", attrs:").append(attrs.toString());
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        final BasicGraphicAction action = new GraphicActionUpdateAttr(instance, ref, attrs);
        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callUpdateAttrs exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callUpdateAttrs",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  private void setExceedGPULimitComponentsInfo(String instanceId,String ref,GraphicSize layoutSize){
    float limit = WXRenderManager.getOpenGLRenderLimitValue();
    if(limit > 0 && (layoutSize.getHeight() > limit || layoutSize.getWidth() > limit)){
      JSONObject ext = new JSONObject();
      WXComponent component = WXSDKManager.getInstance().getWXRenderManager().getWXComponent(instanceId,ref);
      ext.put("GPU limit",String.valueOf(limit));
      ext.put("component.width",String.valueOf(layoutSize.getWidth()));
      ext.put("component.height",String.valueOf(layoutSize.getHeight()));
      if (component.getComponentType() != null && !component.getComponentType().isEmpty()) {
        ext.put("component.type", component.getComponentType());
      }
      if (component.getStyles() != null && !component.getStyles().isEmpty()) {
        ext.put("component.style", component.getStyles().toString());
      }
      if (component.getAttrs() != null && !component.getAttrs().isEmpty()) {
        ext.put("component.attr", component.getAttrs().toString());
      }
      if (component.getEvents() != null && !component.getEvents().isEmpty()) {
        ext.put("component.event", component.getEvents().toString());
      }
      if (component.getMargin() != null) {
        ext.put("component.margin", component.getMargin().toString());
      }
      if (component.getPadding() != null) {
        ext.put("component.padding", component.getPadding().toString());
      }
      if (component.getBorder() != null) {
        ext.put("component.border", component.getBorder().toString());
      }
      WXSDKManager.getInstance().getSDKInstance(instanceId).setComponentsInfoExceedGPULimit(ext);
    }
  }

  public int callAddChildToRichtext(String instanceId, String nodeType, String ref, String parentRef, String richTextRef,
                                    HashMap<String, String> styles, HashMap<String, String> attrs){
    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) {
      if (WXEnvironment.isApkDebugable()){
        WXLogUtils.d("[WXBridgeManager] call callAddChildToRichtext arguments is null");
      }

      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callAddChildToRichtext",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callAddChildToRichtext >>>> instanceId:").append(instanceId)
              .append(", nodeType:").append(nodeType).append(", ref:").append(ref).append(", parentRef:")
              .append(parentRef).append(", richTextRef:").append(richTextRef).append(", styles:")
              .append(styles.toString()).append(", attrs:").append(attrs.toString());
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }
    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        final BasicGraphicAction action = new GraphicActionAddChildToRichtext(instance,nodeType,ref,parentRef,richTextRef,styles,attrs
        );
        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callAddChildToRichtext exception: ", WXLogUtils.getStackTrace(e));
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callAddChildToRichtext",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callRemoveChildFromRichtext(String instanceId, String ref, String parentRef, String richTextRef){
    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) {
      if (WXEnvironment.isApkDebugable()){
        WXLogUtils.d("[WXBridgeManager] call callRemoveChildFromRichtext arguments is null");
      }

      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callRemoveChildFromRichtext",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callRemoveChildFromRichtext >>>> instanceId:").append(instanceId)
              .append(", ref:").append(ref).append(", parentRef:").append(parentRef).append(", richTextRef:").append(richTextRef);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }
    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        final BasicGraphicAction action = new GraphicActionRemoveChildFromRichtext(instance, ref, parentRef, richTextRef);
        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callRemoveChildFromRichtext exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callRemoveChildFromRichtext",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callUpdateRichtextStyle(String instanceId, String ref, HashMap<String, String> styles, String parentRef, String richTextRef){
    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) {
      if (WXEnvironment.isApkDebugable()){
        WXLogUtils.d("[WXBridgeManager] call callUpdateRichtextStyle arguments is null");
      }

      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callUpdateRichtextStyle",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callUpdateRichtextStyle >>>> instanceId:").append(instanceId)
              .append(", ref:").append(ref).append(", styles:").append(styles.toString()).append(", parentRef:")
              .append(parentRef).append(", richTextRef:").append(richTextRef);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }
    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        final BasicGraphicAction action = new GraphicActionUpdateRichtextStyle(instance, ref, styles, parentRef, richTextRef);
        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callUpdateRichtextStyle exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callUpdateRichtextStyle",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }
  public int callUpdateRichtextChildAttr(String instanceId, String ref, HashMap<String, String> attrs, String parentRef, String richTextRef){
    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) {
      if (WXEnvironment.isApkDebugable()){
        WXLogUtils.d("[WXBridgeManager] call callUpdateRichtextChildAttr arguments is null");
      }

      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callUpdateRichtextChildAttr",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callUpdateRichtextChildAttr >>>> instanceId:").append(instanceId)
              .append(", ref:").append(ref).append(", attrs:").append(attrs.toString()).append(", parentRef:")
              .append(parentRef).append(", richTextRef:").append(richTextRef);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }
    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        final BasicGraphicAction action = new GraphicActionUpdateRichtextAttr(instance, ref, attrs, parentRef, richTextRef);
        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callUpdateRichtextChildAttr exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callUpdateRichtextChildAttr",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callLayout(String pageId, String ref, int top, int bottom, int left, int right, int height, int width, boolean isRTL, int index) {

    if (TextUtils.isEmpty(pageId) || TextUtils.isEmpty(ref)) {
        if (WXEnvironment.isApkDebugable()){
            WXLogUtils.d("[WXBridgeManager] call callLayout arguments is null");
        }

      WXExceptionUtils.commitCriticalExceptionRT(pageId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callLayout",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callLayout >>>> instanceId:").append(pageId)
            .append(", ref:").append(ref).append(", height:").append(height).append(", width:").append(width)
              .append(", top:").append(top)
              .append(", bottom:").append(bottom)
              .append(", left:").append(left)
              .append(", right:").append(right);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(pageId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(pageId);
      if (instance != null) {
        GraphicSize size = new GraphicSize(width, height);
        GraphicPosition position = new GraphicPosition(left, top, right, bottom);
        setExceedGPULimitComponentsInfo(pageId,ref,size);
        GraphicActionAddElement addAction = instance.getInActiveAddElementAction(ref);
        if(addAction!=null) {
          addAction.setRTL(isRTL);
          addAction.setSize(size);
          addAction.setPosition(position);
          if(!TextUtils.equals(ref, WXComponent.ROOT)) {
            addAction.setIndex(index);
          }
          WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(pageId, addAction);
          instance.removeInActiveAddElmentAction(ref);
        }
        else {
          final BasicGraphicAction action = new GraphicActionLayout(instance, ref, position, size, isRTL);
          WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
        }
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callLayout exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(pageId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callLayout",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callAppendTreeCreateFinish(String instanceId, String ref) {

    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) {
      WXLogUtils.d("[WXBridgeManager] call callAppendTreeCreateFinish arguments is null");
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callAppendTreeCreateFinish",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callAppendTreeCreateFinish >>>> instanceId:").append(instanceId)
              .append(", ref:").append(ref);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      GraphicActionAppendTreeCreateFinish action = new GraphicActionAppendTreeCreateFinish(instance, ref);
      WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(instanceId, action);
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callAppendTreeCreateFinish exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callAppendTreeCreateFinish",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callCreateFinish(String instanceId) {

    if (TextUtils.isEmpty(instanceId)) {
      WXLogUtils.d("[WXBridgeManager] call callCreateFinish arguments is null");
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callCreateFinish",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callCreateFinish >>>> instanceId:").append(instanceId);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      long start = System.currentTimeMillis();
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        instance.getApmForInstance().onStage("callCreateFinish");
        instance.firstScreenCreateInstanceTime(start);
        GraphicActionCreateFinish action = new GraphicActionCreateFinish(instance);
        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(instanceId, action);
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callCreateFinish exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callCreateFinish",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  public int callRenderSuccess(String instanceId) {

    if (TextUtils.isEmpty(instanceId)) {
      WXLogUtils.d("[WXBridgeManager] call callRenderSuccess arguments is null");
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callRenderSuccess",
              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
      return IWXBridge.INSTANCE_RENDERING_ERROR;
    }

    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
      mLodBuilder.append("[WXBridgeManager] callRenderSuccess >>>> instanceId:").append(instanceId);
      WXLogUtils.d(mLodBuilder.substring(0));
      mLodBuilder.setLength(0);
    }

    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    try {
      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
      if (instance != null) {
        instance.getApmForInstance().onStage("callRenderSuccess");
        GraphicActionRenderSuccess action = new GraphicActionRenderSuccess(instance);
        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(instanceId, action);
      }
    } catch (Exception e) {
      WXLogUtils.e("[WXBridgeManager] callRenderSuccess exception: ", e);
      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callRenderSuccess",
              WXLogUtils.getStackTrace(e), null);
    }

    return IWXBridge.INSTANCE_RENDERING;
  }

  public ContentBoxMeasurement getMeasurementFunc(String instanceId, long renderObjectPtr) {
    ContentBoxMeasurement contentBoxMeasurement = null;
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if (instance != null) {
      contentBoxMeasurement = instance.getContentBoxMeasurement(renderObjectPtr);
    }
    return contentBoxMeasurement;
  }

  public void bindMeasurementToRenderObject(long ptr){
    if (isJSFrameworkInit()) {
      mWXBridge.bindMeasurementToRenderObject(ptr);
    }
  }


  /**
   * Native: Layout
   * @param instanceId
   * @return
   */
  @UiThread
  public boolean notifyLayout(String instanceId) {
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      return mWXBridge.notifyLayout(instanceId);
    }
    return false;
  }

  @UiThread
  public void forceLayout(String instanceId) {
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.forceLayout(instanceId);
    }
  }

  /**
   * native: OnInstanceClose
   * should be called on JSThread
   * @param instanceId
   */
  public void onInstanceClose(String instanceId) {
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.onInstanceClose(instanceId);
    }
  }

  /**
   * native: SetDefaultHeightAndWidthIntoRootDom
   * @param instanceId
   * @param defaultWidth
   * @param defaultHeight
   */
  public void setDefaultRootSize(final String instanceId, final float defaultWidth, final float defaultHeight, final boolean isWidthWrapContent, final boolean isHeightWrapContent) {
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.setDefaultHeightAndWidthIntoRootDom(instanceId, defaultWidth, defaultHeight, isWidthWrapContent, isHeightWrapContent);
    }
  }

  public void setRenderContentWrapContentToCore(boolean wrap, final String instanceId) {
    if (isJSFrameworkInit()) {
      mWXBridge.setRenderContainerWrapContent(wrap, instanceId);
    }
  }

  public void setStyleWidth(String instanceId, String ref, float value) {
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.setStyleWidth(instanceId, ref, value);
    }
  }

  public void setStyleHeight(String instanceId, String ref, float value) {
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.setStyleHeight(instanceId, ref, value);
    }
  }

  public long[] getFirstScreenRenderTime(String instanceId) {
    if (isJSFrameworkInit()) {
      return mWXBridge.getFirstScreenRenderTime(instanceId);
    }
    return new long[]{0, 0, 0};
  }

  public long[] getRenderFinishTime(String instanceId) {
    if (isJSFrameworkInit()) {
      return mWXBridge.getRenderFinishTime(instanceId);
    }
    return new long[]{0, 0, 0};
  }

  public void setDeviceDisplay(final String instanceId, final float deviceWidth, final float deviceHeight, final float scale) {
    post(new Runnable() {
      @Override
      public void run() {
        mWXBridge.setDeviceDisplay(instanceId, deviceWidth, deviceHeight, scale);
      }
    });
  }

  public void updateInitDeviceParams(final String width, final String height, final String density, final String statusHeight){
    if(!isJSFrameworkInit()){
      return;
    }
    post(new Runnable() {
      @Override
      public void run() {
        mWXBridge.updateInitFrameworkParams(WXConfig.deviceWidth, width, WXConfig.deviceWidth);
      }
    });
    post(new Runnable() {
      @Override
      public void run() {
        mWXBridge.updateInitFrameworkParams(WXConfig.deviceHeight, height, WXConfig.deviceHeight);
      }
    });

    post(new Runnable() {
      @Override
      public void run() {
        mWXBridge.updateInitFrameworkParams(WXConfig.scale,  density, WXConfig.scale);
      }
    });

    if(statusHeight != null){
      post(new Runnable() {
        @Override
        public void run() {
          mWXBridge.updateInitFrameworkParams(WXConfig.androidStatusBarHeight,  statusHeight, WXConfig.androidStatusBarHeight);
        }
      });
    }
  }

  public void setMargin(String instanceId, String ref, CSSShorthand.EDGE edge, float value) {
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.setMargin(instanceId, ref, edge, value);
    }
  }

  public void setPadding(String instanceId, String ref, CSSShorthand.EDGE edge, float value) {
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.setPadding(instanceId, ref, edge, value);
    }
  }

  public void setPosition(String instanceId, String ref, CSSShorthand.EDGE edge, float value) {
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.setPosition(instanceId, ref, edge, value);
    }
  }

  public void markDirty(String instanceId, String ref, boolean dirty) {
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.markDirty(instanceId, ref, dirty);
    }
  }
  public void setViewPortWidth(String instanceId,float viewPortWidth){
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.setViewPortWidth(instanceId,viewPortWidth);
    }
  }
  public void setPageArgument(String instanceId,String key,String value){
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.setPageArgument(instanceId,key,value);
    }
  }
  public void reloadPageLayout(String instanceId){
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.reloadPageLayout(instanceId);
    }
  }

  public void setDeviceDisplayOfPage(String instanceId,float width,float height){
    if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
      mWXBridge.setDeviceDisplayOfPage(instanceId,width,height);
    }
  }

  public int callHasTransitionPros(String instanceId, String ref, HashMap<String, String> styles) {
    WXComponent component = WXSDKManager.getInstance().getWXRenderManager().getWXComponent(instanceId, ref);
    if (null == component || null == component.getTransition() || null == component.getTransition().getProperties()) {
      return IWXBridge.DESTROY_INSTANCE;
    }

    for(String property : component.getTransition().getProperties()){
      if(styles.containsKey(property)){
        return IWXBridge.INSTANCE_RENDERING;
      }
    }
    return IWXBridge.INSTANCE_RENDERING_ERROR;
  }

  public void registerCoreEnv(String key, String value) {
    if (isJSFrameworkInit())
      mWXBridge.registerCoreEnv(key, value);
    else
      mWeexCoreEnvOptions.put(key, value);
  }

  private void onJsFrameWorkInitSuccees() {
    for (Map.Entry<String, String> entry : mWeexCoreEnvOptions.entrySet()) {
      mWXBridge.registerCoreEnv(entry.getKey(), entry.getValue());
    }
    mWeexCoreEnvOptions.clear();
  }

  public  String getWeexCoreThreadStackTrace(){
    if (null == mJSThread){
      return "null == mJSThread";
    }
    StringBuilder stringBuilder = new StringBuilder();

    try {
      stringBuilder.append(String.format("Thread Name: '%s'\n", mJSThread.getName()));
      stringBuilder.append(String.format(Locale.ENGLISH,"\"%s\" prio=%d tid=%d %s\n", mJSThread.getName(), mJSThread.getPriority(), mJSThread.getId(), mJSThread.getState()));

      for (StackTraceElement e: mJSThread.getStackTrace()){
        stringBuilder.append(String.format("\tat %s\n", e.toString()));
      }
    } catch (Exception var8) {
      Log.e("weex", "getJSThreadStackTrace error:", var8);
    }
    return stringBuilder.toString();
  }

}
