1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tv.settings.system; 18 19 import com.android.tv.settings.R; 20 import com.android.tv.settings.dialog.old.Action; 21 import com.android.tv.settings.dialog.old.ActionAdapter; 22 import com.android.tv.settings.dialog.old.ActionFragment; 23 import com.android.tv.settings.dialog.old.ContentFragment; 24 import com.android.tv.settings.dialog.old.DialogActivity; 25 import com.android.internal.app.LocalePicker; 26 27 import android.app.ActivityManagerNative; 28 import android.app.Fragment; 29 import android.content.Context; 30 import android.content.res.Configuration; 31 import android.content.res.Resources; 32 import android.net.wifi.WifiManager; 33 import android.os.Bundle; 34 import android.os.RemoteException; 35 import android.text.TextUtils; 36 import android.util.Log; 37 import android.view.KeyEvent; 38 import android.widget.ArrayAdapter; 39 40 import java.util.ArrayList; 41 import java.util.Comparator; 42 import java.util.Locale; 43 import java.util.MissingResourceException; 44 45 public class LanguageActivity extends DialogActivity implements ActionAdapter.Listener { 46 47 private static final String TAG = "LanguageActivity"; 48 private static final boolean DEBUG = false; 49 50 private static final String KEY_LOCALE = "locale"; 51 /** 52 * Comparator of LocaleInfo objects that prioritizes US locales above all 53 * others. Between US locales it prioritizes English. All other locales are 54 * sorted alphabetically first by language and then by region. So, Canadian 55 * French is presented before French French. 56 */ 57 private static class LocaleComparator implements Comparator<LocalePicker.LocaleInfo> { 58 @Override compare(LocalePicker.LocaleInfo l, LocalePicker.LocaleInfo r)59 public int compare(LocalePicker.LocaleInfo l, LocalePicker.LocaleInfo r) { 60 Locale lhs = l.getLocale(); 61 Locale rhs = r.getLocale(); 62 63 String lhsCountry = ""; 64 String rhsCountry = ""; 65 66 try { 67 lhsCountry = lhs.getISO3Country(); 68 } catch (MissingResourceException e) { 69 Log.e(TAG, "LocaleComparator cuaught exception, country set to empty."); 70 } 71 72 try { 73 rhsCountry = rhs.getISO3Country(); 74 } catch (MissingResourceException e) { 75 Log.e(TAG, "LocaleComparator cuaught exception, country set to empty."); 76 } 77 78 String lhsLang = ""; 79 String rhsLang = ""; 80 81 try { 82 lhsLang = lhs.getISO3Language(); 83 } catch (MissingResourceException e) { 84 Log.e(TAG, "LocaleComparator cuaught exception, language set to empty."); 85 } 86 87 try { 88 rhsLang = rhs.getISO3Language(); 89 } catch (MissingResourceException e) { 90 Log.e(TAG, "LocaleComparator cuaught exception, language set to empty."); 91 } 92 93 // if they're the same locale, return 0 94 if (lhsCountry.equals(rhsCountry) && lhsLang.equals(rhsLang)) { 95 return 0; 96 } 97 98 // prioritize US over other countries 99 if ("USA".equals(lhsCountry)) { 100 // if right hand side is not also USA, left hand side is first 101 if (!"USA".equals(rhsCountry)) { 102 return -1; 103 } else { 104 // if one of the languages is english we want to prioritize 105 // it, otherwise we don't care, just alphabetize 106 if ("ENG".equals(lhsLang) && "ENG".equals(rhsLang)) { 107 return 0; 108 } else { 109 return "ENG".equals(lhsLang) ? -1 : 1; 110 } 111 } 112 } else if ("USA".equals(rhsCountry)) { 113 // right-hand side is the US and the other isn't, return greater than 1 114 return 1; 115 } else { 116 // neither side is the US, sort based on display language name 117 // then country name 118 int langEquiv = lhs.getDisplayLanguage(lhs).compareTo(rhs.getDisplayLanguage(rhs)); 119 if (langEquiv == 0) { 120 return lhs.getDisplayCountry(lhs).compareTo(rhs.getDisplayCountry(rhs)); 121 } else { 122 return langEquiv; 123 } 124 } 125 } 126 } 127 128 private Fragment mContentFragment; 129 private ActionFragment mActionFragment; 130 private Resources mResources; 131 private ArrayList<Action> mActions; 132 private ArrayAdapter<LocalePicker.LocaleInfo> mLocales; 133 134 @Override onCreate(Bundle savedInstanceState)135 public void onCreate(Bundle savedInstanceState) { 136 super.onCreate(savedInstanceState); 137 138 mResources = getResources(); 139 init(); 140 setContentAndActionFragments(mContentFragment, mActionFragment); 141 142 } 143 144 @Override onActionClicked(Action action)145 public void onActionClicked(Action action) { 146 String key = action.getKey(); 147 if (key.contains(KEY_LOCALE)) { 148 String s = key.substring(KEY_LOCALE.length()); 149 int i = Integer.parseInt(s); 150 setLanguagePreference(i); 151 setWifiCountryCode(); 152 finish(); 153 } 154 } 155 156 @Override onConfigurationChanged(Configuration newConfig)157 public void onConfigurationChanged(Configuration newConfig) { 158 super.onConfigurationChanged(newConfig); 159 mResources = getResources(); 160 makeContentFragment(); 161 setContentFragment(mContentFragment); 162 } 163 makeContentFragment()164 private void makeContentFragment() { 165 mContentFragment = ContentFragment.newInstance( 166 mResources.getString(R.string.system_language), null, null, 167 R.drawable.ic_settings_language, getResources().getColor(R.color.icon_background)); 168 } 169 init()170 private void init() { 171 mActions = new ArrayList<Action>(); 172 makeContentFragment(); 173 174 final String[] specialLocaleCodes = getResources().getStringArray( 175 com.android.internal.R.array.special_locale_codes); 176 final String[] specialLocaleNames = getResources().getStringArray( 177 com.android.internal.R.array.special_locale_names); 178 mLocales = LocalePicker.constructAdapter(this); 179 mLocales.sort(new LocaleComparator()); 180 final String[] localeNames = new String[mLocales.getCount()]; 181 Locale currentLocale; 182 try { 183 currentLocale = ActivityManagerNative.getDefault().getConfiguration().locale; 184 } catch (RemoteException e) { 185 currentLocale = null; 186 } 187 for (int i = 0; i < localeNames.length; i++) { 188 Locale target = mLocales.getItem(i).getLocale(); 189 localeNames[i] = getDisplayName(target, specialLocaleCodes, specialLocaleNames); 190 191 // if this locale's label has a country, use the shortened version 192 // instead 193 if (mLocales.getItem(i).getLabel().contains("(")) { 194 String country = target.getCountry(); 195 if (!TextUtils.isEmpty(country)) { 196 localeNames[i] = localeNames[i] + " (" + target.getCountry() + ")"; 197 } 198 } 199 200 // For some reason locales are not always first letter cased, for example for 201 // in the Spanish locale. 202 if (localeNames[i].length() > 0) { 203 localeNames[i] = localeNames[i].substring(0, 1).toUpperCase(currentLocale) + 204 localeNames[i].substring(1); 205 } 206 207 StringBuilder sb = new StringBuilder(); 208 sb.append(KEY_LOCALE).append(i); 209 mActions.add(new Action.Builder() 210 .key(sb.toString()) 211 .title(localeNames[i]) 212 .checked(target.equals(currentLocale)) 213 .build()); 214 } 215 216 mActionFragment = ActionFragment.newInstance(mActions); 217 } 218 getDisplayName( Locale l, String[] specialLocaleCodes, String[] specialLocaleNames)219 private static String getDisplayName( 220 Locale l, String[] specialLocaleCodes, String[] specialLocaleNames) { 221 String code = l.toString(); 222 223 for (int i = 0; i < specialLocaleCodes.length; i++) { 224 if (specialLocaleCodes[i].equals(code)) { 225 return specialLocaleNames[i]; 226 } 227 } 228 229 return l.getDisplayName(l); 230 } 231 setLanguagePreference(int offset)232 private void setLanguagePreference(int offset) { 233 LocalePicker.updateLocale(mLocales.getItem(offset).getLocale()); 234 } 235 setWifiCountryCode()236 private void setWifiCountryCode() { 237 String countryCode = Locale.getDefault().getCountry(); 238 WifiManager wifiMgr = (WifiManager) getSystemService(Context.WIFI_SERVICE); 239 240 if (wifiMgr != null && !TextUtils.isEmpty(countryCode)) { 241 wifiMgr.setCountryCode(countryCode, true); 242 } 243 } 244 } 245