diff options
author | 2016-01-29 15:54:10 -0800 | |
---|---|---|
committer | 2016-01-29 16:26:35 -0800 | |
commit | c3127a78b996a540cd002e5a87861e8a2adeb336 (patch) | |
tree | cef0dcfda419701814f065aa69660c871938397d | |
parent | f3e5d1d483231d615f5e77032f787fcd8047488b (diff) |
Fix TextDropShadowCache infinite loop
Bug: 26862239
Switch TextDropCacheShadow to use the tracked objectSize()
instead of the optional bitmapSize. A mismatch here
results in ::get() infinite looping trying to free space in
the cache since the LRU removal callback would always
decrement mSize by 0 since bitmapSize was not being set.
Also prevent the infinite loop in the future by crashing if
this scenario happens again.
Change-Id: Ib4e9fbe1c8327af2335ad650fd694a1627d9824f
-rw-r--r-- | libs/hwui/Android.mk | 3 | ||||
-rw-r--r-- | libs/hwui/TextDropShadowCache.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/tests/unit/TextDropShadowCacheTests.cpp | 53 |
3 files changed, 60 insertions, 4 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index fc405541484f..587a366730c2 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -248,7 +248,8 @@ LOCAL_SRC_FILES += \ tests/unit/VectorDrawableTests.cpp \ tests/unit/OffscreenBufferPoolTests.cpp \ tests/unit/StringUtilsTests.cpp \ - tests/unit/BufferPoolTests.cpp + tests/unit/BufferPoolTests.cpp \ + tests/unit/TextDropShadowCacheTests.cpp ifeq (true, $(HWUI_NEW_OPS)) LOCAL_SRC_FILES += \ diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp index 62a20fcfa699..1707468f169d 100644 --- a/libs/hwui/TextDropShadowCache.cpp +++ b/libs/hwui/TextDropShadowCache.cpp @@ -148,7 +148,7 @@ void TextDropShadowCache::setMaxSize(uint32_t maxSize) { void TextDropShadowCache::operator()(ShadowText&, ShadowTexture*& texture) { if (texture) { - mSize -= texture->bitmapSize; + mSize -= texture->objectSize(); if (mDebugEnabled) { ALOGD("Shadow texture deleted, size = %d", texture->bitmapSize); @@ -195,7 +195,9 @@ ShadowTexture* TextDropShadowCache::get(const SkPaint* paint, const char* glyphs // Don't even try to cache a bitmap that's bigger than the cache if (size < mMaxSize) { while (mSize + size > mMaxSize) { - mCache.removeOldest(); + LOG_ALWAYS_FATAL_IF(!mCache.removeOldest(), + "Failed to remove oldest from cache. mSize = %" + PRIu32 ", mCache.size() = %zu", mSize, mCache.size()); } } @@ -212,7 +214,7 @@ ShadowTexture* TextDropShadowCache::get(const SkPaint* paint, const char* glyphs entry.copyTextLocally(); - mSize += size; + mSize += texture->objectSize(); mCache.put(entry, texture); } else { texture->cleanup = true; diff --git a/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp new file mode 100644 index 000000000000..c54f2c365ee2 --- /dev/null +++ b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed 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. + */ + +#include <gtest/gtest.h> + +#include "GammaFontRenderer.h" +#include "TextDropShadowCache.h" +#include "utils/Blur.h" +#include "tests/common/TestUtils.h" + +#include <SkBlurDrawLooper.h> +#include <SkPaint.h> + +using namespace android; +using namespace android::uirenderer; + +RENDERTHREAD_TEST(TextDropShadowCache, addRemove) { + GammaFontRenderer gammaFontRenderer; + FontRenderer& fontRenderer = gammaFontRenderer.getFontRenderer(); + TextDropShadowCache cache(5000); + cache.setFontRenderer(fontRenderer); + + SkPaint paint; + paint.setLooper(SkBlurDrawLooper::Create((SkColor)0xFFFFFFFF, + Blur::convertRadiusToSigma(10), 10, 10))->unref(); + std::string msg("This is a test"); + std::unique_ptr<float[]> positions(new float[msg.length()]); + for (size_t i = 0; i < msg.length(); i++) { + positions[i] = i * 10.0f; + } + fontRenderer.setFont(&paint, SkMatrix::I()); + ShadowTexture* texture = cache.get(&paint, msg.c_str(), msg.length(), + 10.0f, positions.get()); + ASSERT_TRUE(texture); + ASSERT_FALSE(texture->cleanup); + ASSERT_EQ((uint32_t) texture->objectSize(), cache.getSize()); + ASSERT_TRUE(cache.getSize()); + cache.clear(); + ASSERT_EQ(cache.getSize(), 0u); +} |