Merge "Return Olson ids from TimeZoneNames.forLocale in zone.tab order."
diff --git a/luni/src/main/java/libcore/icu/TimeZoneNames.java b/luni/src/main/java/libcore/icu/TimeZoneNames.java
index e71ec61..65ada89 100644
--- a/luni/src/main/java/libcore/icu/TimeZoneNames.java
+++ b/luni/src/main/java/libcore/icu/TimeZoneNames.java
@@ -16,12 +16,14 @@
 
 package libcore.icu;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.TimeZone;
 import libcore.util.BasicLruCache;
+import libcore.util.ZoneInfoDB;
 
 /**
  * Provides access to ICU's time zone name data.
@@ -140,12 +142,22 @@
     /**
      * Returns an array containing the time zone ids in use in the country corresponding to
      * the given locale. This is not necessary for Java API, but is used by telephony as a
-     * fallback.
+     * fallback. We retrieve these strings from zone.tab rather than icu4c because the latter
+     * supplies them in alphabetical order where zone.tab has them in a kind of "importance"
+     * order (as defined in the zone.tab header).
      */
     public static String[] forLocale(Locale locale) {
-        return forCountryCode(locale.getCountry());
+        String countryCode = locale.getCountry();
+        ArrayList<String> ids = new ArrayList<String>();
+        for (String line : ZoneInfoDB.getZoneTab().split("\n")) {
+            if (line.startsWith(countryCode)) {
+                int olsonIdStart = line.indexOf('\t', 4) + 1;
+                int olsonIdEnd = line.indexOf('\t', olsonIdStart);
+                ids.add(line.substring(olsonIdStart, olsonIdEnd));
+            }
+        }
+        return ids.toArray(new String[ids.size()]);
     }
 
-    private static native String[] forCountryCode(String countryCode);
     private static native void fillZoneStrings(String locale, String[][] result);
 }
diff --git a/luni/src/main/java/libcore/util/ZoneInfoDB.java b/luni/src/main/java/libcore/util/ZoneInfoDB.java
index 2bf55ce..b211c93 100644
--- a/luni/src/main/java/libcore/util/ZoneInfoDB.java
+++ b/luni/src/main/java/libcore/util/ZoneInfoDB.java
@@ -55,6 +55,7 @@
     private static final MemoryMappedFile TZDATA = mapData();
 
     private static String version;
+    private static String zoneTab;
 
     /**
      * The 'ids' array contains time zone ids sorted alphabetically, for binary searching.
@@ -92,6 +93,7 @@
         int zonetab_offset = it.readInt();
 
         readIndex(it, index_offset, data_offset);
+        readZoneTab(it, zonetab_offset);
     }
 
     private static MemoryMappedFile mapData() {
@@ -113,6 +115,13 @@
         }
     }
 
+    private static void readZoneTab(BufferIterator it, int zoneTabOffset) {
+        byte[] bytes = new byte[(int) TZDATA.size() - zoneTabOffset];
+        it.seek(zoneTabOffset);
+        it.readByteArray(bytes, 0, bytes.length);
+        zoneTab = new String(bytes, 0, bytes.length, Charsets.US_ASCII);
+    }
+
     private static void readIndex(BufferIterator it, int indexOffset, int dataOffset) {
         it.seek(indexOffset);
 
@@ -211,4 +220,8 @@
     public static String getVersion() {
         return version;
     }
+
+    public static String getZoneTab() {
+        return zoneTab;
+    }
 }
diff --git a/luni/src/main/native/libcore_icu_TimeZoneNames.cpp b/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
index 8e777f7..8c8682a 100644
--- a/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
+++ b/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
@@ -28,14 +28,6 @@
 #include "unicode/timezone.h"
 #include "unicode/tznames.h"
 
-static jobjectArray TimeZoneNames_forCountryCode(JNIEnv* env, jclass, jstring countryCode) {
-  ScopedUtfChars countryChars(env, countryCode);
-  if (countryChars.c_str() == NULL) {
-    return NULL;
-  }
-  return fromStringEnumeration(env, TimeZone::createEnumeration(countryChars.c_str()));
-}
-
 static bool isUtc(const UnicodeString& id) {
   static const UnicodeString kEtcUct("Etc/UCT", 7, US_INV);
   static const UnicodeString kEtcUtc("Etc/UTC", 7, US_INV);
@@ -119,7 +111,6 @@
 }
 
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(TimeZoneNames, forCountryCode, "(Ljava/lang/String;)[Ljava/lang/String;"),
   NATIVE_METHOD(TimeZoneNames, fillZoneStrings, "(Ljava/lang/String;[[Ljava/lang/String;)V"),
 };
 void register_libcore_icu_TimeZoneNames(JNIEnv* env) {
diff --git a/luni/src/test/java/libcore/icu/TimeZoneNamesTest.java b/luni/src/test/java/libcore/icu/TimeZoneNamesTest.java
new file mode 100644
index 0000000..da8e035
--- /dev/null
+++ b/luni/src/test/java/libcore/icu/TimeZoneNamesTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package libcore.icu;
+
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.HashSet;
+import java.util.TimeZone;
+
+public class TimeZoneNamesTest extends junit.framework.TestCase {
+  public void test_forLocale() throws Exception {
+    String[] ids = TimeZoneNames.forLocale(Locale.CANADA);
+    // Check that we got some ids.
+    assertTrue(ids.length > 0);
+    HashSet<String> allIds = new HashSet<String>(Arrays.asList(TimeZone.getAvailableIDs()));
+    // Check that they're all real.
+    for (String id : ids) {
+      assertTrue(allIds.contains(id));
+    }
+    // Check that Toronto comes before Atikokan. http://b/8391426.
+    int toronto = linearSearch(ids, "America/Toronto");
+    assertTrue(toronto >= 0);
+    int atikokan = linearSearch(ids, "America/Atikokan");
+    assertTrue(atikokan >= 0);
+    assertTrue(toronto < atikokan);
+  }
+
+  private int linearSearch(String[] xs, String x) {
+    for (int i = 0; i < xs.length; ++i) {
+      if (xs[i].equals(x)) {
+        return i;
+      }
+    }
+    return -1;
+  }
+}