blob: 801f84fab2e4724b399d5071526c75bdbea46986 [file] [log] [blame]
/*
* 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();
}
}