Repository: incubator-weex
Updated Branches:
  refs/heads/master edb442697 -> aad360553


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/common/WXPerformance.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/common/WXPerformance.java 
b/android/sdk/src/main/java/com/taobao/weex/common/WXPerformance.java
index 8238041..8af7d85 100644
--- a/android/sdk/src/main/java/com/taobao/weex/common/WXPerformance.java
+++ b/android/sdk/src/main/java/com/taobao/weex/common/WXPerformance.java
@@ -18,25 +18,188 @@
  */
 package com.taobao.weex.common;
 
+import android.os.Debug;
+import android.support.annotation.RestrictTo;
+import android.support.annotation.RestrictTo.Scope;
+import android.text.TextUtils;
+
 import com.taobao.weex.WXEnvironment;
+import com.taobao.weex.performance.FpsCollector;
+import com.taobao.weex.performance.MemUtils;
+import com.taobao.weex.utils.WXViewUtils;
 
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 
 public class WXPerformance {
 
+  @RestrictTo(Scope.LIBRARY)
+  public enum Dimension {
+    JSLibVersion,
+    WXSDKVersion,
+    pageName,
+    spm,
+    scheme,
+    cacheType,
+    requestType,
+    networkType,
+    connectionType,
+    zcacheInfo,
+    wxdim1,
+    wxdim2,
+    wxdim3,
+    wxdim4,
+    wxdim5,
+    bizType,
+    templateUrl,
+    useScroller
+  }
+
+  public enum Measure {
+    /**
+     * range : [min,max)
+     */
+    JSLibSize(0D, Double.MAX_VALUE),
+    //normal 300ms.. first install apk 30s ?
+    JSLibInitTime(0D, 50000D),
+    SDKInitTime(0D, 5000D),
+    SDKInitInvokeTime(0D, 5000D),
+    SDKInitExecuteTime(0D, 5000D),
+    JSTemplateSize(0D, 5000D),
+    pureNetworkTime(0D, 15000D),
+    networkTime(0D, 15000D),
+    fsCreateInstanceTime(0D, 3000D),
+    fsCallJsTotalTime(0D, 5000D),
+    fsCallJsTotalNum(0D, Double.MAX_VALUE),
+    fsCallNativeTotalTime(0D, 5000D),
+    fsCallNativeTotalNum(0D, Double.MAX_VALUE),
+    fsCallEventTotalNum(0D, Double.MAX_VALUE),
+    fsRenderTime(0D, 5000D),
+    fsRequestNum(0D, 100D),
+    callCreateFinishTime(0D, 10000D),
+    cellExceedNum(0D, Double.MAX_VALUE),
+    communicateTotalTime(0D, 5000D),
+    maxDeepViewLayer(0D, Double.MAX_VALUE),
+    maxDeepVDomLayer(0D, Double.MAX_VALUE),
+    componentCount(0D, Double.MAX_VALUE),
+    avgFps(0D, 61D),
+    timerCount(0D, Double.MAX_VALUE),
+
+    MaxImproveMemory(0D, Double.MAX_VALUE),
+    BackImproveMemory(0D, Double.MAX_VALUE),
+    PushImproveMemory(0D, Double.MAX_VALUE),
+    measureTime1(0D, Double.MAX_VALUE),
+    measureTime2(0D, Double.MAX_VALUE),
+    measureTime3(0D, Double.MAX_VALUE),
+    measureTime4(0D, Double.MAX_VALUE),
+    measureTime5(0D, Double.MAX_VALUE),
+
+    communicateTime(0D, 5000D),
+    screenRenderTime(0D, 5000D),
+    totalTime(0D, 5000D),
+    localReadTime(0D, 5000D),
+    templateLoadTime(0D, 5000D),
+    packageSpendTime(0D, 5000D),
+    syncTaskTime(0D, 5000D),
+    actualNetworkTime(0D, 5000D),
+    firstScreenJSFExecuteTime(0D, 5000D),
+    //..
+
+    fluency(0D, 101D),
+    imgSizeCount(0D, 2000D),
+    interactionTime(0D,10000D);
+
+
+    private double mMinRange, mMaxRange;
+
+    Measure(double min, double max) {
+      this.mMinRange = min;
+      this.mMaxRange = max;
+    }
+
+    public double getMinRange() {
+      return mMinRange;
+    }
+
+    public double getMaxRange() {
+      return mMaxRange;
+    }
+  }
+
   public static final String DEFAULT = "default";
 
+  @RestrictTo(Scope.LIBRARY_GROUP)
+  public static final String CACHE_TYPE = "cacheType";
+
+  public static final int VIEW_LIMIT_HEIGHT = WXViewUtils.getScreenHeight() / 
2;
+  public static final int VIEW_LIMIT_WIDTH = WXViewUtils.getScreenWidth() / 2;
+  public static boolean TRACE_DATA = WXEnvironment.isApkDebugable();
+
   /**
-   * Business unit, mandatory. If no business unit can be provided, set the 
field as default
+   * No longer needed.
    */
+  @Deprecated
   public String bizType = "weex";
 
   /**
-   * URL used for rendering view, optional
+   * Use {@link #pageName} instead.
    */
+  @Deprecated
   public String templateUrl;
 
+  @RestrictTo(Scope.LIBRARY_GROUP)
+  public String cacheType = "unknown";
+
+  @RestrictTo(Scope.LIBRARY)
+  public long renderTimeOrigin;
+
+  public long fsRenderTime;
+
+  public long callCreateFinishTime;
+
+  public long interactionTime;
+
+  /**
+   * Time used for
+   * {@link com.taobao.weex.bridge.WXBridgeManager#createInstance(String, 
String, Map, String)}
+   */
+  @RestrictTo(Scope.LIBRARY)
+  public long callCreateInstanceTime;
+
+
+  public long fsCallJsTotalTime;
+
+  public int fsCallJsTotalNum;
+
+  public long fsCallNativeTotalTime;
+
+  public int fsCallNativeTotalNum;
+
+  public int fsRequestNum;
+
+  public int cellExceedNum;
+
+  public int timerInvokeCount;
+
+  public int fsCallEventTotalNum;
+
+  public long avgFPS;
+  public long frameSum;
+  public long frameStartTime;
+  public long frameEndTime;
+  public double fluency = 100D;
+
+  public long maxImproveMemory;
+
+  public long backImproveMemory;
+
+  public long pushImproveMemory;
+
+  public long memTotalBeforeRender;
+
+
   /**
    * Time spent for reading, time unit is ms.
    */
@@ -65,9 +228,9 @@ public class WXPerformance {
   public long templateLoadTime;
 
   /**
-   * Time used for
-   * {@link com.taobao.weex.bridge.WXBridgeManager#createInstance(String, 
String, Map, String)}
+   * Use {@link #callCreateInstanceTime} instead.
    */
+  @Deprecated
   public long communicateTime;
 
   /**
@@ -96,18 +259,18 @@ public class WXPerformance {
   public long parseJsonTime;
 
   /**
-   *  UpdateDomObj Time spent when rendering first screen
+   * UpdateDomObj Time spent when rendering first screen
    */
   public long updateDomObjTime;
 
   /**
-   *  ApplyUpdate Time spent when rendering first screen
+   * ApplyUpdate Time spent when rendering first screen
    */
   public long applyUpdateTime;
 
 
   /**
-   *  CssLayout Time spent when rendering first screen
+   * CssLayout Time spent when rendering first screen
    */
   public long cssLayoutTime;
 
@@ -133,11 +296,16 @@ public class WXPerformance {
    * view hierarchy
    */
   public int maxDeepViewLayer;
+
+  public int maxDeepVDomLayer;
+
+  public double wrongImgSizeCount;
+
   /**
    * 1:true
    * 0:false
    */
-  public int useScroller=0;
+  public int useScroller = 0;
 
   /**
    * component Count
@@ -171,101 +339,144 @@ public class WXPerformance {
   public String errMsg;
   private StringBuilder mErrMsgBuilder;
 
-  public String args="";
+  public String args = "";
 
   public String connectionType;
   public String requestType;
 
+  public String zCacheInfo;
+
   /**
    *for network tracker
    */
 
-  public String wxDims[] = new String [5];
-  public long measureTimes[] = new long [5];
+  /**
+   * TODO These dimensions will be moved to elsewhere
+   */
+  @RestrictTo(Scope.LIBRARY)
+  @Deprecated
+  public String wxDims[] = new String[5];
 
-  public WXPerformance(){
-    mErrMsgBuilder=new StringBuilder();
+  /**
+   * TODO These dimensions will be moved to elsewhere
+   */
+  @RestrictTo(Scope.LIBRARY)
+  @Deprecated
+  public long measureTimes[] = new long[5];
+
+  public WXPerformance() {
+    mErrMsgBuilder = new StringBuilder();
   }
 
-  public Map<String,Double> getMeasureMap(){
-    Map<String,Double> quotas = new HashMap<>();
-    quotas.put("JSTemplateSize", JSTemplateSize);
-    quotas.put("JSLibSize", JSLibSize);
-    quotas.put("communicateTime", (double)communicateTime);
-    quotas.put("screenRenderTime", (double)screenRenderTime);
-    quotas.put("totalTime", totalTime);
-    quotas.put("localReadTime", localReadTime);
-    quotas.put("JSLibInitTime", (double)JSLibInitTime);
-    quotas.put("networkTime", (double)networkTime);
-    quotas.put("templateLoadTime", (double)templateLoadTime);
-    quotas.put("SDKInitInvokeTime",(double)WXEnvironment.sSDKInitInvokeTime);
-    quotas.put("SDKInitExecuteTime",(double)WXEnvironment.sSDKInitExecuteTime);
-    quotas.put("firstScreenJSFExecuteTime",(double) firstScreenJSFExecuteTime);
-    quotas.put("componentCount",(double)componentCount);
-    quotas.put("actualNetworkTime",(double)actualNetworkTime);
-    quotas.put("pureNetworkTime",(double)pureNetworkTime);
-    quotas.put("syncTaskTime",(double)syncTaskTime);
-    quotas.put("packageSpendTime",(double)packageSpendTime);
-    quotas.put("SDKInitTime",(double)WXEnvironment.sSDKInitTime);
-    quotas.put("maxDeepViewLayer", (double) maxDeepViewLayer);
-    quotas.put("useScroller", (double) useScroller);
-       quotas.put("measureTime1", (double) measureTimes[0]);
-       quotas.put("measureTime2", (double) measureTimes[1]);
-       quotas.put("measureTime3", (double) measureTimes[2]);
-       quotas.put("measureTime4", (double) measureTimes[3]);
-       quotas.put("measureTime5", (double) measureTimes[4]);
-       return quotas;
+  public static void init() {
+    if (WXPerformance.TRACE_DATA) {
+      FpsCollector.getInstance().init();
+    }
   }
 
-  public Map<String,String> getDimensionMap(){
-    Map<String,String> quotas = new HashMap<>();
-    quotas.put("bizType", bizType);
-    quotas.put("templateUrl", templateUrl);
-    quotas.put("pageName", pageName);
-    quotas.put("JSLibVersion", JSLibVersion);
-    quotas.put("WXSDKVersion", WXSDKVersion);
-    quotas.put("connectionType",connectionType);
-    quotas.put("requestType",requestType);
-       quotas.put("wxdim1", wxDims[0]);
-       quotas.put("wxdim2", wxDims[1]);
-       quotas.put("wxdim3", wxDims[2]);
-       quotas.put("wxdim4", wxDims[3]);
-       quotas.put("wxdim5", wxDims[4]);
-       return quotas;
+  public Map<String, Double> getMeasureMap() {
+    double fsRenderTime;
+    if (this.fsRenderTime != 0) {
+      fsRenderTime = this.fsRenderTime - renderTimeOrigin;
+    } else {
+      if (totalTime != 0) {
+        fsRenderTime = totalTime;
+      } else {
+        fsRenderTime = -1;
+      }
+    }
+    Map<String, Double> quotas = new HashMap<>();
+    quotas.put(Measure.JSLibSize.toString(), JSLibSize);
+    quotas.put(Measure.JSLibInitTime.toString(), (double) JSLibInitTime);
+    quotas.put(Measure.SDKInitTime.toString(), (double) 
WXEnvironment.sSDKInitTime);
+    quotas.put(Measure.SDKInitInvokeTime.toString(), (double) 
WXEnvironment.sSDKInitInvokeTime);
+    quotas.put(Measure.SDKInitExecuteTime.toString(), (double) 
WXEnvironment.sSDKInitExecuteTime);
+    quotas.put(Measure.JSTemplateSize.toString(), JSTemplateSize);
+    quotas.put(Measure.pureNetworkTime.toString(), (double) pureNetworkTime);
+    quotas.put(Measure.networkTime.toString(), (double) networkTime);
+    quotas.put(Measure.fsCreateInstanceTime.toString(), (double) 
(callCreateInstanceTime - renderTimeOrigin));
+    quotas.put(Measure.fsCallJsTotalTime.toString(), (double) 
fsCallJsTotalTime);
+    quotas.put(Measure.fsCallJsTotalNum.toString(), (double) fsCallJsTotalNum);
+    quotas.put(Measure.fsCallNativeTotalTime.toString(), (double) 
fsCallNativeTotalTime);
+    quotas.put(Measure.fsCallNativeTotalNum.toString(), (double) 
fsCallNativeTotalNum);
+    quotas.put(Measure.fsRenderTime.toString(), fsRenderTime);
+    quotas.put(Measure.fsRequestNum.toString(), (double) fsRequestNum);
+    quotas.put(Measure.communicateTotalTime.toString(), totalTime);
+    quotas.put(Measure.maxDeepViewLayer.toString(), (double) maxDeepViewLayer);
+    quotas.put(Measure.maxDeepVDomLayer.toString(), (double) maxDeepVDomLayer);
+    quotas.put(Measure.componentCount.toString(), (double) componentCount);
+    quotas.put(Measure.cellExceedNum.toString(), (double) cellExceedNum);
+    quotas.put(Measure.timerCount.toString(), (double) timerInvokeCount);
+    quotas.put(Measure.avgFps.toString(), (double) avgFPS);
+    quotas.put(Measure.fluency.toString(), fluency);
+    quotas.put(Measure.MaxImproveMemory.toString(), 0D);
+    quotas.put(Measure.BackImproveMemory.toString(), (double) 
backImproveMemory);
+    quotas.put(Measure.PushImproveMemory.toString(), 0D);
+
+    quotas.put(Measure.fsCallEventTotalNum.toString(), (double) 
fsCallEventTotalNum);
+    quotas.put(Measure.callCreateFinishTime.toString(), (double) 
callCreateFinishTime);
+    quotas.put(Measure.imgSizeCount.toString(), wrongImgSizeCount);
+    quotas.put(Measure.interactionTime.toString(), (double) interactionTime);
+
+    // TODO the following attribute is no longer needed and will be deleted 
soon.
+    quotas.put(Measure.screenRenderTime.toString(), (double) screenRenderTime);
+    quotas.put(Measure.communicateTime.toString(), (double) communicateTime);
+    quotas.put(Measure.localReadTime.toString(), localReadTime);
+    quotas.put(Measure.templateLoadTime.toString(), (double) templateLoadTime);
+    quotas.put(Measure.firstScreenJSFExecuteTime.toString(), (double) 
firstScreenJSFExecuteTime);
+    quotas.put(Measure.actualNetworkTime.toString(), (double) 
actualNetworkTime);
+    quotas.put(Measure.syncTaskTime.toString(), (double) syncTaskTime);
+    quotas.put(Measure.packageSpendTime.toString(), (double) packageSpendTime);
+
+    // TODO These attribute will be moved to elsewhere
+    quotas.put(Measure.measureTime1.toString(), (double) measureTimes[0]);
+    quotas.put(Measure.measureTime2.toString(), (double) measureTimes[1]);
+    quotas.put(Measure.measureTime3.toString(), (double) measureTimes[2]);
+    quotas.put(Measure.measureTime4.toString(), (double) measureTimes[3]);
+    quotas.put(Measure.measureTime5.toString(), (double) measureTimes[4]);
+    return quotas;
   }
 
-  public static String[] getDimensions(){
-    return new 
String[]{"bizType","templateUrl","pageName","JSLibVersion","WXSDKVersion","connectionType","requestType"
-    ,"wxdim1","wxdim2","wxdim3","wxdim4","wxdim5"};
+  public Map<String, String> getDimensionMap() {
+    Map<String, String> quotas = new HashMap<>();
+    quotas.put(Dimension.JSLibVersion.toString(), JSLibVersion);
+    quotas.put(Dimension.WXSDKVersion.toString(), WXSDKVersion);
+    quotas.put(Dimension.pageName.toString(), pageName);
+    quotas.put(Dimension.requestType.toString(), requestType);
+    quotas.put(Dimension.networkType.toString(), "unknown");
+    quotas.put(Dimension.connectionType.toString(), connectionType);
+    quotas.put(Dimension.zcacheInfo.toString(), zCacheInfo);
+    quotas.put(Dimension.cacheType.toString(), cacheType);
+    quotas.put(Dimension.useScroller.toString(), String.valueOf(useScroller));
+
+    // TODO These attribute will be moved to elsewhere
+    // Extra Dimension for 3rd developers.
+    quotas.put(Dimension.wxdim1.toString(), wxDims[0]);
+    quotas.put(Dimension.wxdim2.toString(), wxDims[1]);
+    quotas.put(Dimension.wxdim3.toString(), wxDims[2]);
+    quotas.put(Dimension.wxdim4.toString(), wxDims[3]);
+    quotas.put(Dimension.wxdim5.toString(), wxDims[4]);
+
+    // TODO the following attribute is no longer needed and will be deleted 
soon.
+    quotas.put(Dimension.bizType.toString(), bizType);
+    quotas.put(Dimension.templateUrl.toString(), templateUrl);
+    return quotas;
   }
 
-  public static String[] getMeasures(){
-    return new String[]{"JSTemplateSize",
-        "JSLibSize",
-        "communicateTime",
-        "screenRenderTime",
-        "totalTime",
-        "localReadTime",
-        "JSLibInitTime",
-        "networkTime",
-        "componentCount",
-        "templateLoadTime",
-        "SDKInitInvokeTime",
-        "SDKInitExecuteTime",
-        "SDKInitTime",
-        "packageSpendTime",
-        "syncTaskTime",
-        "pureNetworkTime",
-        "actualNetworkTime",
-        "firstScreenJSFExecuteTime",
-        "maxDeepViewLayer",
-        "useScroller",
-               "measureTime1",
-               "measureTime2",
-               "measureTime3",
-               "measureTime4",
-               "measureTime5"
-       };
+  public static String[] getDimensions() {
+    List<String> ret = new LinkedList<>();
+    for (Dimension dimension : Dimension.values()) {
+      ret.add(dimension.toString());
+    }
+    return ret.toArray(new String[ret.size()]);
+  }
+
+  public static String[] getMeasures() {
+    List<String> ret = new LinkedList<>();
+    for (Measure measure : Measure.values()) {
+      ret.add(measure.toString());
+    }
+    return ret.toArray(new String[ret.size()]);
   }
 
   @Override
@@ -285,8 +496,8 @@ public class WXPerformance {
              + ",packageSpendTime:" + packageSpendTime
              + ",connectionType:" + connectionType
              + ",requestType:" + requestType
-             + 
",initInvokeTime:"+WXEnvironment.sSDKInitInvokeTime+",initExecuteTime:"+WXEnvironment.sSDKInitExecuteTime
-             + ",SDKInitTime:"+ WXEnvironment.sSDKInitTime
+             + ",initInvokeTime:" + WXEnvironment.sSDKInitInvokeTime + 
",initExecuteTime:" + WXEnvironment.sSDKInitExecuteTime
+             + ",SDKInitTime:" + WXEnvironment.sSDKInitTime
              + ",totalTime:" + totalTime + ",JSLibVersion:" + JSLibVersion + 
",WXSDKVersion:" + WXSDKVersion
              + ",errCode:" + errCode + ",renderFailedDetail:" + 
renderFailedDetail
              + ",arg:" + args
@@ -294,21 +505,22 @@ public class WXPerformance {
     }
     return super.toString();
   }
-  public String getPerfData(){
-      return  "networkTime:" + networkTime
-              + " actualNetworkTime:" + actualNetworkTime
-              + " connectionType:" + connectionType
-              + " requestType:" + requestType
-              + " firstScreenRenderTime:" + screenRenderTime
-              + " firstScreenJSFExecuteTime:" + firstScreenJSFExecuteTime
-              + " componentCount:" + componentCount
-              + " JSTemplateSize:" + JSTemplateSize
-              + " SDKInitTime:" + WXEnvironment.sSDKInitTime
-              + " totalTime:" + totalTime
-              + " JSLibVersion:" + JSLibVersion
-              + " WXSDKVersion:" + WXSDKVersion
-              + " pageName:" + pageName
-              + " useScroller:" + useScroller;
+
+  public String getPerfData() {
+    return "networkTime:" + networkTime
+           + " actualNetworkTime:" + actualNetworkTime
+           + " connectionType:" + connectionType
+           + " requestType:" + requestType
+           + " firstScreenRenderTime:" + screenRenderTime
+           + " firstScreenJSFExecuteTime:" + firstScreenJSFExecuteTime
+           + " componentCount:" + componentCount
+           + " JSTemplateSize:" + JSTemplateSize
+           + " SDKInitTime:" + WXEnvironment.sSDKInitTime
+           + " totalTime:" + totalTime
+           + " JSLibVersion:" + JSLibVersion
+           + " WXSDKVersion:" + WXSDKVersion
+           + " pageName:" + pageName
+           + " useScroller:" + useScroller;
 
   }
 
@@ -319,4 +531,65 @@ public class WXPerformance {
   public void appendErrMsg(CharSequence msg) {
     mErrMsgBuilder.append(msg);
   }
-}
+
+
+  private FpsRecorder mFpsRecorder = new FpsRecorder();
+
+  public void beforeInstanceRender(String instanceId) {
+    renderTimeOrigin = System.currentTimeMillis();
+    if (WXPerformance.TRACE_DATA) {
+      if (TextUtils.isEmpty(instanceId)) {
+        return;
+      }
+      Debug.MemoryInfo mem = 
MemUtils.getMemoryInfo(WXEnvironment.getApplication());
+      if (null != mem) {
+        memTotalBeforeRender = mem.getTotalPss();
+      }
+      FpsCollector.getInstance().registerListener(instanceId, mFpsRecorder);
+    }
+  }
+
+  //  public void onInstanceEndRender(String instanceId,boolean isFirstScreen){
+  //
+  //  }
+
+
+  public void afterInstanceDestroy(String instanceId) {
+    if (WXPerformance.TRACE_DATA) {
+      if (TextUtils.isEmpty(instanceId)) {
+        return;
+      }
+      FpsCollector.getInstance().unRegister(instanceId);
+      Debug.MemoryInfo mem = 
MemUtils.getMemoryInfo(WXEnvironment.getApplication());
+      if (null != mem) {
+        backImproveMemory = mem.getTotalPss() - memTotalBeforeRender;
+      }
+      if (mFpsRecorder.totalFpsCount > 0) {
+        avgFPS = mFpsRecorder.totalFpsCount / mFpsRecorder.totalFpsCount;
+        fluency = (double) mFpsRecorder.fluncyFpsPointCount / (double) 
mFpsRecorder.totalFpsCount;
+      }
+    }
+  }
+
+  private class FpsRecorder implements FpsCollector.IFPSCallBack {
+
+    private final long FLUENCY_FPS_LIMIT = 35;
+
+    private long totalFpsFrame;
+    private long totalFpsCount;
+    private long fluncyFpsPointCount;
+    private final long LIMIT_LONG = Long.MAX_VALUE - 1000;
+
+    @Override
+    public void fps(int fps) {
+      if (totalFpsFrame >= LIMIT_LONG || totalFpsCount >= Long.MAX_VALUE) {
+        return;
+      }
+      totalFpsFrame += fps;
+      totalFpsCount++;
+      if (fps >= FLUENCY_FPS_LIMIT) {
+        fluncyFpsPointCount++;
+      }
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/dom/WXDomManager.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomManager.java 
b/android/sdk/src/main/java/com/taobao/weex/dom/WXDomManager.java
index 5bc24ae..af00be9 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomManager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXDomManager.java
@@ -170,7 +170,7 @@ public final class WXDomManager {
                  WXLogUtils.e("WXDomManager", className + " Is Invalid 
Action");
                  if(className.contains("CreateFinishAction")){
                        WXExceptionUtils.commitCriticalExceptionRT(instanceId,
-                                       
WXErrorCode.WX_KEY_EXCEPTION_DOM_ACTION_FIRST_ACTION.getErrorCode(),
+                                       
WXErrorCode.WX_KEY_EXCEPTION_DOM_ACTION_FIRST_ACTION,
                                        "executeAction",
                                        
WXErrorCode.WX_KEY_EXCEPTION_DOM_ACTION_FIRST_ACTION.getErrorMsg() + "|current 
action is" +className, null);
                        instance.setmIsCommitedDomAtionExp(true);

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java 
b/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java
index 5e8b5bb..7897d44 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXDomObject.java
@@ -115,10 +115,10 @@ public class WXDomObject extends CSSNode implements 
Cloneable,ImmutableDomObject
 
   private  boolean cloneThis = false;
 
-  public void traverseTree(Consumer...consumers){
+  public int traverseTree(Consumer...consumers){
     long startNanos = System.nanoTime();
     if (consumers == null) {
-      return;
+      return 0;
     }
 
     for (Consumer consumer:consumers){
@@ -127,11 +127,14 @@ public class WXDomObject extends CSSNode implements 
Cloneable,ImmutableDomObject
 
     int count = childCount();
     WXDomObject child;
+    int maxChildDep = 0;
     for (int i = 0; i < count; ++i) {
       child = getChild(i);
-      child.traverseTree(consumers);
+      int depNum = child.traverseTree(consumers);
+      maxChildDep= maxChildDep > depNum? maxChildDep:depNum;
     }
     mDomThreadNanos += (System.nanoTime() - startNanos);
+    return maxChildDep+1;
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/dom/action/AbstractAddElementAction.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/AbstractAddElementAction.java
 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/AbstractAddElementAction.java
index b6a27fb..08ca2e3 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/AbstractAddElementAction.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/AbstractAddElementAction.java
@@ -71,7 +71,7 @@ public abstract class AbstractAddElementAction extends 
TraceableAction implement
             parentC.addChild(createdComponent);
           }else{
             WXLogUtils.e("[generateComponentTree] " + getStatementName() + " 
create dom component failed name " + child.getType());
-            
WXExceptionUtils.commitCriticalExceptionRT(context.getInstanceId(), 
getErrorCode().getErrorCode(), "generateComponentTree", " create dom component 
failed name " + child.getType(), null);
+            
WXExceptionUtils.commitCriticalExceptionRT(context.getInstanceId(), 
getErrorCode(), "generateComponentTree", " create dom component failed name " + 
child.getType(), null);
           }
         }
       }
@@ -94,12 +94,11 @@ public abstract class AbstractAddElementAction extends 
TraceableAction implement
     if (instance == null) {
       return;
     }
-    String errCode = getErrorCode().getErrorCode();
        String errMsg  = getErrorMsg();
 
        if (dom == null) {
 //      instance.commitUTStab(IWXUserTrackAdapter.DOM_MODULE, errCode);
-         WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(), 
errCode, "addDomInternal", errMsg, null);
+         WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(), 
getErrorCode(), "addDomInternal", errMsg, null);
     }
 
     //only non-root has parent.
@@ -110,16 +109,21 @@ public abstract class AbstractAddElementAction extends 
TraceableAction implement
     if (domObject == null || context.getDomByRef(domObject.getRef()) != null) {
       WXLogUtils.e("[DOMActionContextImpl] " + getStatementName() + " 
error,DOM object is null or already registered!!");
 //      instance.commitUTStab(IWXUserTrackAdapter.DOM_MODULE, errCode);
-         WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(), 
errCode, "addDomInternal", errMsg, null);
+         WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(), 
getErrorCode(), "addDomInternal", errMsg, null);
          return;
     }
     appendDomToTree(context, domObject);
     Stopwatch.split("appendDomToTree");
 
-    domObject.traverseTree(
+    int maxDomDep = domObject.traverseTree(
         context.getAddDOMConsumer(),
         context.getApplyStyleConsumer()
     );
+
+    if (instance.getMaxDomDeep()< maxDomDep){
+      instance.setMaxDomDeep(maxDomDep);
+    }
+
     Stopwatch.split("traverseTree");
 
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/dom/action/AddElementAction.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/AddElementAction.java 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/AddElementAction.java
index 87f5d56..00bccce 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/action/AddElementAction.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/action/AddElementAction.java
@@ -150,5 +150,6 @@ final class AddElementAction extends 
AbstractAddElementAction {
       WXLogUtils.e("add component failed.", e);
          mErrMsg.append("add component 
failed.").append(WXLogUtils.getStackTrace(e));
     }
+    instance.onElementChange();
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/dom/action/AddEventAction.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/AddEventAction.java 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/AddEventAction.java
index 2e3b469..58ccf6a 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/action/AddEventAction.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/action/AddEventAction.java
@@ -69,7 +69,7 @@ class AddEventAction extends TraceableAction implements 
DOMAction, RenderAction
 
                if(!"_documentElement".equals(mRef)){//Rax framework
                  
WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(),
-                                 
WXErrorCode.WX_KEY_EXCEPTION_DOM_ADD_EVENT.getErrorCode(),
+                                 WXErrorCode.WX_KEY_EXCEPTION_DOM_ADD_EVENT,
                                  "addEvent",
                                  
WXErrorCode.WX_KEY_EXCEPTION_DOM_ADD_EVENT.getErrorMsg() + "| domObject is null 
|"
                                                  +sbErr.toString(),null);

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/dom/action/AnimationAction.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/AnimationAction.java 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/AnimationAction.java
index fa2246f..a0d689f 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/action/AnimationAction.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/action/AnimationAction.java
@@ -128,7 +128,7 @@ class AnimationAction implements DOMAction, RenderAction {
       }
     } catch (RuntimeException e) {
          
WXExceptionUtils.commitCriticalExceptionRT(context.getInstance().getInstanceId(),
-                         
WXErrorCode.WX_KEY_EXCEPTION_DOM_ANIMATION.getErrorCode(),
+                         WXErrorCode.WX_KEY_EXCEPTION_DOM_ANIMATION,
                          "animationAction",
                          
WXErrorCode.WX_KEY_EXCEPTION_DOM_ANIMATION.getErrorMsg() + 
WXLogUtils.getStackTrace(e),null);
       WXLogUtils.e(TAG, WXLogUtils.getStackTrace(e));
@@ -174,7 +174,7 @@ class AnimationAction implements DOMAction, RenderAction {
           }
         } catch (RuntimeException e) {
                  
WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(),
-                                 
WXErrorCode.WX_KEY_EXCEPTION_DOM_ANIMATION.getErrorCode(),
+                                 WXErrorCode.WX_KEY_EXCEPTION_DOM_ANIMATION,
                                  "animationAction",
                                  
WXErrorCode.WX_KEY_EXCEPTION_DOM_ANIMATION.getErrorMsg() + 
WXLogUtils.getStackTrace(e),null);
                  WXLogUtils.e(TAG, WXLogUtils.getStackTrace(e));        }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/dom/action/ModuleInvocationAction.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/ModuleInvocationAction.java
 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/ModuleInvocationAction.java
index 12c70ab..327f9a3 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/ModuleInvocationAction.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/ModuleInvocationAction.java
@@ -64,7 +64,7 @@ class ModuleInvocationAction implements DOMAction, 
RenderAction {
             helper.invoke(mWXModule,mInvoker,mArgs);
         } catch (Exception e) {
                  
WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(),
-                                 
WXErrorCode.WX_KEY_EXCEPTION_DOM_MODULEINVO.getErrorCode(),
+                                 WXErrorCode.WX_KEY_EXCEPTION_DOM_MODULEINVO,
                                  "updateAttr",
                                  
WXErrorCode.WX_KEY_EXCEPTION_DOM_MODULEINVO.getErrorMsg() + "callModuleMethod 
>>> invoke module:"
                                                  + 
mWXModule.getClass().getSimpleName() + " failed. " + 
WXLogUtils.getStackTrace(e),null);

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/dom/action/MoveElementAction.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/MoveElementAction.java 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/MoveElementAction.java
index e447283..a103858 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/MoveElementAction.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/MoveElementAction.java
@@ -59,7 +59,7 @@ final class MoveElementAction implements DOMAction, 
RenderAction {
         || parentObject == null || parentObject.hasNewLayout()) {
       if (instance != null) {
                
WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(),
-                               
WXErrorCode.WX_KEY_EXCEPTION_DOM_MOVE_ELEMENT.getErrorCode(),
+                               WXErrorCode.WX_KEY_EXCEPTION_DOM_MOVE_ELEMENT,
                                "moveElement",
                                
WXErrorCode.WX_KEY_EXCEPTION_DOM_MOVE_ELEMENT.getErrorMsg() +
                                                "domObject = " + domObject

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/dom/action/RemoveElementAction.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/RemoveElementAction.java 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/RemoveElementAction.java
index 36babe5..144d3ec 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/RemoveElementAction.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/RemoveElementAction.java
@@ -51,7 +51,7 @@ final class RemoveElementAction implements DOMAction, 
RenderAction {
       if (instance != null) {
 //        instance.commitUTStab(IWXUserTrackAdapter.DOM_MODULE, 
WXErrorCode.WX_ERR_DOM_REMOVEELEMENT);
                
WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(),
-                               
WXErrorCode.WX_KEY_EXCEPTION_DOM_REMOVE_ELEMENT.getErrorCode(),
+                               WXErrorCode.WX_KEY_EXCEPTION_DOM_REMOVE_ELEMENT,
                                "removeElement",
                                
WXErrorCode.WX_KEY_EXCEPTION_DOM_REMOVE_ELEMENT.getErrorMsg() + "domObject is 
null",null);
       }
@@ -62,7 +62,7 @@ final class RemoveElementAction implements DOMAction, 
RenderAction {
       if (instance != null) {
 //        instance.commitUTStab(IWXUserTrackAdapter.DOM_MODULE, 
WXErrorCode.WX_ERR_DOM_REMOVEELEMENT);
                
WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(),
-                               
WXErrorCode.WX_KEY_EXCEPTION_DOM_REMOVE_ELEMENT.getErrorCode(),
+                               WXErrorCode.WX_KEY_EXCEPTION_DOM_REMOVE_ELEMENT,
                                "removeElement",
                                
WXErrorCode.WX_KEY_EXCEPTION_DOM_REMOVE_ELEMENT.getErrorMsg() + "parent is 
null",null);
       }
@@ -85,6 +85,10 @@ final class RemoveElementAction implements DOMAction, 
RenderAction {
     clearRegistryForComponent(context, component);
     parent.remove(component, true);
     context.unregisterComponent(mRef);
+    WXSDKInstance instance = context.getInstance();
+    if (null != instance){
+      instance.onElementChange();
+    }
   }
 
   private void clearRegistryForComponent(RenderActionContext context, 
WXComponent component) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/dom/action/RemoveEventAction.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/RemoveEventAction.java 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/RemoveEventAction.java
index 511ada6..79f55af 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/RemoveEventAction.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/RemoveEventAction.java
@@ -57,7 +57,7 @@ class RemoveEventAction implements DOMAction, RenderAction {
     if (domObject == null) {
       if (instance != null) {
                
WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(),
-                               
WXErrorCode.WX_KEY_EXCEPTION_DOM_REMOVE_EVENT.getErrorCode(),
+                               WXErrorCode.WX_KEY_EXCEPTION_DOM_REMOVE_EVENT,
                                "updateAttr",
                                
WXErrorCode.WX_KEY_EXCEPTION_DOM_REMOVE_EVENT.getErrorMsg() + "domObject is 
null",null);
       }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateAttributeAction.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateAttributeAction.java
 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateAttributeAction.java
index ac6ca5d..92d8513 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateAttributeAction.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateAttributeAction.java
@@ -58,7 +58,7 @@ class UpdateAttributeAction extends TraceableAction 
implements DOMAction, Render
     if (domObject == null) {
       if (instance != null) {
                
WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(),
-                               
WXErrorCode.WX_KEY_EXCEPTION_DOM_UPDATE_ATTRS.getErrorCode(),
+                               WXErrorCode.WX_KEY_EXCEPTION_DOM_UPDATE_ATTRS,
                                "updateAttr",
                                
WXErrorCode.WX_KEY_EXCEPTION_DOM_UPDATE_ATTRS.getErrorMsg() + "domObject is 
null",null);
       }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateStyleAction.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateStyleAction.java 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateStyleAction.java
index 0c9a08a..a289bca 100644
--- 
a/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateStyleAction.java
+++ 
b/android/sdk/src/main/java/com/taobao/weex/dom/action/UpdateStyleAction.java
@@ -68,7 +68,7 @@ class UpdateStyleAction extends TraceableAction implements 
DOMAction, RenderActi
     if (domObject == null) {
       if (instance != null) {
                
WXExceptionUtils.commitCriticalExceptionRT(instance.getInstanceId(),
-                               
WXErrorCode.WX_KEY_EXCEPTION_DOM_UPDATE_STYLE.getErrorCode(),
+                               WXErrorCode.WX_KEY_EXCEPTION_DOM_UPDATE_STYLE,
                                "updateStyle",
                                
WXErrorCode.WX_KEY_EXCEPTION_DOM_UPDATE_STYLE.getErrorMsg() + "domObject is 
null",null);
       }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/performance/FpsCollector.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/performance/FpsCollector.java 
b/android/sdk/src/main/java/com/taobao/weex/performance/FpsCollector.java
new file mode 100644
index 0000000..5819bd2
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/performance/FpsCollector.java
@@ -0,0 +1,113 @@
+/**
+ * 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 com.taobao.weex.performance;
+
+
+import android.os.Build;
+import android.os.Handler;
+import android.support.annotation.RequiresApi;
+import android.view.Choreographer;
+
+import com.taobao.weex.WXEnvironment;
+import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.common.WXPerformance;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * @author chenpeihan
+ * @date 2017/12/12
+ */
+
+public class FpsCollector {
+
+  private Map<String, IFPSCallBack> mListenerMap = new ConcurrentHashMap<>();
+  private AtomicBoolean mHasInit = new AtomicBoolean(false);
+
+
+  private static class SingleTonHolder {
+
+    private static FpsCollector INSTANCE = new FpsCollector();
+  }
+
+  public static FpsCollector getInstance() {
+    return SingleTonHolder.INSTANCE;
+  }
+
+  public void init() {
+    if (!WXEnvironment.isApkDebugable()) {
+      return;
+    }
+    if (mHasInit.compareAndSet(false, true)) {
+      WXSDKManager.getInstance().postOnUiThread(new Runnable() {
+        @Override
+        public void run() {
+          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && 
WXPerformance.TRACE_DATA) {
+            Choreographer.getInstance().postFrameCallback(new 
OnFrameListener());
+          }
+        }
+      }, 0);
+
+    }
+  }
+
+
+  @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
+  private class OnFrameListener implements Choreographer.FrameCallback {
+
+    private int mFrameCount = 0;
+    private long mTimeBegin = 0;
+
+    @Override
+    public void doFrame(long frameTimeNanos) {
+      Choreographer.getInstance().postFrameCallback(this);
+      if (mTimeBegin == 0) {
+        mTimeBegin = System.currentTimeMillis();
+        mFrameCount++;
+        return;
+      }
+      long timeDiff = System.currentTimeMillis() - mTimeBegin;
+      if (timeDiff < 1000) {
+        mFrameCount++;
+        return;
+      }
+      for (Map.Entry<String, IFPSCallBack> entry : mListenerMap.entrySet()) {
+        entry.getValue().fps(mFrameCount);
+      }
+      WXAnalyzerDataTransfer.transferFps(mFrameCount);
+
+      mTimeBegin = 0;
+      mFrameCount = 0;
+    }
+  }
+
+  public interface IFPSCallBack {
+
+    void fps(int fps);
+  }
+
+
+  public void registerListener(String key, IFPSCallBack listener) {
+    mListenerMap.put(key, listener);
+  }
+
+  public void unRegister(String key) {
+    mListenerMap.remove(key);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/performance/IWXAnalyzer.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/performance/IWXAnalyzer.java 
b/android/sdk/src/main/java/com/taobao/weex/performance/IWXAnalyzer.java
new file mode 100644
index 0000000..cbd170c
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/performance/IWXAnalyzer.java
@@ -0,0 +1,35 @@
+/**
+ * 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 com.taobao.weex.performance;
+
+
+/**
+ * @author zhongcang
+ * @date 2018/2/28
+ */
+
+public interface IWXAnalyzer {
+
+  /**
+   *
+   * @param group   dataGroup
+   * @param module  dataModule in group
+   * @param type    dataType
+   * @param data   data (json)
+   */
+  void transfer(String group, String module, String type, String data);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/performance/MemUtils.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/performance/MemUtils.java 
b/android/sdk/src/main/java/com/taobao/weex/performance/MemUtils.java
new file mode 100644
index 0000000..9933988
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/performance/MemUtils.java
@@ -0,0 +1,80 @@
+/**
+ * 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 com.taobao.weex.performance;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.Build;
+import android.os.Debug;
+import android.util.Log;
+
+import com.taobao.weex.WXEnvironment;
+
+/**
+ * @author chenpeihan
+ * @date 2017/12/12
+ */
+
+public class MemUtils {
+
+    /**
+     * bad performance ,40ms-60ms
+     */
+    public static Debug.MemoryInfo getMemoryInfo(Context context) {
+        long start = System.currentTimeMillis();
+        if (null == context){
+            return null;
+        }
+        Debug.MemoryInfo meminfo = null;
+        ActivityManager activityManager = (ActivityManager) 
context.getSystemService(Context.ACTIVITY_SERVICE);
+        if (activityManager != null) {
+            if (Build.VERSION.SDK_INT >= 23) {
+                int[] pids = {android.os.Process.myPid()};
+                Debug.MemoryInfo[] meminfos = 
activityManager.getProcessMemoryInfo(pids);
+                if (meminfos != null && meminfos.length > 0) {
+                    meminfo = meminfos[0];
+                }
+            } else {
+                meminfo = new Debug.MemoryInfo();
+                Debug.getMemoryInfo(meminfo);
+                int privateDirty = meminfo.getTotalPrivateDirty();
+                if (privateDirty == 0) {
+                    Debug.getMemoryInfo(meminfo);
+                }
+            }
+        }
+        if (WXEnvironment.isApkDebugable()){
+            Log.d("MemUtils", "getMemoryInfo , time 
:"+(System.currentTimeMillis() -start));
+        }
+
+        return meminfo;
+    }
+
+    public static long getTotalPss(Context context) {
+
+        long totalPss = 0L;
+
+        Debug.MemoryInfo meminfo = getMemoryInfo(context);
+        if (meminfo != null) {
+            totalPss = meminfo.getTotalPss();
+        }
+        return totalPss;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/performance/WXAnalyzerDataTransfer.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/performance/WXAnalyzerDataTransfer.java
 
b/android/sdk/src/main/java/com/taobao/weex/performance/WXAnalyzerDataTransfer.java
new file mode 100644
index 0000000..129dcec
--- /dev/null
+++ 
b/android/sdk/src/main/java/com/taobao/weex/performance/WXAnalyzerDataTransfer.java
@@ -0,0 +1,138 @@
+/**
+ * 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 com.taobao.weex.performance;
+
+import com.taobao.weex.WXEnvironment;
+import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.common.WXErrorCode;
+import com.taobao.weex.common.WXJSExceptionInfo;
+import com.taobao.weex.common.WXPerformance;
+
+import org.json.JSONObject;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author zhongcang
+ * @date 2018/2/28
+ */
+
+public class WXAnalyzerDataTransfer {
+
+  private static final String GROUP = "WXAnalyzer";
+  private static final String MODULE_PERFORMANCE = "WXPerformance";
+  private static final String MODULE_ERROR = "WXError";
+
+
+  public static void transferPerformance(WXPerformance performance, String 
instanceId) {
+    if (!WXEnvironment.isApkDebugable()) {
+      return;
+    }
+    List<IWXAnalyzer> transferList = 
WXSDKManager.getInstance().getWXAnalyzerList();
+    if (null == transferList || transferList.size() == 0) {
+      return;
+    }
+
+
+    WXSDKInstance instance = 
WXSDKManager.getInstance().getSDKInstance(instanceId);
+    if (null == instance) {
+      return;
+    }
+    String data = "";
+    try {
+      JSONObject dimensionMap = new JSONObject();
+      JSONObject measureMap = new JSONObject();
+
+      for (Map.Entry<String, String> entry : 
performance.getDimensionMap().entrySet()) {
+        dimensionMap.put(entry.getKey(), entry.getValue());
+      }
+      for (Map.Entry<String, Double> entry : 
performance.getMeasureMap().entrySet()) {
+        measureMap.put(entry.getKey(), entry.getValue());
+      }
+
+      data = new JSONObject()
+          .put("instanceId", instanceId)
+          .put("url", instance.getBundleUrl())
+          .put("dimensionMap", dimensionMap)
+          .put("measureMap", measureMap)
+          .toString();
+
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    for (IWXAnalyzer transfer : transferList) {
+      transfer.transfer(GROUP, MODULE_PERFORMANCE, "instance", data);
+    }
+  }
+
+  public static void transferError(WXJSExceptionInfo exceptionInfo, String 
instanceId) {
+    if (!WXEnvironment.isApkDebugable()) {
+      return;
+    }
+    List<IWXAnalyzer> transferList = 
WXSDKManager.getInstance().getWXAnalyzerList();
+    if (null == transferList || transferList.size() == 0) {
+      return;
+    }
+
+    WXSDKInstance instance = 
WXSDKManager.getInstance().getSDKInstance(instanceId);
+    if (null == instance) {
+      return;
+    }
+    WXErrorCode errorCode = exceptionInfo.getErrCode();
+    String data = "";
+    try {
+      data = new JSONObject()
+          .put("instanceId", instanceId)
+          .put("url", instance.getBundleUrl())
+          .put("errorCode", errorCode.getErrorCode())
+          .put("errorMsg", errorCode.getErrorMsg())
+          .put("errorGroup", errorCode.getErrorGroup())
+          .toString();
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    for (IWXAnalyzer transfer : transferList) {
+      transfer.transfer(GROUP, MODULE_ERROR, 
errorCode.getErrorType().toString(), data);
+    }
+  }
+
+  public static void transferFps(long fps) {
+    if (!WXEnvironment.isApkDebugable()) {
+      return;
+    }
+    List<IWXAnalyzer> transferList = 
WXSDKManager.getInstance().getWXAnalyzerList();
+    if (null == transferList || transferList.size() == 0) {
+      return;
+    }
+    String data = "";
+    try {
+      data = new JSONObject().put("fps", fps).toString();
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    for (IWXAnalyzer transfer : transferList) {
+      transfer.transfer(GROUP, MODULE_PERFORMANCE, "fps", data);
+    }
+  }
+
+//  @Override
+//  public void transfer2(String tag, String module, String type, String data) 
{
+//    WXLogUtils.d(tag, module + ":" + type + ":" + data);
+//  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java
index 6522c9b..39a0358 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXComponent.java
@@ -66,6 +66,7 @@ import com.taobao.weex.bridge.EventResult;
 import com.taobao.weex.bridge.Invoker;
 import com.taobao.weex.common.Constants;
 import com.taobao.weex.common.IWXObject;
+import com.taobao.weex.common.WXPerformance;
 import com.taobao.weex.common.WXRuntimeException;
 import com.taobao.weex.dom.ImmutableDomObject;
 import com.taobao.weex.dom.WXDomHandler;
@@ -535,6 +536,10 @@ public abstract class  WXComponent<T extends View> 
implements IWXObject, IWXActi
       return;
     }
 
+    if (realHeight >= WXPerformance.VIEW_LIMIT_HEIGHT && 
realWidth>=WXPerformance.VIEW_LIMIT_WIDTH){
+      mInstance.getWXPerformance().cellExceedNum++;
+    }
+
     mAbsoluteY = (int) (nullParent?0:mParent.getAbsoluteY() + 
mDomObj.getLayoutY());
     mAbsoluteX = (int) (nullParent?0:mParent.getAbsoluteX() + 
mDomObj.getLayoutX());
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/ui/component/WXEmbed.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXEmbed.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXEmbed.java
index 6002a5d..87f5859 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXEmbed.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXEmbed.java
@@ -30,10 +30,10 @@ import android.widget.ImageView;
 import com.taobao.weappplus_sdk.R;
 import com.taobao.weex.IWXRenderListener;
 import com.taobao.weex.WXEnvironment;
-import com.taobao.weex.WXRenderErrorCode;
 import com.taobao.weex.WXSDKInstance;
 import com.taobao.weex.annotation.Component;
 import com.taobao.weex.common.Constants;
+import com.taobao.weex.common.WXErrorCode;
 import com.taobao.weex.common.WXPerformance;
 import com.taobao.weex.common.WXRenderStrategy;
 import com.taobao.weex.dom.WXDomObject;
@@ -112,8 +112,8 @@ public class WXEmbed extends WXDiv implements 
WXSDKInstance.OnInstanceVisibleLis
   public static class ClickToReloadListener implements 
OnNestedInstanceEventListener {
     @Override
     public void onException(NestedContainer container, String errCode, String 
msg) {
-      if (TextUtils.equals(errCode, WXRenderErrorCode.DegradPassivityCode.
-                         
WX_DEGRAD_ERR_NETWORK_BUNDLE_DOWNLOAD_FAILED.getDegradErrorCode()) && container 
instanceof WXEmbed) {
+      if (TextUtils.equals(errCode, WXErrorCode.
+                         
WX_DEGRAD_ERR_NETWORK_BUNDLE_DOWNLOAD_FAILED.getErrorCode()) && container 
instanceof WXEmbed) {
         final WXEmbed comp = ((WXEmbed)container);
         final ImageView imageView = new ImageView(comp.getContext());
         imageView.setImageResource(R.drawable.error);
@@ -327,8 +327,8 @@ public class WXEmbed extends WXDiv implements 
WXSDKInstance.OnInstanceVisibleLis
 
     if(TextUtils.isEmpty(url)){
       mListener.mEventListener.onException(this,
-                         
WXRenderErrorCode.DegradPassivityCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getDegradErrorCode(),
-                         
WXRenderErrorCode.DegradPassivityCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getDegradErrorMsg()
 + "!!wx embed src url is null"
+                         
WXErrorCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getErrorCode(),
+              WXErrorCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getErrorMsg() 
+ "!!wx embed src url is null"
          );
       return sdkInstance;
     }
@@ -347,7 +347,7 @@ public class WXEmbed extends WXDiv implements 
WXSDKInstance.OnInstanceVisibleLis
     super.setVisibility(visibility);
     boolean visible = TextUtils.equals(visibility, Constants.Value.VISIBLE);
     if(mIsVisible != visible){
-      
+
       if (!TextUtils.isEmpty(src) && visible) {
         if (mNestedInstance == null) {
           loadContent();

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java
index f307d8a..dcaefdf 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java
@@ -22,6 +22,7 @@ import android.Manifest;
 import android.app.Activity;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -31,6 +32,8 @@ import android.support.annotation.Nullable;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.content.ContextCompat;
 import android.text.TextUtils;
+import android.util.Log;
+import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
 
@@ -323,6 +326,7 @@ public class WXImage extends WXComponent<ImageView> {
               fireEvent(Constants.Event.ONLOAD, params);
             }
           }
+          monitorImgSize(imageView);
         }
       });
 
@@ -437,6 +441,25 @@ public class WXImage extends WXComponent<ImageView> {
     });
   }
 
+  private void monitorImgSize(ImageView imageView){
+    if (null == imageView){
+      return;
+    }
+    WXSDKInstance instance = getInstance();
+    if (null == instance){
+      return;
+    }
+    ViewGroup.LayoutParams params =imageView.getLayoutParams();
+    Drawable img = imageView.getDrawable();
+    if (null == params || null ==img){
+      return;
+    }
+
+    if (img.getIntrinsicHeight() * img.getIntrinsicWidth() > 
imageView.getMeasuredHeight() *
+                                                             
imageView.getMeasuredWidth()){
+      instance.getWXPerformance().wrongImgSizeCount++;
+    }
+  }
 
   public void destroy() {
     if(getHostView() instanceof WXImageView){

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/ui/module/WXTimerModule.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/ui/module/WXTimerModule.java 
b/android/sdk/src/main/java/com/taobao/weex/ui/module/WXTimerModule.java
index 2c048c1..8745b54 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/module/WXTimerModule.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/module/WXTimerModule.java
@@ -41,6 +41,7 @@ import com.taobao.weex.bridge.WXHashMap;
 import com.taobao.weex.bridge.WXJSObject;
 import com.taobao.weex.common.Destroyable;
 import com.taobao.weex.common.WXModule;
+import com.taobao.weex.common.WXPerformance;
 import com.taobao.weex.dom.action.Actions;
 import com.taobao.weex.utils.WXJsonUtils;
 import com.taobao.weex.utils.WXLogUtils;
@@ -69,6 +70,14 @@ public class WXTimerModule extends WXModule implements 
Destroyable, Handler.Call
   public void setTimeout(@IntRange(from = 1) int funcId, @FloatRange(from = 0) 
float delay) {
     if(mWXSDKInstance != null) {
       postOrHoldMessage(MODULE_TIMEOUT, funcId, (int) delay, 
Integer.parseInt(mWXSDKInstance.getInstanceId()));
+      WXSDKManager.getInstance().postOnUiThread(new Runnable() {
+          @Override
+          public void run() {
+            if (null != mWXSDKInstance){
+              mWXSDKInstance.getWXPerformance().timerInvokeCount++;
+            }
+          }
+      },0);
     }
   }
 
@@ -76,6 +85,14 @@ public class WXTimerModule extends WXModule implements 
Destroyable, Handler.Call
   public void setInterval(@IntRange(from = 1) int funcId, @FloatRange(from = 
0) float interval) {
     if(mWXSDKInstance != null) {
       postOrHoldMessage(MODULE_INTERVAL, funcId, (int) interval, 
Integer.parseInt(mWXSDKInstance.getInstanceId()));
+      WXSDKManager.getInstance().postOnUiThread(new Runnable() {
+          @Override
+          public void run() {
+            if (null != mWXSDKInstance){
+              mWXSDKInstance.getWXPerformance().timerInvokeCount++;
+            }
+          }
+      },0);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/utils/WXExceptionUtils.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/utils/WXExceptionUtils.java 
b/android/sdk/src/main/java/com/taobao/weex/utils/WXExceptionUtils.java
index 4fbcafc..c571ba2 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/WXExceptionUtils.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/WXExceptionUtils.java
@@ -18,14 +18,22 @@
  */
 package com.taobao.weex.utils;
 
+import android.app.Activity;
+import android.content.Context;
 import android.support.annotation.Nullable;
 import android.text.TextUtils;
 
 import com.taobao.weex.WXSDKInstance;
 import com.taobao.weex.WXSDKManager;
 import com.taobao.weex.adapter.IWXJSExceptionAdapter;
+import com.taobao.weex.performance.IWXAnalyzer;
+import com.taobao.weex.common.WXErrorCode;
 import com.taobao.weex.common.WXJSExceptionInfo;
 import com.taobao.weex.common.WXPerformance;
+import com.taobao.weex.performance.WXAnalyzerDataTransfer;
+
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -39,6 +47,7 @@ public class WXExceptionUtils {
    */
   public static String degradeUrl = "BundleUrlDefaultDegradeUrl";
 
+
   /**
    * commitCriticalExceptionRT eg:JsRuntime Exception or JsFramework Init 
Exception
    * @param instanceId
@@ -48,7 +57,7 @@ public class WXExceptionUtils {
    * @param extParams
    */
   public static void commitCriticalExceptionRT(@Nullable final String 
instanceId,
-                                                                               
           @Nullable final String errCode,
+                                                                               
           @Nullable final WXErrorCode errCode,
                                                                                
           @Nullable final String function,
                                                                                
           @Nullable final String exception,
                                                                                
           @Nullable final Map<String,String> extParams ) {
@@ -59,11 +68,22 @@ public class WXExceptionUtils {
        String instanceIdCommit = "InstanceIdDefalut";
        String exceptionMsgCommit = exception;
        Map<String, String> commitMap = extParams;
+       if (null == commitMap){
+         commitMap = new HashMap<>();
+       }
+       commitMap.put("activity","empty");
 
        if (!TextUtils.isEmpty(instanceId)) {
          instanceIdCommit = instanceId;
          instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
 
+         if (null != instance && instance.getContainerView() != null){
+               Context c = instance.getContainerView().getContext();
+               if (c instanceof Activity){
+                 commitMap.put("activity",c.getClass().getSimpleName());
+               }
+         }
+
          if (null != instance && instance.getContext() != null && 
instance.getBundleUrl() != null) {
                bundleUrlCommit = instance.getBundleUrl();
                exceptionMsgCommit += "\n instance.getTemplateInfo()==" + 
instance.getTemplateInfo();
@@ -72,8 +92,8 @@ public class WXExceptionUtils {
                        bundleUrlCommit = degradeUrl;
                  } else
                        bundleUrlCommit = WXSDKInstance.requestUrl;
-               }
-         }
+                 }
+          }
        } else {//instance is null for instance id is null
          if (!TextUtils.isEmpty(WXSDKInstance.requestUrl)) {
                bundleUrlCommit = WXSDKInstance.requestUrl;
@@ -84,10 +104,12 @@ public class WXExceptionUtils {
          }
        }
 
+        exceptionCommit = new WXJSExceptionInfo(instanceIdCommit, 
bundleUrlCommit, errCode, function, exceptionMsgCommit, commitMap);
        if (adapter != null) {
-         exceptionCommit = new WXJSExceptionInfo(instanceIdCommit, 
bundleUrlCommit, errCode, function, exceptionMsgCommit, commitMap);
          adapter.onJSException(exceptionCommit);
-         WXLogUtils.e(exceptionCommit.toString());
        }
+
+       WXAnalyzerDataTransfer.transferError(exceptionCommit, instanceId);
+
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java 
b/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java
index e8ec6bc..b03fb95 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/WXLogUtils.java
@@ -28,7 +28,9 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 
 public class WXLogUtils {
 
@@ -39,11 +41,12 @@ public class WXLogUtils {
 
   private static StringBuilder builder = new StringBuilder(50);
   private static HashMap<String, Class> clazzMaps = new HashMap<>(2);
-  private static JsLogWatcher jsLogWatcher;
+  private static List<JsLogWatcher> jsLogWatcherList;
   private static LogWatcher sLogWatcher;
 
   static {
     clazzMaps.put(CLAZZ_NAME_LOG_UTIL, loadClass(CLAZZ_NAME_LOG_UTIL));
+    jsLogWatcherList = new ArrayList<>();
   }
 
   private static Class loadClass(String clazzName) {
@@ -124,18 +127,20 @@ public class WXLogUtils {
          log(tag, msg, LogLevel.DEBUG);
 
          if(WXEnvironment.isApkDebugable()){//sLogLevel in debug mode is 
"LogLevel.DEBUG"
-               if ("jsLog".equals(tag) && jsLogWatcher != null) {
-                 if (msg.endsWith("__DEBUG")) {
-                       jsLogWatcher.onJsLog(Log.DEBUG, msg.replace("__DEBUG", 
""));
-                 } else if (msg.endsWith("__INFO")) {
-                       jsLogWatcher.onJsLog(Log.DEBUG, msg.replace("__INFO", 
""));
-                 } else if (msg.endsWith("__WARN")) {
-                       jsLogWatcher.onJsLog(Log.DEBUG, msg.replace("__WARN", 
""));
-                 } else if (msg.endsWith("__ERROR")) {
-                       jsLogWatcher.onJsLog(Log.DEBUG, msg.replace("__ERROR", 
""));
-                 } else {
-                       jsLogWatcher.onJsLog(Log.DEBUG, msg);
-                 }
+               if ("jsLog".equals(tag) && jsLogWatcherList != null && 
jsLogWatcherList.size() > 0) {
+          for (JsLogWatcher jsLogWatcher : jsLogWatcherList) {
+            if (msg.endsWith("__DEBUG")) {
+              jsLogWatcher.onJsLog(Log.DEBUG, msg.replace("__DEBUG", ""));
+            } else if (msg.endsWith("__INFO")) {
+              jsLogWatcher.onJsLog(Log.DEBUG, msg.replace("__INFO", ""));
+            } else if (msg.endsWith("__WARN")) {
+              jsLogWatcher.onJsLog(Log.DEBUG, msg.replace("__WARN", ""));
+            } else if (msg.endsWith("__ERROR")) {
+              jsLogWatcher.onJsLog(Log.DEBUG, msg.replace("__ERROR", ""));
+            } else {
+              jsLogWatcher.onJsLog(Log.DEBUG, msg);
+            }
+          }
                }
 
                /** This log method will be invoked from jni code, so try to 
extract loglevel from message. **/
@@ -289,7 +294,9 @@ public class WXLogUtils {
   }
 
   public static void setJsLogWatcher(JsLogWatcher watcher) {
-    jsLogWatcher = watcher;
+    if (!jsLogWatcherList.contains(watcher)) {
+      jsLogWatcherList.add(watcher);
+    }
   }
 
   public static void setLogWatcher(LogWatcher watcher) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java 
b/android/sdk/src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java
index 60d45d8..7fc1009 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java
@@ -112,7 +112,7 @@ public class WXSoInstallMgrSdk {
     String cpuType = _cpuType();
     if (cpuType.equalsIgnoreCase(MIPS) ) {
          WXExceptionUtils.commitCriticalExceptionRT(null,
-                         WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT.getErrorCode(),
+                         WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT,
                          "initSo", 
"[WX_KEY_EXCEPTION_SDK_INIT_CPU_NOT_SUPPORT] for android cpuType is MIPS",
                          null);
       return false;
@@ -140,7 +140,7 @@ public class WXSoInstallMgrSdk {
       } catch (Exception | Error e2) {
         if (cpuType.contains(ARMEABI) || cpuType.contains(X86)) {
                  WXExceptionUtils.commitCriticalExceptionRT(null,
-                                 
WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT.getErrorCode(),
+                                 WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT,
                                  "initSo", 
"[WX_KEY_EXCEPTION_SDK_INIT_CPU_NOT_SUPPORT] for android cpuType is " +cpuType +
                                  "\n Detail Error is: " +e2.getMessage(),
                                  null);
@@ -295,7 +295,7 @@ public class WXSoInstallMgrSdk {
       }
     }catch(Throwable e ){
          WXExceptionUtils.commitCriticalExceptionRT(null,
-                         WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT.getErrorCode(),
+                         WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT,
                          "checkSoIsValid", 
"[WX_KEY_EXCEPTION_SDK_INIT_CPU_NOT_SUPPORT] for " +
                                          "weex so size check fail exception 
:"+e.getMessage(),
                          null);
@@ -375,7 +375,7 @@ public class WXSoInstallMgrSdk {
     } catch (Throwable e) {
          initSuc = false;
          WXExceptionUtils.commitCriticalExceptionRT(null,
-                         "-9001",
+                         WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT_CPU_NOT_SUPPORT,
                          "_loadUnzipSo", 
"[WX_KEY_EXCEPTION_SDK_INIT_WX_ERR_COPY_FROM_APK] " +
                          "\n Detail Msg is : " +  e.getMessage(),
                          null);
@@ -473,7 +473,7 @@ public class WXSoInstallMgrSdk {
     } catch (java.io.IOException e) {
       e.printStackTrace();
          WXExceptionUtils.commitCriticalExceptionRT(null,
-                         "-9001",
+                         WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT_CPU_NOT_SUPPORT,
                          "unZipSelectedFiles", 
"[WX_KEY_EXCEPTION_SDK_INIT_unZipSelectedFiles] " +
                          "\n Detail msg is: " + e.getMessage(),
                          null);

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/495c7aca/android/sdk/src/test/java/com/taobao/weex/utils/WXExceptionUtilsTest.java
----------------------------------------------------------------------
diff --git 
a/android/sdk/src/test/java/com/taobao/weex/utils/WXExceptionUtilsTest.java 
b/android/sdk/src/test/java/com/taobao/weex/utils/WXExceptionUtilsTest.java
index 81c9804..8709304 100644
--- a/android/sdk/src/test/java/com/taobao/weex/utils/WXExceptionUtilsTest.java
+++ b/android/sdk/src/test/java/com/taobao/weex/utils/WXExceptionUtilsTest.java
@@ -20,6 +20,7 @@ package com.taobao.weex.utils;
 
 import com.taobao.weappplus_sdk.BuildConfig;
 import com.taobao.weex.WXEnvironment;
+import com.taobao.weex.common.WXErrorCode;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -67,7 +68,7 @@ public class WXExceptionUtilsTest {
        Map testMap =  new HashMap<String, String>();
        testMap.put("weexUrl","weexurltest");
        testMap.put("bundleUrl","bundleUrltest");
-       Exp.commitCriticalExceptionRT("1","test","test","test",testMap);
-       Exp.commitCriticalExceptionRT("1","test","test","test",null);
+       Exp.commitCriticalExceptionRT("1", 
WXErrorCode.WX_ERR_TEST,"test","test",testMap);
+       
Exp.commitCriticalExceptionRT("1",WXErrorCode.WX_ERR_TEST,"test","test",null);
   }
 }
\ No newline at end of file

Reply via email to