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

luckychen 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 5e8d9ac  [Android] Fix Crash in NotifyLayout (#2902)
5e8d9ac is described below

commit 5e8d9ac935d6fbadd2469d83540426cc30b4e676
Author: YorkShen <shenyua...@gmail.com>
AuthorDate: Mon Sep 16 16:20:43 2019 +0800

    [Android] Fix Crash in NotifyLayout (#2902)
    
    There is a concurrent read/write operation to `RenderManager::pages_` 
during `CoreSideInPlatform::NotifyLayout`where MainThread is reading 
`RenderManager::pages_` while other thread may be writing to it.
    
    ```
    std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, 
std::__ndk1::allocator<char> >::__is_long() const at string:1266
     (inlined by) std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >::size() const at 
string:905
     (inlined by) std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> 
>::compare(std::__ndk1::basic_string_view<char, std::__ndk1::char_traits<char> 
>) const at string:3455
     (inlined by) std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> 
>::compare(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, 
std::__ndk1::allocator<char> > const&) const at string:3473
     (inlined by) bool std::__ndk1::operator< <char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> 
>(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, 
std::__ndk1::allocator<char> > const&, std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&) at 
string:3693
     (inlined by) std::__ndk1::less<std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > 
>::operator()(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, 
std::__ndk1::allocator<char> > const&, std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&) const at 
__functional_base:55
     (inlined by) 
std::__ndk1::__map_value_compare<std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, 
std::__ndk1::__value_type<std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, 
WeexCore::RenderPageBase*>, std::__ndk1::less<std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >, 
true>::operator()(std::__ndk1::__value_type<std::__ndk1::basic_string<char, 
std: [...]
     (inlined by) 
std::__ndk1::__tree_iterator<std::__ndk1::__value_type<std::__ndk1::basic_string<char,
 std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, 
WeexCore::RenderPageBase*>, 
std::__ndk1::__tree_node<std::__ndk1::__value_type<std::__ndk1::basic_string<char,
 std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, 
WeexCore::RenderPageBase*>, void*>*, int> 
std::__ndk1::__tree<std::__ndk1::__value_type<std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char [...]
    
std::__ndk1::__tree_iterator<std::__ndk1::__value_type<std::__ndk1::basic_string<char,
 std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, 
WeexCore::RenderPageBase*>, 
std::__ndk1::__tree_node<std::__ndk1::__value_type<std::__ndk1::basic_string<char,
 std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, 
WeexCore::RenderPageBase*>, void*>*, int> 
std::__ndk1::__tree<std::__ndk1::__value_type<std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1 [...]
    std::__ndk1::map<std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, 
WeexCore::RenderPageBase*, std::__ndk1::less<std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >, 
std::__ndk1::allocator<std::__ndk1::pair<std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const, 
WeexCore::RenderPageBase*> > >::find(std::__ndk1::basic_string<char, 
std::__ndk1::char_tra [...]
     (inlined by) 
WeexCore::RenderManager::GetPage(std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&) at 
render_manager.cpp:472
    WeexCore::CoreSideInPlatform::NotifyLayout(std::__ndk1::basic_string<char, 
std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&) at 
core_side_in_platform.cpp:223
    ```
---
 .../java/com/taobao/weex/WeexFrameRateControl.java | 52 ++++++++++++----------
 .../com/taobao/weex/bridge/WXBridgeManager.java    |  6 +--
 2 files changed, 32 insertions(+), 26 deletions(-)

diff --git 
a/android/sdk/src/main/java/com/taobao/weex/WeexFrameRateControl.java 
b/android/sdk/src/main/java/com/taobao/weex/WeexFrameRateControl.java
index eef4d5c..14817fd 100644
--- a/android/sdk/src/main/java/com/taobao/weex/WeexFrameRateControl.java
+++ b/android/sdk/src/main/java/com/taobao/weex/WeexFrameRateControl.java
@@ -26,14 +26,15 @@ import android.annotation.SuppressLint;
 import android.os.Build;
 import android.util.Log;
 import android.view.Choreographer;
+import com.taobao.weex.bridge.WXBridgeManager;
 import com.taobao.weex.common.WXErrorCode;
 import java.lang.ref.WeakReference;
 
 public class WeexFrameRateControl {
     private static final long VSYNC_FRAME = 1000 / 60;
     private WeakReference<VSyncListener> mListener;
-    private final Choreographer mChoreographer;
-    private final Choreographer.FrameCallback mVSyncFrameCallback;
+    private Choreographer mChoreographer;
+    private Choreographer.FrameCallback mVSyncFrameCallback;
     private final Runnable runnable;
 
     public interface VSyncListener {
@@ -43,27 +44,32 @@ public class WeexFrameRateControl {
     public WeexFrameRateControl(VSyncListener listener) {
         mListener = new WeakReference<>(listener);
         if (Build.VERSION.SDK_INT > 
Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
-            mChoreographer = Choreographer.getInstance();
-            mVSyncFrameCallback = new Choreographer.FrameCallback() {
-                @SuppressLint("NewApi")
-                @Override
-                public void doFrame(long frameTimeNanos) {
-                    VSyncListener vSyncListener;
-                    if (mListener != null && (vSyncListener=mListener.get()) 
!= null) {
-                        try {
-                            vSyncListener.OnVSync();
-                            
mChoreographer.postFrameCallback(mVSyncFrameCallback);
-                        }catch (UnsatisfiedLinkError e){
-                            if(vSyncListener instanceof WXSDKInstance){
-                                ((WXSDKInstance) vSyncListener).onRenderError(
-                                    
WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(),
-                                    Log.getStackTraceString(e));
-                            }
-                        }
-                    }
-                }
-            };
-            runnable = null;
+          WXBridgeManager.getInstance().post(new Runnable() {
+              @Override
+              public void run() {
+                  mChoreographer = Choreographer.getInstance();
+                  mVSyncFrameCallback = new Choreographer.FrameCallback() {
+                      @SuppressLint("NewApi")
+                      @Override
+                      public void doFrame(long frameTimeNanos) {
+                          VSyncListener vSyncListener;
+                          if (mListener != null && 
(vSyncListener=mListener.get()) != null) {
+                              try {
+                                  vSyncListener.OnVSync();
+                                  
mChoreographer.postFrameCallback(mVSyncFrameCallback);
+                              }catch (UnsatisfiedLinkError e){
+                                  if(vSyncListener instanceof WXSDKInstance){
+                                      ((WXSDKInstance) 
vSyncListener).onRenderError(
+                                          
WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(),
+                                          Log.getStackTraceString(e));
+                                  }
+                              }
+                          }
+                      }
+                  };
+              }
+          });
+          runnable = null;
         } else {
             // For API 15 or lower
             runnable = new Runnable() {
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 8c31da1..ccbb45f 100755
--- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
@@ -31,7 +31,7 @@ import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 import android.support.annotation.RestrictTo.Scope;
-import android.support.annotation.UiThread;
+import android.support.annotation.WorkerThread;
 import android.support.v4.util.ArrayMap;
 import android.text.TextUtils;
 import android.util.Log;
@@ -3449,7 +3449,7 @@ public class WXBridgeManager implements Callback, 
BactchExecutor {
    * @param instanceId
    * @return
    */
-  @UiThread
+  @WorkerThread
   public boolean notifyLayout(String instanceId) {
     if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
       return mWXBridge.notifyLayout(instanceId);
@@ -3457,7 +3457,7 @@ public class WXBridgeManager implements Callback, 
BactchExecutor {
     return false;
   }
 
-  @UiThread
+  @WorkerThread
   public void forceLayout(String instanceId) {
     if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) {
       mWXBridge.forceLayout(instanceId);

Reply via email to