三星GS4(android 4.3)上webview crash问题

最近发现客户端中android4.3上GS4手机上的WebApp应用特别容易crash。分析了源代码之后发现,在ActivityThread中回收内存时会调用EGLImpl里边去,回收RenderThread,进而调用到计算CPU FPS的逻辑,进而crash:

java.lang.Error: signal 11 (Address not mapped to object) at address 0xbe59dff0 [at libPowerStretch.so:0x2d4c (_ZN11LucidConfig13calcTargetFPSEi+0x1b)]
at system.lib.libPowerStretch_so.0x2d4c(LucidConfig::calcTargetFPS(int):0x1b:0)
at system.lib.libPowerStretch_so.0x2f23(LucidConfig::isLucidActive(bool):0x86:0)

因为在问题出在系统层而android应用回收内存这个message是ActivityManager发出,为正常且必要的行为,无法规避。最终选择如下方式将其绕过:

public class H5WebViewRenderPolicy {
public static boolean shouldDisableHardwareRenderInLayer() {
// case 1: samsung GS4 on android 4.3 is know to cause crashes at libPowerStretch.so:0x2d4c
// use GT-I95xx to match more GS4 series devices though GT-I9500 is the typical device
final boolean isSamsungGs4 = android.os.Build.MODEL != null && android.os.Build.MODEL.contains("GT-I95") && android.os.Build.MANUFACTURER != null && android.os.Build.MANUFACTURER.equals("samsung");
final boolean isJbMr2 = Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR2;
if (isSamsungGs4 && isJbMr2) {
return true;
}
return false;
}
}

以上定义一个渲染策略类(方便以后维护),针对GS4 + android 4.3这种组合在WebView layer层面关闭硬件加速(这样就不会存在RenderThread,自然也就没法触发上文的crash)。

之后在自定义WebView中利用上以上渲染策略类:

final boolean meetApiLevel11 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
if (H5WebViewRenderPolicy.shouldDisableHardwareRenderInLayer() && meetApiLevel11) {
final View underlyingWebView = webView.getUnderlyingWebView();
if (underlyingWebView != null && webView.getType().equals(WebViewType.SYSTEM_BUILD_IN)) {
try {
underlyingWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
} catch (Exception globalException) {
globalException.printStackTrace();
}
}
}

更新 2015/2/1

该现象表现在多款三星制造的搭载android 4.3系统的手机上,不仅限于GS4