Home | History | Annotate | Download | only in location
      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 {
     42         public Locale getDefaultLocale() {
     43             return Locale.getDefault();
     44         }
     45     }
     46 
     47     private CountryDetector(Context context) {
     48         this (context, (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
     49                 new LocaleProvider());
     50     }
     51 
     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      */
     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      */
     73     public synchronized static CountryDetector getInstance(Context context) {
     74         if (sInstance == null) {
     75             sInstance = new CountryDetector(context.getApplicationContext());
     76         }
     77         return sInstance;
     78     }
     79 
     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      */
    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      */
    107     private String getSimBasedCountryIso() {
    108         return mTelephonyManager.getSimCountryIso();
    109     }
    110 
    111     /**
    112      * @return the country code of the user's currently selected locale.
    113      */
    114     private String getLocaleBasedCountryIso() {
    115         Locale defaultLocale = mLocaleProvider.getDefaultLocale();
    116         if (defaultLocale != null) {
    117             return defaultLocale.getCountry();
    118         }
    119         return null;
    120     }
    121 
    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