Correctly compare strings in UTF-8 instead of UTF-16
Bug #3272858

Change-Id: Idacd5d7c2c052b4834a8ddb5906ab32b3f548f73
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index 951fba3..62d0ce1 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -19,6 +19,7 @@
 
 #include <utils/KeyedVector.h>
 
+#include "utils/Compare.h"
 #include "Debug.h"
 #include "Patch.h"
 
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index ac91769..c474936 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -39,7 +39,8 @@
 enum DebugLevel {
     kDebugDisabled = 0,
     kDebugMemory = 1,
-    kDebugCaches = 2
+    kDebugCaches = 2,
+    kDebugMoreCaches = 3
 };
 
 // These properties are defined in mega-bytes
diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp
index 2f7c7be..d96a7f5 100644
--- a/libs/hwui/TextDropShadowCache.cpp
+++ b/libs/hwui/TextDropShadowCache.cpp
@@ -37,19 +37,24 @@
         LOGD("  Using default drop shadow cache size of %.2fMB", DEFAULT_DROP_SHADOW_CACHE_SIZE);
     }
 
-    mCache.setOnEntryRemovedListener(this);
+    init();
 }
 
 TextDropShadowCache::TextDropShadowCache(uint32_t maxByteSize):
         mCache(GenerationCache<ShadowText, ShadowTexture*>::kUnlimitedCapacity),
         mSize(0), mMaxSize(maxByteSize) {
-    mCache.setOnEntryRemovedListener(this);
+    init();
 }
 
 TextDropShadowCache::~TextDropShadowCache() {
     mCache.clear();
 }
 
+void TextDropShadowCache::init() {
+    mCache.setOnEntryRemovedListener(this);
+    mDebugEnabled = readDebugLevel() & kDebugMoreCaches;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Size management
 ///////////////////////////////////////////////////////////////////////////////
@@ -75,8 +80,11 @@
 
 void TextDropShadowCache::operator()(ShadowText& text, ShadowTexture*& texture) {
     if (texture) {
-        const uint32_t size = texture->width * texture->height;
-        mSize -= size;
+        mSize -= texture->bitmapSize;
+
+        if (mDebugEnabled) {
+            LOGD("Shadow texture deleted, size = %d", texture->bitmapSize);
+        }
 
         glDeleteTextures(1, &texture->id);
         delete texture;
@@ -109,6 +117,8 @@
         texture->blend = true;
 
         const uint32_t size = shadow.width * shadow.height;
+        texture->bitmapSize = size;
+
         // Don't even try to cache a bitmap that's bigger than the cache
         if (size < mMaxSize) {
             while (mSize + size > mMaxSize) {
@@ -132,6 +142,9 @@
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
         if (size < mMaxSize) {
+            if (mDebugEnabled) {
+                LOGD("Shadow texture created, size = %d", texture->bitmapSize);
+            }
             mSize += size;
             mCache.put(entry, texture);
         } else {
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index adf09e2..8cefc8c 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -21,6 +21,9 @@
 
 #include <SkPaint.h>
 
+#include <utils/String8.h>
+
+#include "utils/Compare.h"
 #include "utils/GenerationCache.h"
 #include "FontRenderer.h"
 #include "Texture.h"
@@ -29,20 +32,20 @@
 namespace uirenderer {
 
 struct ShadowText {
-    ShadowText() {
-        text = NULL;
+    ShadowText(): radius(0), len(0), hash(0), textSize(0.0f), typeface(NULL) {
     }
 
     ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText):
             radius(radius), len(len) {
-        text = new char[len];
-        memcpy(text, srcText, len);
+        // The source text we receive is in UTF-16, convert to UTF-8
+        str.setTo((const char16_t*) srcText, len >> 1);
 
         textSize = paint->getTextSize();
         typeface = paint->getTypeface();
 
         hash = 0;
         uint32_t multiplier = 1;
+        const char* text = str.string();
         for (uint32_t i = 0; i < len; i++) {
             hash += text[i] * multiplier;
             uint32_t shifted = multiplier << 5;
@@ -52,13 +55,10 @@
 
     ShadowText(const ShadowText& shadow):
             radius(shadow.radius), len(shadow.len), hash(shadow.hash),
-            textSize(shadow.textSize), typeface(shadow.typeface) {
-        text = new char[shadow.len];
-        memcpy(text, shadow.text, shadow.len);
+            textSize(shadow.textSize), typeface(shadow.typeface), str(shadow.str) {
     }
 
     ~ShadowText() {
-        delete[] text;
     }
 
     uint32_t radius;
@@ -66,20 +66,16 @@
     uint32_t hash;
     float textSize;
     SkTypeface* typeface;
-    char *text;
+    String8 str;
 
     bool operator<(const ShadowText& rhs) const {
-        if (hash < rhs.hash) return true;
-        else if (hash == rhs.hash) {
-            if (len < rhs.len) return true;
-            else if (len == rhs.len) {
-                if (radius < rhs.radius) return true;
-                else if (radius == rhs.radius) {
-                    if (textSize < rhs.textSize) return true;
-                    else if (textSize == rhs.textSize) {
+        LTE_INT(hash) {
+            LTE_INT(len) {
+                LTE_INT(radius) {
+                    LTE_FLOAT(textSize) {
                         if (typeface < rhs.typeface) return true;
                         else if (typeface == rhs.typeface) {
-                            return strncmp(text, rhs.text, len) < 0;
+                            return str.compare(rhs.str) < 0;
                         }
                     }
                 }
@@ -138,11 +134,14 @@
     uint32_t getSize();
 
 private:
+    void init();
+
     GenerationCache<ShadowText, ShadowTexture*> mCache;
 
     uint32_t mSize;
     uint32_t mMaxSize;
     FontRenderer* mRenderer;
+    bool mDebugEnabled;
 }; // class TextDropShadowCache
 
 }; // namespace uirenderer