hwui android,Android bug——hwui中fb socket泄露问题

现象描述:

在launcher的使用过程中,会发现系统越来越慢,内存越来越少,通过adb shell ps -t可以查看到当前launcher开启了几百上千个线程,这样就导致了系统越来越慢。

分析:

通过定位,发现在hwui中,当绘制带阴影的字体的时候,使用了renderScript,由于renderScript中绘制阴影时,会开启3-4个线程来处理阴影文字。

void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int32_t radius) {

#ifdef ANDROID_ENABLE_RENDERSCRIPT

if (width * height * radius >= RS_MIN_INPUT_CUTOFF) {

uint8_t* outImage = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height);

if (mRs == 0) {

mRs = new RSC::RS();

if (!mRs->init(RSC::RS_INIT_LOW_LATENCY | RSC::RS_INIT_SYNCHRONOUS)) {

ALOGE("blur RS failed to init");

}

mRsElement = RSC::Element::A_8(mRs);

mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement);

}

RSC::sp t = RSC::Type::create(mRs, mRsElement, width, height, 0);

RSC::sp<:allocation> ain = RSC::Allocation::createTyped(mRs, t,

RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,

*image);

RSC::sp<:allocation> aout = RSC::Allocation::createTyped(mRs, t,

RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,

outImage);

mRsScript->setRadius(radius);

mRsScript->setInput(ain);

mRsScript->forEach(aout);

// replace the original image's pointer, avoiding a copy back to the original buffer

free(*image);

*image = outImage;

return;

}

#endif当内存不足时,会调用GammaFontRenderer的clear函数,也就是会将当前的FontRenderer对象删除,由于rs对象是以智能指针的形式来使用,所以正常情况在FontRenderer的时候会将当前的rs指针对象都删除,通过写一些测试用例发现,rs使用的智能指针在析构的时候并没有将rs的对象删除,这也就是导致每次创建了rs对象没删除,导致一直会创建大量的线程的原因。

通过查看renderScript的代码,发现rs的对象都是使用强指针引用(sp)的方式来使用:

struct {

sp U8;

sp U8_2;

sp U8_3;

sp U8_4;

…………

sp A_8;

sp RGB_565;

sp RGB_888;

sp RGBA_5551;

sp RGBA_4444;

sp RGBA_8888;

sp YUV;

sp MATRIX_4X4;

sp MATRIX_3X3;

sp MATRIX_2X2;

} mElements;这样导致mRsElement中使用了mRs的强引用,当mRsElement也保存了mRs的强引用,当mRsElement生命周期结束时,由于不等1,所以只能将mRsElement的引用计数减1,mRs还是为2,这样也就会导致最后出现循环引用问题,无法将任何一个对象删除,这就导致了申请的线程没有释放,出现了fb socket泄露的问题。

解决方案:

1. 临时解决方案:

将FontRenderer的rs对象都设置为静态对象,这样就能避免出现socket泄露的问题:

#ifdef ANDROID_ENABLE_RENDERSCRIPT

// RS constructs

static RSC::sp<:rs> mRs;

static RSC::sp mRsElement;

static RSC::sp<:scriptintrinsicblur> mRsScript;

#endif

2. 修改renderScript:

这种修改方式比较麻烦,需要将rs中存在强智能指针的对象都改为普通指针的方式,所幸的是,后面google已经在这方便做了修改,所以可以参考google官网的修改:https://android-review.googlesource.com

你可能感兴趣的:(hwui,android)