1 package com.android.contacts.location; 2 3 import android.content.Context; 4 import android.telephony.TelephonyManager; 5 import android.text.TextUtils; 6 7 import java.util.Locale; 8 9 /** 10 * This class is used to detect the country where the user is. It is a simplified version of the 11 * country detector service in the framework. The sources of country location are queried in the 12 * following order of reliability: 13 * <ul> 14 * <li>Mobile network</li> 15 * <li>SIM's country</li> 16 * <li>User's default locale</li> 17 * </ul> 18 * 19 * As far as possible this class tries to replicate the behavior of the system's country detector 20 * service: 21 * 1) Order in priority of sources of country location 22 * 2) Mobile network information provided by CDMA phones is ignored 23 */ 24 public class CountryDetector { 25 private static final String TAG = "CountryDetector"; 26 27 private static CountryDetector sInstance; 28 29 private final Context mContext; 30 private final LocaleProvider mLocaleProvider; 31 private final TelephonyManager mTelephonyManager; 32 33 // Used as a default country code when all the sources of country data have failed in the 34 // exceedingly rare event that the device does not have a default locale set for some reason. 35 private final String DEFAULT_COUNTRY_ISO = "US"; 36 37 /** 38 * Class that can be used to return the user's default locale. This is in its own class so that 39 * it can be mocked out. 40 */ 41 public static class LocaleProvider { getDefaultLocale()42 public Locale getDefaultLocale() { 43 return Locale.getDefault(); 44 } 45 } 46 CountryDetector(Context context)47 private CountryDetector(Context context) { 48 this (context, (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE), 49 new LocaleProvider()); 50 } 51 CountryDetector(Context context, TelephonyManager telephonyManager, LocaleProvider localeProvider)52 private CountryDetector(Context context, TelephonyManager telephonyManager, 53 LocaleProvider localeProvider) { 54 mTelephonyManager = telephonyManager; 55 mLocaleProvider = localeProvider; 56 mContext = context; 57 } 58 59 /** 60 * Factory method for {@link CountryDetector} that allows the caller to provide mock objects. 61 */ getInstanceForTest(Context context, TelephonyManager telephonyManager, LocaleProvider localeProvider)62 public CountryDetector getInstanceForTest(Context context, TelephonyManager telephonyManager, 63 LocaleProvider localeProvider) { 64 return new CountryDetector(context, telephonyManager, localeProvider); 65 } 66 67 /** 68 * Returns the instance of the country detector. {@link #initialize(Context)} must have been 69 * called previously. 70 * 71 * @return the initialized country detector. 72 */ getInstance(Context context)73 public synchronized static CountryDetector getInstance(Context context) { 74 if (sInstance == null) { 75 sInstance = new CountryDetector(context.getApplicationContext()); 76 } 77 return sInstance; 78 } 79 getCurrentCountryIso()80 public String getCurrentCountryIso() { 81 String result = null; 82 if (isNetworkCountryCodeAvailable()) { 83 result = getNetworkBasedCountryIso(); 84 } 85 if (TextUtils.isEmpty(result)) { 86 result = getSimBasedCountryIso(); 87 } 88 if (TextUtils.isEmpty(result)) { 89 result = getLocaleBasedCountryIso(); 90 } 91 if (TextUtils.isEmpty(result)) { 92 result = DEFAULT_COUNTRY_ISO; 93 } 94 return result.toUpperCase(Locale.US); 95 } 96 97 /** 98 * @return the country code of the current telephony network the user is connected to. 99 */ getNetworkBasedCountryIso()100 private String getNetworkBasedCountryIso() { 101 return mTelephonyManager.getNetworkCountryIso(); 102 } 103 104 /** 105 * @return the country code of the SIM card currently inserted in the device. 106 */ getSimBasedCountryIso()107 private String getSimBasedCountryIso() { 108 return mTelephonyManager.getSimCountryIso(); 109 } 110 111 /** 112 * @return the country code of the user's currently selected locale. 113 */ getLocaleBasedCountryIso()114 private String getLocaleBasedCountryIso() { 115 Locale defaultLocale = mLocaleProvider.getDefaultLocale(); 116 if (defaultLocale != null) { 117 return defaultLocale.getCountry(); 118 } 119 return null; 120 } 121 isNetworkCountryCodeAvailable()122 private boolean isNetworkCountryCodeAvailable() { 123 // On CDMA TelephonyManager.getNetworkCountryIso() just returns the SIM's country code. 124 return mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM; 125 } 126 } 127