Added code to allow for time zone name substitution in the app.

Disabled search by time zone
Sort by actual offset (respects DST) then country, then name
Dropped TZs without country. They are usually dups and since we don't search by tz name, they are hard to find.
Move Sydney above Hobart, Australia
Moved Adelaide above Broken Hill, Australia
Moved Dawson_Creek above Creston, Canada
Updated string descriptions

Bug: 7157738

Change-Id: I0320a002d5267633fe581dfc8cd636ba6e689bc0
diff --git a/assets/zone.tab b/assets/zone.tab
index 6bda826..44bbc4c 100644
--- a/assets/zone.tab
+++ b/assets/zone.tab
@@ -57,15 +57,15 @@
 AR	-5448-06818	America/Argentina/Ushuaia	Tierra del Fuego (TF)
 AS	-1416-17042	Pacific/Pago_Pago
 AT	+4813+01620	Europe/Vienna
+AU	-3352+15113	Australia/Sydney	New South Wales - most locations
+AU	-3455+13835	Australia/Adelaide	South Australia
 AU	-3133+15905	Australia/Lord_Howe	Lord Howe Island
 AU	-4253+14719	Australia/Hobart	Tasmania - most locations
 AU	-3956+14352	Australia/Currie	Tasmania - King Island
 AU	-3749+14458	Australia/Melbourne	Victoria
-AU	-3352+15113	Australia/Sydney	New South Wales - most locations
 AU	-3157+14127	Australia/Broken_Hill	New South Wales - Yancowinna
 AU	-2728+15302	Australia/Brisbane	Queensland - most locations
 AU	-2016+14900	Australia/Lindeman	Queensland - Holiday Islands
-AU	-3455+13835	Australia/Adelaide	South Australia
 AU	-1228+13050	Australia/Darwin	Northern Territory
 AU	-3157+11551	Australia/Perth	Western Australia - most locations
 AU	-3143+12852	Australia/Eucla	Western Australia - Eucla area
@@ -130,8 +130,8 @@
 CA	+690650-1050310	America/Cambridge_Bay	Mountain Time - west Nunavut
 CA	+6227-11421	America/Yellowknife	Mountain Time - central Northwest Territories
 CA	+682059-1334300	America/Inuvik	Mountain Time - west Northwest Territories
-CA	+4906-11631	America/Creston	Mountain Standard Time - Creston, British Columbia
 CA	+5946-12014	America/Dawson_Creek	Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia
+CA	+4906-11631	America/Creston	Mountain Standard Time - Creston, British Columbia
 CA	+4916-12307	America/Vancouver	Pacific Time - west British Columbia
 CA	+6043-13503	America/Whitehorse	Pacific Time - south Yukon
 CA	+6404-13925	America/Dawson	Pacific Time - north Yukon
diff --git a/res/layout/timezonepickerview.xml b/res/layout/timezonepickerview.xml
index 771223a..204b69d 100644
--- a/res/layout/timezonepickerview.xml
+++ b/res/layout/timezonepickerview.xml
@@ -20,10 +20,12 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:minHeight="400dp"
+    android:minWidth="300dp"
     android:orientation="vertical" >
 
     <AutoCompleteTextView
         android:id="@+id/searchBox"
+        style="@style/font_family_thin"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="8dp"
@@ -53,7 +55,7 @@
 
     <TextView
         style="@style/font_family_thin"
-        android:layout_width="wrap_content"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:background="#FFECECEC"
         android:ellipsize="marquee"
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
new file mode 100644
index 0000000..56e6564
--- /dev/null
+++ b/res/values/arrays.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<resources>
+
+    <!--
+        Timezone IDs for the time zones that we want to override the display strings.
+        ALWAYS ADD NEW ENTRIES AT THE END. Othewise the entries after the insertion point will
+        not match for languages that didn't get the translations.
+    -->
+    <string-array name="timezone_rename_ids" translatable="false">
+
+        <!-- Australia -->
+        <item>"Australia/Darwin"</item>
+        <item>"Australia/Adelaide"</item>
+        <item>"Australia/Brisbane"</item>
+        <item>"Australia/Sydney"</item>
+
+        <!-- Canada -->
+        <!-- Non DST version -->
+        <item>"America/Dawson_Creek"</item>
+        <!-- Non DST version -->
+        <item>"America/Regina"</item>
+        <!-- Non DST version -->
+        <item>"America/Atikokan"</item>
+        <!-- Non DST version -->
+        <item>"America/Blanc-Sablon"</item>
+
+        <!-- US -->
+        <!-- Non DST version -->
+        <item>"Pacific/Honolulu"</item>
+        <!-- DST version -->
+        <item>"America/Adak"</item>
+        <!-- Non DST version -->
+        <item>"America/Metlakatla"</item>
+        <!-- Non DST version -->
+        <item>"America/Phoenix"</item>
+
+        <!-- Mexico -->
+        <!-- DST version with post-2006 US rule -->
+        <item>"America/Tijuana"</item>
+        <!-- DST version with post-2006 US rule -->
+        <item>"America/Ojinaga"</item>
+        <!-- DST version with post-2006 US rule -->
+        <item>"America/Matamoros"</item>
+        <!-- Non DST version -->
+        <item>"America/Hermosillo"</item>
+
+        <!-- Other time zones with missing labels from the framework -->
+        <!-- Missing string in ICS -->
+        <item>"Africa/Juba"</item>
+        <!-- Missing string in ICS -->
+        <item>"America/Kralendijk"</item>
+        <!-- Missing string in ICS -->
+        <item>"America/Lower_Princes"</item>
+        <!-- Only had GMT as the display string -->
+        <item>"Europe/Minsk"</item>
+        <!-- Only had GMT as the display string -->
+        <item>"Europe/Kaliningrad"</item>
+    </string-array>
+
+    <!--
+        Replacement display strings for time zones. The order should match the entries in
+        timezone_rename_ids
+        ALWAYS ADD NEW ENTRIES AT THE END. Othewise the array will not be the same size until
+        all the translations are available. [CHAR LIMIT=32]
+    -->
+    <string-array name="timezone_rename_labels">
+
+        <!-- Australia -->
+        <item>"Australian Central - NT"</item>
+        <item>"Australian Central - SA"</item>
+        <item>"Australian Eastern - QLD"</item>
+        <item>"Australian Eastern - NSW"</item>
+
+        <!-- Canada -->
+        <item>"Mountain Standard - Dawson Creek"</item>
+        <item>"Central Standard - Saskatchewan"</item>
+        <item>"Eastern Standard - Atikokan"</item>
+        <item>"Atlantic Standard - Quebec"</item>
+
+        <!-- US -->
+        <item>"Hawaii-Aleutian - Hawaii"</item>
+        <item>"Hawaii-Aleutian - Alaska"</item>
+        <item>"Pacific Standard - Metlakatla"</item>
+        <item>"Mountain Standard - Arizona"</item>
+
+        <!-- Mexico -->
+        <item>"Pacific - Baja California"</item>
+        <item>"Mountain - Chihuahua"</item>
+        <item>"Central - Tamaulipas"</item>
+        <item>"Mountain - Sonora"</item>
+
+        <!-- Other countries with missing or undesirable labels from the framework -->
+        <item>"East Africa Time"</item>
+        <item>"Atlantic Standard Time"</item>
+        <item>"Atlantic Standard Time"</item>
+        <item>"Eastern European Time"</item>
+        <item>"Kaliningrad Time"</item>
+    </string-array>
+
+</resources>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c24e707..b7d21da 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -16,20 +16,43 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <string name="hint_time_zone_search">Country, time zone, or time</string>
+    <!-- Hint text to encourage the user to enter a country name to find a time zone
+     [CHAR LIMIT=25] -->
+    <string name="hint_time_zone_search">Country</string>
 
+    <!-- Label for the currently selected time zone [CHAR LIMIT=25] -->
     <string name="currenttime_zone">CURRENT TIME ZONE</string>
-    <string name="recent_time_zone">RECENT TIME ZONES</string>
 
-    <string name="country">Countries</string>
+    <!-- Label for the recently selected time zones [CHAR LIMIT=25] -->
+    <plurals name="recent_time_zone">
+        <item quantity="one">RECENT TIME ZONE</item>
+        <!-- This is the label for 2 or more time zones. -->
+        <item quantity="other">RECENT TIME ZONES</item>
+    </plurals>
+
+    <!-- Label for a list of time zones searched by country name [CHAR LIMIT=30] -->
+    <string name="country">Country</string>
+
+    <!-- Label for a list of time zones searched by time zone name [CHAR LIMIT=30] -->
     <string name="time_zone">Time zones</string>
+
+    <!-- Label for a list of time zones searched by GMT Offset [CHAR LIMIT=30] -->
     <string name="gmt_offset">GMT offset</string>
+
+    <!-- Label for a list of time zones searched by the hour of the local time [CHAR LIMIT=30] -->
     <string name="local_time">Local time (hr)</string>
 
+    <!-- Label for a list of time zones in country [CHAR LIMIT=25] -->
     <string name="results_country">"TIME ZONES IN <xliff:g id="country">%s</xliff:g>"</string>
+
+    <!-- Label for a list of time zones with a certain GMT offset [CHAR LIMIT=25] -->
     <string name="results_gmt">"TIME ZONES IN GMT <xliff:g id="offset">%s</xliff:g>"</string>
+
+    <!-- Label for a list of time zones in a certain hour of the day [CHAR LIMIT=25] -->
     <string name="results_local_type">"TIME ZONES AT <xliff:g id="local_time">%s</xliff:g>"</string>
 
-    <string name="dst_note">\u2600 Time zone observes daylight saving time</string>
+    <!-- Legend for the * symbol to mean that the time zone has
+     a future day light savings time [CHAR LIMIT=30] -->
+    <string name="dst_note">\u2600 Observes daylight saving time</string>
 
 </resources>
\ No newline at end of file
diff --git a/src/com/android/timezonepicker/TimeZoneData.java b/src/com/android/timezonepicker/TimeZoneData.java
index 115a8b8..a0cfa4b 100644
--- a/src/com/android/timezonepicker/TimeZoneData.java
+++ b/src/com/android/timezonepicker/TimeZoneData.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.res.AssetManager;
+import android.content.res.Resources;
 import android.text.format.DateFormat;
 import android.text.format.DateUtils;
 import android.util.Log;
@@ -53,8 +54,13 @@
     private TimeZoneInfo mDefaultTimeZoneInfo;
     private String mAlternateDefaultTimeZoneId;
     private String mDefaultTimeZoneCountry;
+    private HashMap<String, TimeZoneInfo> mTimeZonesById;
+    private boolean[] mHasTimeZonesInHrOffset = new boolean[40];
+    SparseArray<ArrayList<Integer>> mTimeZonesByOffsets;
+    private Context mContext;
 
     public TimeZoneData(Context context, String defaultTimeZoneId, long timeMillis) {
+        mContext = context;
         is24HourFormat = TimeZoneInfo.is24HourFormat = DateFormat.is24HourFormat(context);
         mDefaultTimeZoneId = mAlternateDefaultTimeZoneId = defaultTimeZoneId;
         long now = System.currentTimeMillis();
@@ -65,6 +71,7 @@
             mTimeMillis = timeMillis;
         }
         loadTzs(context);
+
         Log.i(TAG, "Time to load time zones (ms): " + (System.currentTimeMillis() - now));
 
         // now = System.currentTimeMillis();
@@ -115,6 +122,16 @@
                 continue;
             }
 
+            /*
+             * Dropping non-GMT tzs without a country code. They are not
+             * really needed and they are dups but missing proper
+             * country codes. e.g. WET CET MST7MDT PST8PDT Asia/Khandyga
+             * Asia/Ust-Nera EST
+             */
+            if (!tzId.startsWith("Etc/GMT")) {
+                continue;
+            }
+
             final TimeZone tz = TimeZone.getTimeZone(tzId);
             if (tz == null) {
                 Log.e(TAG, "Timezone not found: " + tzId);
@@ -153,17 +170,54 @@
 
         // Don't change the order of mTimeZones after this sort
         Collections.sort(mTimeZones);
+        // TimeZoneInfo last = null;
+        // boolean first = true;
+        // for (TimeZoneInfo tz : mTimeZones) {
+        // // All
+        // Log.e("ALL", tz.toString());
+        //
+        // // GMT
+        // String name = tz.mTz.getDisplayName();
+        // if (name.startsWith("GMT") && !tz.mTzId.startsWith("Etc/GMT")) {
+        // Log.e("GMT", tz.toString());
+        // }
+        //
+        // // Dups
+        // if (last != null) {
+        // if (last.compareTo(tz) == 0) {
+        // if (first) {
+        // Log.e("SAME", last.toString());
+        // first = false;
+        // }
+        // Log.e("SAME", tz.toString());
+        // } else {
+        // first = true;
+        // }
+        // }
+        // last = tz;
+        // }
 
         mTimeZonesByCountry = new LinkedHashMap<String, ArrayList<Integer>>();
         mTimeZonesByOffsets = new SparseArray<ArrayList<Integer>>(mHasTimeZonesInHrOffset.length);
+        mTimeZonesById = new HashMap<String, TimeZoneInfo>(mTimeZones.size());
+        for (TimeZoneInfo tz : mTimeZones) {
+            // /////////////////////
+            // Lookup map for id -> tz
+            mTimeZonesById.put(tz.mTzId, tz);
+        }
+        populateDisplayNameOverrides(mContext.getResources());
 
         Date date = new Date(mTimeMillis);
         Locale defaultLocal = Locale.getDefault();
 
         int idx = 0;
         for (TimeZoneInfo tz : mTimeZones) {
-            tz.mDisplayName = tz.mTz.getDisplayName(tz.mTz.inDaylightTime(date),
-                    TimeZone.LONG, defaultLocal);
+            // /////////////////////
+            // Populate display name
+            if (tz.mDisplayName == null) {
+                tz.mDisplayName = tz.mTz.getDisplayName(tz.mTz.inDaylightTime(date),
+                        TimeZone.LONG, defaultLocal);
+            }
 
             // /////////////////////
             // Grouping tz's by country for search by country
@@ -191,8 +245,22 @@
         }
     }
 
-    private boolean[] mHasTimeZonesInHrOffset = new boolean[40];
-    SparseArray<ArrayList<Integer>> mTimeZonesByOffsets;
+    private void populateDisplayNameOverrides(Resources resources) {
+        String[] ids = resources.getStringArray(R.array.timezone_rename_ids);
+        String[] labels = resources.getStringArray(R.array.timezone_rename_labels);
+
+        int length = ids.length;
+        if (ids.length != labels.length) {
+            Log.e(TAG, "timezone_rename_ids len=" + ids.length + " timezone_rename_labels len="
+                    + labels.length);
+            length = Math.min(ids.length, labels.length);
+        }
+
+        for (int i = 0; i < length; i++) {
+            TimeZoneInfo tzi = mTimeZonesById.get(ids[i]);
+            tzi.mDisplayName = labels[i];
+        }
+    }
 
     public boolean hasTimeZonesInHrOffset(int offsetHr) {
         int index = OFFSET_ARRAY_OFFSET + offsetHr;
@@ -302,9 +370,20 @@
                         continue;
                     }
 
+                    /*
+                     * Dropping non-GMT tzs without a country code. They are not
+                     * really needed and they are dups but missing proper
+                     * country codes. e.g. WET CET MST7MDT PST8PDT Asia/Khandyga
+                     * Asia/Ust-Nera EST
+                     */
+                    if (countryCode == null && !timeZoneId.startsWith("Etc/GMT")) {
+                        processedTimeZones.add(timeZoneId);
+                        continue;
+                    }
+
                     // Remember the mapping between the country code and display
                     // name
-                    String country = mCountryCodeToNameMap.get(fields[0]);
+                    String country = mCountryCodeToNameMap.get(countryCode);
                     if (country == null) {
                         country = new Locale(lang, countryCode)
                                 .getDisplayCountry(Locale.getDefault());
diff --git a/src/com/android/timezonepicker/TimeZoneFilterTypeAdapter.java b/src/com/android/timezonepicker/TimeZoneFilterTypeAdapter.java
index b5557cb..0c8d420 100644
--- a/src/com/android/timezonepicker/TimeZoneFilterTypeAdapter.java
+++ b/src/com/android/timezonepicker/TimeZoneFilterTypeAdapter.java
@@ -266,20 +266,20 @@
             // ////////////////////////////////////////
             // Search by time zone name
             // ////////////////////////////////////////
-            first = true;
-            for (String timeZoneName : mTimeZoneData.mTimeZoneNames) {
-                // TODO Perf - cache toLowerCase()?
-                if (timeZoneName.toLowerCase().startsWith(prefixString)) {
-                    FilterTypeResult r;
-                    if (first) {
-                        r = new FilterTypeResult(true, FILTER_TYPE_TIME_ZONE, null, 0);
-                        filtered.add(r);
-                        first = false;
-                    }
-                    r = new FilterTypeResult(false, FILTER_TYPE_TIME_ZONE, timeZoneName, 0);
-                    filtered.add(r);
-                }
-            }
+//            first = true;
+//            for (String timeZoneName : mTimeZoneData.mTimeZoneNames) {
+//                // TODO Perf - cache toLowerCase()?
+//                if (timeZoneName.toLowerCase().startsWith(prefixString)) {
+//                    FilterTypeResult r;
+//                    if (first) {
+//                        r = new FilterTypeResult(true, FILTER_TYPE_TIME_ZONE, null, 0);
+//                        filtered.add(r);
+//                        first = false;
+//                    }
+//                    r = new FilterTypeResult(false, FILTER_TYPE_TIME_ZONE, timeZoneName, 0);
+//                    filtered.add(r);
+//                }
+//            }
 
             // ////////////////////////////////////////
             // TODO Search by state
diff --git a/src/com/android/timezonepicker/TimeZoneInfo.java b/src/com/android/timezonepicker/TimeZoneInfo.java
index 7fdc472..3cc2f92 100644
--- a/src/com/android/timezonepicker/TimeZoneInfo.java
+++ b/src/com/android/timezonepicker/TimeZoneInfo.java
@@ -308,19 +308,8 @@
      */
     @Override
     public int compareTo(TimeZoneInfo other) {
-
-        // TODO !!! Should compare the clock time instead of raw offset
-
-        // Higher raw offset comes before i.e. if the offset is bigger, return
-        // positive number.
-        if (this.mRawoffset != other.mRawoffset) {
-            return other.mRawoffset - this.mRawoffset;
-        }
-
-        // TZ with DST comes first because the offset is bigger during DST
-        // compared to a tz without DST
-        if (this.hasDst != other.hasDst) {
-            return this.hasDst ? -1 : 1;
+        if (this.getNowOffsetMillis() != other.getNowOffsetMillis()) {
+            return other.getNowOffsetMillis() - this.getNowOffsetMillis();
         }
 
         // By country