Make JNI function for setLocale() call register_localized_collators()
with the current locale, not previous one, every time it is possible.

Add a unit test verifying this fix.

BUG: 2514026
Change-Id: I4dd1b047e1ab4bf399e2c3ebc0304c0cfa3a0928
diff --git a/core/jni/android_database_SQLiteDatabase.cpp b/core/jni/android_database_SQLiteDatabase.cpp
index fb93014..4e8d05b 100644
--- a/core/jni/android_database_SQLiteDatabase.cpp
+++ b/core/jni/android_database_SQLiteDatabase.cpp
@@ -349,7 +349,7 @@
         goto done;
     }
 
-    dbLocale = (rowCount >= 1) ? meta[1 * colCount + 0] : NULL;
+    dbLocale = (rowCount >= 1) ? meta[colCount] : NULL;
 
     if (dbLocale != NULL && !strcmp(dbLocale, locale8)) {
         // database locale is the same as the desired locale; set up the collators and go
@@ -360,7 +360,8 @@
 
     if ((flags & OPEN_READONLY)) {
         // read-only database, so we're going to have to put up with whatever we got
-        err = register_localized_collators(handle, dbLocale ? dbLocale : locale8, UTF16_STORAGE);
+        // For registering new index. Not for modifing the read-only database.
+        err = register_localized_collators(handle, locale8, UTF16_STORAGE);
         if (err != SQLITE_OK) throw_sqlite3_exception(env, handle);
         goto done;
     }
@@ -373,7 +374,7 @@
         goto done;
     }
 
-    err = register_localized_collators(handle, dbLocale ? dbLocale : locale8, UTF16_STORAGE);
+    err = register_localized_collators(handle, locale8, UTF16_STORAGE);
     if (err != SQLITE_OK) {
         LOGE("register_localized_collators() failed setting locale\n");
         throw_sqlite3_exception(env, handle);
diff --git a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
index ab142c9..656029d 100644
--- a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
@@ -16,15 +16,12 @@
 
 package android.database;
 
+import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_COLUMNNAME_INDEX;
+import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_DEFAULT_INDEX;
 import android.content.ContentValues;
 import android.content.Context;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.CharArrayBuffer;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteStatement;
-import android.os.Environment;
 import android.os.Handler;
 import android.os.Parcel;
 import android.test.AndroidTestCase;
@@ -33,18 +30,14 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 
-import java.io.File;
-import java.io.UnsupportedEncodingException;
-import java.text.Collator;
-import java.util.Arrays;
-
 import junit.framework.Assert;
-import junit.framework.TestCase;
 
-import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_COLUMNNAME_INDEX;
-import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_DEFAULT_INDEX;
+import java.io.File;
+import java.util.Arrays;
+import java.util.Locale;
 
 public class DatabaseGeneralTest extends AndroidTestCase implements PerformanceTestCase {
+    private static final String TAG = "DatabaseGeneralTest";
 
     private static final String sString1 = "this is a test";
     private static final String sString2 = "and yet another test";
@@ -1029,4 +1022,91 @@
             fail("unexpected, of course");
         }
     }
+
+    /**
+     * This test is available only when the platform has a locale with the language "ja".
+     * It finishes without failure when it is not available.  
+     */
+    @MediumTest
+    public void testCollateLocalizedForJapanese() throws Exception {
+        final String testName = "DatabaseGeneralTest#testCollateLocalizedForJapanese()";
+        final Locale[] localeArray = Locale.getAvailableLocales();
+        final String japanese = Locale.JAPANESE.getLanguage();
+        final String english = Locale.ENGLISH.getLanguage();
+        Locale japaneseLocale = null;
+        Locale englishLocale = null;
+        for (Locale locale : localeArray) {
+            if (locale != null) {
+                final String language = locale.getLanguage();
+                if (language == null) {
+                    continue;
+                } else if (language.equals(japanese)) {
+                    japaneseLocale = locale;
+                } else if (language.equals(english)) {
+                    englishLocale = locale;
+                }
+            }
+            
+            if (japaneseLocale != null && englishLocale != null) {
+                break;
+            }
+        }
+
+        if (japaneseLocale == null || englishLocale == null) {
+            Log.d(TAG, testName + "n is silently skipped since " +
+                    (englishLocale == null ?
+                            (japaneseLocale == null ?
+                                    "Both English and Japanese locales do not exist." :
+                                    "English locale does not exist.") :
+                            (japaneseLocale == null ?
+                                    "Japanese locale does not exist." :
+                                    "...why?")));
+            return;
+        }
+
+        Locale originalLocale = Locale.getDefault();
+        try {
+
+            final String dbName = "collate_localized_test";
+            mDatabase.execSQL("CREATE TABLE " + dbName + " (" +
+                    "_id INTEGER PRIMARY KEY, " +
+                    "s TEXT COLLATE LOCALIZED) ");
+            DatabaseUtils.InsertHelper ih =
+                new DatabaseUtils.InsertHelper(mDatabase, dbName);
+            ContentValues cv = new ContentValues();
+
+            cv = new ContentValues();  //
+            cv.put("s", "\uFF75\uFF77\uFF85\uFF9C");  // O-ki-na-wa in half-width Katakana
+            ih.insert(cv);
+
+            cv = new ContentValues();  //
+            cv.put("s", "\u306B\u307B\u3093");  // Ni-ho-n in Hiragana
+            ih.insert(cv);
+
+            cv = new ContentValues();  //
+            cv.put("s", "\u30A2\u30E1\u30EA\u30AB");  // A-me-ri-ca in hull-width Katakana
+            ih.insert(cv);            
+
+            // Assume setLocale() does REINDEX and an English locale does not consider
+            // Japanese-specific LOCALIZED order.
+            Locale.setDefault(englishLocale);
+            Locale.setDefault(japaneseLocale);
+
+            Cursor cur = mDatabase.rawQuery(
+                    "SELECT * FROM " + dbName + " ORDER BY s", null);
+            assertTrue(cur.moveToFirst());
+            assertEquals("\u30A2\u30E1\u30EA\u30AB", cur.getString(1));
+            assertTrue(cur.moveToNext());
+            assertEquals("\uFF75\uFF77\uFF85\uFF9C", cur.getString(1));
+            assertTrue(cur.moveToNext());
+            assertEquals("\u306B\u307B\u3093", cur.getString(1));
+        } finally {
+            if (originalLocale != null) {
+                try {
+                    Locale.setDefault(originalLocale);
+                } catch (Exception e) {
+                }
+            }
+        }
+    }    
 }