Fix bug #6408393 Character corruption is caused when locale is changed

- free the TextLayoutCache on Locale change

- also free TextLayoutCache when memory is low

Change-Id: I39a37ac8ec3c292cfb1c0eea4bb41ff71897d089
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b55ee26..e53438c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2639,6 +2639,7 @@
                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
                             + r.activityInfo.name + " with newConfig " + r.newConfig);
                     performConfigurationChanged(r.activity, r.newConfig);
+                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
                     r.newConfig = null;
                 }
                 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
@@ -2955,6 +2956,7 @@
                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
                             + r.activityInfo.name + " with new config " + r.newConfig);
                     performConfigurationChanged(r.activity, r.newConfig);
+                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
                     r.newConfig = null;
                 }
             } else {
@@ -3669,6 +3671,7 @@
     final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
 
         ArrayList<ComponentCallbacks2> callbacks = null;
+        int configDiff = 0;
 
         synchronized (mPackages) {
             if (mPendingConfiguration != null) {
@@ -3693,6 +3696,7 @@
             if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
                 return;
             }
+            configDiff = mConfiguration.diff(config);
             mConfiguration.updateFrom(config);
             config = applyCompatConfiguration();
             callbacks = collectComponentCallbacksLocked(false, config);
@@ -3701,6 +3705,8 @@
         // Cleanup hardware accelerated stuff
         WindowManagerImpl.getDefault().trimLocalMemory();
 
+        freeTextLayoutCachesIfNeeded(configDiff);
+
         if (callbacks != null) {
             final int N = callbacks.size();
             for (int i=0; i<N; i++) {
@@ -3709,6 +3715,17 @@
         }
     }
 
+    final void freeTextLayoutCachesIfNeeded(int configDiff) {
+        if (configDiff != 0) {
+            // Ask text layout engine to free its caches if there is a locale change
+            boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
+            if (hasLocaleConfigChange) {
+                Canvas.freeTextLayoutCaches();
+                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches");
+            }
+        }
+    }
+
     final void handleActivityConfigurationChanged(IBinder token) {
         ActivityClientRecord r = mActivities.get(token);
         if (r == null || r.activity == null) {
@@ -3719,6 +3736,8 @@
                 + r.activityInfo.name);
         
         performConfigurationChanged(r.activity, mCompatConfiguration);
+
+        freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(mCompatConfiguration));
     }
 
     final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) {
@@ -3821,6 +3840,9 @@
         // Ask graphics to free up as much as possible (font/image caches)
         Canvas.freeCaches();
 
+        // Ask text layout engine to free also as much as possible
+        Canvas.freeTextLayoutCaches();
+
         BinderInternal.forceGc("mem");
     }