You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ky...@apache.org on 2019/07/01 08:43:45 UTC

[incubator-weex] branch master updated: [Android] solve components exceed gpu limit problem (#2603)

This is an automated email from the ASF dual-hosted git repository.

kyork pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-weex.git


The following commit(s) were added to refs/heads/master by this push:
     new 48a7cb7  [Android] solve components exceed gpu limit problem (#2603)
48a7cb7 is described below

commit 48a7cb7cf9dd8e59d97bb53d2d263f51ab5af403
Author: katherine95s <51...@users.noreply.github.com>
AuthorDate: Mon Jul 1 16:43:40 2019 +0800

    [Android] solve components exceed gpu limit problem (#2603)
---
 .../main/java/com/taobao/weex/WXSDKInstance.java   | 11 ++-
 .../com/taobao/weex/bridge/WXBridgeManager.java    | 92 +++++++++++++++++++---
 .../java/com/taobao/weex/common/WXErrorCode.java   |  1 +
 .../java/com/taobao/weex/ui/WXRenderManager.java   | 61 ++++++++++++++
 .../com/taobao/weex/ui/component/WXComponent.java  | 23 ++++++
 5 files changed, 174 insertions(+), 14 deletions(-)

diff --git a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
index d66b444..5d78e19 100644
--- a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
+++ b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
@@ -95,6 +95,7 @@ import java.io.Serializable;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.PriorityQueue;
@@ -152,6 +153,7 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
   private Map<String,String> mContainerInfo;
 
   public boolean isNewFsEnd = false;
+  private List<JSONObject> componentsInfoExceedGPULimit  = new LinkedList<>();
 
   /**
    * bundle type
@@ -206,6 +208,13 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
    * */
   private boolean mAutoAdjustDeviceWidth = WXEnvironment.AUTO_ADJUST_ENV_DEVICE_WIDTH;
 
+  public  List<JSONObject> getComponentsExceedGPULimit(){return componentsInfoExceedGPULimit;}
+  @RestrictTo(Scope.LIBRARY)
+  public void setComponentsInfoExceedGPULimit(JSONObject component){
+    if(component!= null && !component.isEmpty()){
+      componentsInfoExceedGPULimit.add(component);
+    }
+  }
 
   public List<String> getLayerOverFlowListeners() {
     return mLayerOverFlowListeners;
@@ -827,7 +836,7 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
     mWXPerformance.JSTemplateSize = template.length() / 1024f;
     mApmForInstance.addStats(WXInstanceApm.KEY_PAGE_STATS_BUNDLE_SIZE,mWXPerformance.JSTemplateSize);
     mRenderStartTime = System.currentTimeMillis();
-    WXSDKManager.getInstance().setCrashInfo(WXEnvironment.WEEX_CURRENT_KEY,pageName);;
+    WXSDKManager.getInstance().setCrashInfo(WXEnvironment.WEEX_CURRENT_KEY,pageName);
     if(mAutoAdjustDeviceWidth && WXDeviceUtils.isAutoResize(mContext)){
          if(WXEnvironment.AUTO_UPDATE_APPLICATION_SCREEN_SIZE) {
              WXViewUtils.updateApplicationScreen(mContext);
diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
index 8968596..87f7557 100644
--- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
@@ -62,6 +62,7 @@ import com.taobao.weex.layout.ContentBoxMeasurement;
 import com.taobao.weex.performance.WXInstanceApm;
 import com.taobao.weex.performance.WXStateRecord;
 import com.taobao.weex.ui.WXComponentRegistry;
+import com.taobao.weex.ui.WXRenderManager;
 import com.taobao.weex.ui.action.ActionReloadPage;
 import com.taobao.weex.ui.action.BasicGraphicAction;
 import com.taobao.weex.ui.action.GraphicActionAddElement;
@@ -102,11 +103,13 @@ import java.lang.reflect.Method;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Stack;
 import java.util.concurrent.CountDownLatch;
@@ -851,7 +854,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
                 Log.d("jsengine", "callReportCrashReloadPage crashFile:" + crashFile);
             }
         } catch (Throwable e) {
-            e.printStackTrace();
+          WXLogUtils.e(WXLogUtils.getStackTrace(e));
         }
         WXStateRecord.getInstance().onJSCCrash();
         callReportCrash(crashFile, instanceId, url);
@@ -955,7 +958,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
                 commitJscCrashAlarmMonitor(IWXUserTrackAdapter.JS_BRIDGE, WXErrorCode.WX_ERR_JSC_CRASH, result.toString(), instanceId, url);
                 br.close();
               } catch (Exception e) {
-                e.printStackTrace();
+                WXLogUtils.e(WXLogUtils.getStackTrace(e));
               }
             } else {
               WXLogUtils.e("[WXBridgeManager] callReportCrash crash file is empty");
@@ -1536,7 +1539,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
             WXLogUtils.e("end getBundleType type:" + type.toString() + " time:" + (end - start));
           }
         } catch (Throwable e) {
-          e.printStackTrace();
+          WXLogUtils.e(WXLogUtils.getStackTrace(e));
         }
 
         try {
@@ -1566,7 +1569,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
             options.put("env", mInitParams.toMap());
           }
         } catch (Throwable e) {
-          e.printStackTrace();
+          WXLogUtils.e(WXLogUtils.getStackTrace(e));
         }
         instance.bundleType = type;
         if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
@@ -1694,7 +1697,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
       }
       return new WXJSObject(WXJSObject.JSON, obj.toString());
     } catch (Throwable e) {
-      e.printStackTrace();
+      WXLogUtils.e(WXLogUtils.getStackTrace(e));
     }
     return opt;
 
@@ -1748,7 +1751,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
       }
       return BundType.Others;
     } catch (Throwable e) {
-      e.printStackTrace();
+      WXLogUtils.e(WXLogUtils.getStackTrace(e));
       return BundType.Others;
     }
   }
@@ -2030,7 +2033,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
               adapter.commit(WXEnvironment.getApplication(),"sJSFMStartListener",IWXUserTrackAdapter.COUNTER,null,params);
             }
           }catch (Exception e){
-            e.printStackTrace();
+            WXLogUtils.e(WXLogUtils.getStackTrace(e));
           }
         }
 
@@ -2039,7 +2042,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
         try {
           crashFile = WXEnvironment.getApplication().getApplicationContext().getCacheDir().getPath();
         } catch (Exception e) {
-          e.printStackTrace();
+          WXLogUtils.e(WXLogUtils.getStackTrace(e));
         }
         boolean pieSupport = true;
         try {
@@ -2047,7 +2050,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
             pieSupport = false;
           }
         } catch (Exception e) {
-          e.printStackTrace();
+          WXLogUtils.e(WXLogUtils.getStackTrace(e));
         }
         sInitFrameWorkMsg.append(" | pieSupport:").append(pieSupport);
         WXLogUtils.d("[WXBridgeManager] initFrameworkEnv crashFile:" + crashFile + " pieSupport:" + pieSupport);
@@ -2443,7 +2446,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
             return;
           }
         } catch (Exception e) {
-          e.printStackTrace();
+          WXLogUtils.e(WXLogUtils.getStackTrace(e));
         }
       }
       if (METHOD_CREATE_INSTANCE.equals(function) && !instance.getApmForInstance().hasAddView){
@@ -2489,17 +2492,17 @@ public class WXBridgeManager implements Callback, BactchExecutor {
                       exceptionExt = result.toString();
                       br.close();
                     } catch (Exception e) {
-                      e.printStackTrace();
+                      WXLogUtils.e(WXLogUtils.getStackTrace(e));
                     }
                   }
                   file.delete();
                 }
               } catch (Throwable throwable) {
-                throwable.printStackTrace();
+                WXLogUtils.e(WXLogUtils.getStackTrace(throwable));
               }
             }
           } catch (Throwable e) {
-            e.printStackTrace();
+            WXLogUtils.e(WXLogUtils.getStackTrace(e));
           }
           exception += "\n" + exceptionExt;
           WXLogUtils.e("reportJSException:" + exception);
@@ -2948,7 +2951,69 @@ public class WXBridgeManager implements Callback, BactchExecutor {
 
     return IWXBridge.INSTANCE_RENDERING;
   }
+  private boolean shouldReportGPULimit() {
+    IWXConfigAdapter adapter = WXSDKManager.getInstance().getWxConfigAdapter();
+    boolean report_gpu_limited_layout = false;
+    float sample_rate_of_report = 0;
+    if (adapter != null) {
+      try {
+        sample_rate_of_report = Float.parseFloat(adapter
+                .getConfig("android_weex_test_gpu",
+                        "sample_rate_of_report",
+                        "0"));
+      }catch(Exception e){
+        WXLogUtils.e(WXLogUtils.getStackTrace(e));
+      }
+      WXLogUtils.i("sample_rate_of_report : " + sample_rate_of_report);
+      if(Math.random() < sample_rate_of_report){
+        report_gpu_limited_layout = true;
+      }
+    }
+    return report_gpu_limited_layout;
+  }
 
+  private void reportIfReachGPULimit(String instanceId,String ref,GraphicSize layoutSize){
+    float limit = WXRenderManager.getOpenGLRenderLimitValue();
+    if(limit > 0 && (layoutSize.getHeight() > limit || layoutSize.getWidth() > limit)){
+      Map<String, String> ext = new ArrayMap<>();
+      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());
+      }
+      JSONObject map = new JSONObject();
+      map.putAll(ext);
+      WXSDKManager.getInstance().getSDKInstance(instanceId).setComponentsInfoExceedGPULimit(map);
+      if(shouldReportGPULimit()) {
+        WXExceptionUtils.commitCriticalExceptionRT(instanceId
+                , WXErrorCode.WX_RENDER_WAR_GPU_LIMIT_LAYOUT,
+                "WXBridgeManager",
+                String.format(Locale.ENGLISH, "You are creating a component(%s x %2$s) which exceeds the limit of gpu(%3$s x %3$s),it may cause crash",
+                        String.valueOf(layoutSize.getWidth()), String.valueOf(layoutSize.getHeight()), String.valueOf(limit)),
+                ext);
+      }
+    }
+  }
   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)) {
@@ -2982,6 +3047,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
       if (instance != null) {
         GraphicSize size = new GraphicSize(width, height);
         GraphicPosition position = new GraphicPosition(left, top, right, bottom);
+        reportIfReachGPULimit(pageId,ref,size);
         GraphicActionAddElement addAction = instance.getInActiveAddElementAction(ref);
         if(addAction!=null) {
           addAction.setRTL(isRTL);
diff --git a/android/sdk/src/main/java/com/taobao/weex/common/WXErrorCode.java b/android/sdk/src/main/java/com/taobao/weex/common/WXErrorCode.java
index 0556879..df09117 100644
--- a/android/sdk/src/main/java/com/taobao/weex/common/WXErrorCode.java
+++ b/android/sdk/src/main/java/com/taobao/weex/common/WXErrorCode.java
@@ -223,6 +223,7 @@ public enum WXErrorCode {
   WX_RENDER_ERR_INSTANCE_ID_NULL("-9618", "WX_RENDER_ERR_INSTANCE_ID_NULL", ErrorType.NATIVE_ERROR, ErrorGroup.NATIVE),
   WX_RENDER_ERR_LIST_INVALID_COLUMN_COUNT("-9619", "WX_RENDER_ERR_LIST_INVALID_COLUMNJ_CONUNT", ErrorType.JS_ERROR, ErrorGroup.JS),
   WX_RENDER_ERR_TEXTURE_SETBACKGROUND("-9620", "WX_RENDER_ERR_TEXTURE_SETBACKGROUND", ErrorType.NATIVE_ERROR, ErrorGroup.NATIVE),
+  WX_RENDER_WAR_GPU_LIMIT_LAYOUT("-9621", "WX_RENDER_WAR_GPU_LIMIT_LAYOUT", ErrorType.JS_ERROR,ErrorGroup.JS),
 
   WX_KEY_EXCEPTION_NO_BUNDLE_TYPE("-9801", "Fatal Error : No bundle type in js bundle head, cause white screen or memory leak!!", ErrorType.JS_ERROR, ErrorGroup.JS),
   /**
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderManager.java b/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderManager.java
index 928c491..85f54b7 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderManager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/WXRenderManager.java
@@ -18,6 +18,7 @@
  */
 package com.taobao.weex.ui;
 
+import android.opengl.GLES10;
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 import android.support.annotation.RestrictTo.Scope;
@@ -33,6 +34,7 @@ import com.taobao.weex.ui.action.BasicGraphicAction;
 import com.taobao.weex.ui.action.GraphicActionBatchAction;
 import com.taobao.weex.ui.component.WXComponent;
 import com.taobao.weex.utils.WXExceptionUtils;
+import com.taobao.weex.utils.WXLogUtils;
 import com.taobao.weex.utils.WXUtils;
 
 import java.util.ArrayList;
@@ -41,6 +43,14 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
+
+
+
 /**
  * Manager class for render operation, mainly for managing {@link RenderContextImpl}.
  * This is <strong>not</strong> a thread-safe class
@@ -54,6 +64,7 @@ public class WXRenderManager {
   private final int MAX_DROP_FRAME_NATIVE_BATCH = 2000;
   private final static  String sKeyAction = "Action";
   private static int nativeBatchTimes = 0;
+  private static int mOpenGLRenderLimitValue = 0;
 
   public WXRenderManager() {
     mRenderContext = new ConcurrentHashMap<>();
@@ -81,6 +92,56 @@ public class WXRenderManager {
     return statement.getWXSDKInstance();
   }
 
+    public static int getOpenGLRenderLimitValue() {
+      if(mOpenGLRenderLimitValue == 0){
+          int maxsize = 0;
+              try {
+                  EGL10 egl = (EGL10) EGLContext.getEGL();
+                  EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+                  int[] vers = new int[2];
+                  egl.eglInitialize(dpy, vers);
+                  int[] configAttr = {
+                          EGL10.EGL_COLOR_BUFFER_TYPE, EGL10.EGL_RGB_BUFFER,
+                          EGL10.EGL_LEVEL, 0,
+                          EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
+                          EGL10.EGL_NONE};
+                  EGLConfig[] configs = new EGLConfig[1];
+                  int[] numConfig = new int[1];
+                  egl.eglChooseConfig(dpy, configAttr, configs, 1, numConfig);
+                  if(numConfig[0] == 0){
+                      //There is something wrong with opengl environment.
+                      maxsize = -1;
+                      egl.eglTerminate(dpy);
+                  }else {
+                      EGLConfig config = configs[0];
+                      int[] surfAttr = {
+                              EGL10.EGL_WIDTH, 64,
+                              EGL10.EGL_HEIGHT, 64,
+                              EGL10.EGL_NONE};
+                      EGLSurface surf = egl.eglCreatePbufferSurface(dpy, config, surfAttr);
+                      final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;// missing in EGL10
+                      int[] ctxAttrib = {
+                              EGL_CONTEXT_CLIENT_VERSION, 1,
+                              EGL10.EGL_NONE};
+                      EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, ctxAttrib);
+                      egl.eglMakeCurrent(dpy, surf, surf, ctx);
+                      int[] maxSize = new int[1];
+                      GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
+                      egl.eglMakeCurrent(dpy, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
+                              EGL10.EGL_NO_CONTEXT);
+                      egl.eglDestroySurface(dpy, surf);
+                      egl.eglDestroyContext(dpy, ctx);
+                      egl.eglTerminate(dpy);
+                      maxsize = maxSize[0];
+                  }
+              } catch(Exception e){
+                  WXLogUtils.e(WXLogUtils.getStackTrace(e));
+              }
+          mOpenGLRenderLimitValue = maxsize;
+      }
+      return mOpenGLRenderLimitValue;
+    }
+
   @RestrictTo(Scope.LIBRARY)
   public void postOnUiThread(Runnable runnable, long delayMillis) {
     mWXRenderHandler.postDelayed(WXThread.secure(runnable), delayMillis);
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 ca1b6ec..fa00470 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
@@ -60,6 +60,7 @@ import com.taobao.weex.WXEnvironment;
 import com.taobao.weex.WXSDKInstance;
 import com.taobao.weex.WXSDKManager;
 import com.taobao.weex.adapter.IWXAccessibilityRoleAdapter;
+import com.taobao.weex.adapter.IWXConfigAdapter;
 import com.taobao.weex.bridge.EventResult;
 import com.taobao.weex.bridge.Invoker;
 import com.taobao.weex.bridge.WXBridgeManager;
@@ -78,6 +79,7 @@ import com.taobao.weex.performance.WXInstanceApm;
 import com.taobao.weex.tracing.Stopwatch;
 import com.taobao.weex.tracing.WXTracing;
 import com.taobao.weex.ui.IFComponentHolder;
+import com.taobao.weex.ui.WXRenderManager;
 import com.taobao.weex.ui.action.BasicComponentData;
 import com.taobao.weex.ui.action.GraphicActionAnimation;
 import com.taobao.weex.ui.action.GraphicActionUpdateStyle;
@@ -1682,12 +1684,33 @@ public abstract class WXComponent<T extends View> extends WXBasicComponent imple
       getOrCreateBorder().setImage(shader);
     }
   }
+  private boolean shouldCancelHardwareAccelerate() {
+    IWXConfigAdapter adapter = WXSDKManager.getInstance().getWxConfigAdapter();
+    boolean cancel_hardware_accelerate = false;
+    if (adapter != null) {
+      try {
+        cancel_hardware_accelerate = Boolean.parseBoolean(adapter
+                .getConfig("android_weex_test_gpu",
+                        "cancel_hardware_accelerate",
+                        "false"));
+      }catch (Exception e){
+        WXLogUtils.e(WXLogUtils.getStackTrace(e));
+      }
+      WXLogUtils.i("cancel_hardware_accelerate : " + cancel_hardware_accelerate);
+    }
+    return cancel_hardware_accelerate;
+  }
 
   public void setOpacity(float opacity) {
     if (opacity >= 0 && opacity <= 1 && mHost.getAlpha() != opacity) {
+      int limit = WXRenderManager.getOpenGLRenderLimitValue();
       if (isLayerTypeEnabled()) {
         mHost.setLayerType(View.LAYER_TYPE_HARDWARE, null);
       }
+      if(isLayerTypeEnabled() && shouldCancelHardwareAccelerate() && limit > 0 && (getLayoutHeight() > limit ||
+              getLayoutWidth() > limit)){
+        mHost.setLayerType(View.LAYER_TYPE_NONE,null);
+      }
       mHost.setAlpha(opacity);
     }
   }