1a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao/* 2a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Copyright (C) 2010 The Android Open Source Project 3a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * 4a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Licensed under the Apache License, Version 2.0 (the "License"); 5a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * you may not use this file except in compliance with the License. 6a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * You may obtain a copy of the License at 7a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * 8a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * http://www.apache.org/licenses/LICENSE-2.0 9a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * 10a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Unless required by applicable law or agreed to in writing, software 11a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * distributed under the License is distributed on an "AS IS" BASIS, 12a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * See the License for the specific language governing permissions and 14a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * limitations under the License 15a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 16a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 17a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taopackage com.android.server.location; 18a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 19a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.content.Context; 20a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.location.Country; 21a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.location.CountryListener; 22a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.location.Geocoder; 23d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onukiimport android.os.SystemClock; 24a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.provider.Settings; 25a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.telephony.PhoneStateListener; 26a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.telephony.ServiceState; 27a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.telephony.TelephonyManager; 28a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.text.TextUtils; 29a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.util.Slog; 30a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 31141e00c212ab1cd9d6def55edadc3e709d88f9d5Marc Blankimport java.util.Locale; 32141e00c212ab1cd9d6def55edadc3e709d88f9d5Marc Blankimport java.util.Timer; 33141e00c212ab1cd9d6def55edadc3e709d88f9d5Marc Blankimport java.util.TimerTask; 34d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onukiimport java.util.concurrent.ConcurrentLinkedQueue; 35141e00c212ab1cd9d6def55edadc3e709d88f9d5Marc Blank 36a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao/** 37a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * This class is used to detect the country where the user is. The sources of 38a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * country are queried in order of reliability, like 39a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <ul> 40a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <li>Mobile network</li> 41a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <li>Location</li> 42a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <li>SIM's country</li> 43a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <li>Phone's locale</li> 44a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * </ul> 45a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 46a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Call the {@link #detectCountry()} to get the available country immediately. 47a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 48a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * To be notified of the future country change, using the 49a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * {@link #setCountryListener(CountryListener)} 50a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 51a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Using the {@link #stop()} to stop listening to the country change. 52a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 53a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * The country information will be refreshed every 54a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * {@link #LOCATION_REFRESH_INTERVAL} once the location based country is used. 55a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * 56a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @hide 57a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 58a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taopublic class ComprehensiveCountryDetector extends CountryDetectorBase { 59a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 60d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private final static String TAG = "CountryDetector"; 61a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa /* package */ static final boolean DEBUG = false; 62a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 63a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 64d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * Max length of logs to maintain for debugging. 65d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki */ 66d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private static final int MAX_LENGTH_DEBUG_LOGS = 20; 67d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 68d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki /** 69a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * The refresh interval when the location based country was used 70a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 71a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private final static long LOCATION_REFRESH_INTERVAL = 1000 * 60 * 60 * 24; // 1 day 72a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 73a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected CountryDetectorBase mLocationBasedCountryDetector; 74a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected Timer mLocationRefreshTimer; 75a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 76a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private Country mCountry; 77d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private final TelephonyManager mTelephonyManager; 78a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private Country mCountryFromLocation; 79a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private boolean mStopped = false; 80a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 81d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private PhoneStateListener mPhoneStateListener; 82d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 83d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki /** 84d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * List of the most recent country state changes for debugging. This should have 85d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * a max length of MAX_LENGTH_LOGS. 86d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki */ 87d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private final ConcurrentLinkedQueue<Country> mDebugLogs = new ConcurrentLinkedQueue<Country>(); 88d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 89d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki /** 90d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * Most recent {@link Country} result that was added to the debug logs {@link #mDebugLogs}. 91d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * We keep track of this value to help prevent adding many of the same {@link Country} objects 92d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * to the logs. 93d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki */ 94d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private Country mLastCountryAddedToLogs; 95d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 96d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki /** 97d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * Object used to synchronize access to {@link #mLastCountryAddedToLogs}. Be careful if 98d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * using it to synchronize anything else in this file. 99d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki */ 100d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private final Object mObject = new Object(); 101d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 102d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki /** 103d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * Start time of the current session for which the detector has been active. 104d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki */ 105d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private long mStartTime; 106d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 107d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki /** 108d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * Stop time of the most recent session for which the detector was active. 109d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki */ 110d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private long mStopTime; 111d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 112d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki /** 113d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * The sum of all the time intervals in which the detector was active. 114d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki */ 115d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private long mTotalTime; 116d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 117d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki /** 118d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * Number of {@link PhoneStateListener#onServiceStateChanged(ServiceState state)} events that 119d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * have occurred for the current session for which the detector has been active. 120d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki */ 121d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private int mCountServiceStateChanges; 122d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 123d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki /** 124d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * Total number of {@link PhoneStateListener#onServiceStateChanged(ServiceState state)} events 125d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * that have occurred for all time intervals in which the detector has been active. 126d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki */ 127d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private int mTotalCountServiceStateChanges; 128a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 129a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 130a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * The listener for receiving the notification from LocationBasedCountryDetector. 131a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 132a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private CountryListener mLocationBasedCountryDetectionListener = new CountryListener() { 133a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa @Override 134a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void onCountryDetected(Country country) { 135a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa if (DEBUG) Slog.d(TAG, "Country detected via LocationBasedCountryDetector"); 136a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mCountryFromLocation = country; 137a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // Don't start the LocationBasedCountryDetector. 138a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao detectCountry(true, false); 139a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao stopLocationBasedDetector(); 140a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 141a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao }; 142a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 143a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public ComprehensiveCountryDetector(Context context) { 144a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao super(context); 145a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 146a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 147a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 148a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao @Override 149a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public Country detectCountry() { 150a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // Don't start the LocationBasedCountryDetector if we have been stopped. 151a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return detectCountry(false, !mStopped); 152a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 153a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 154a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao @Override 155a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void stop() { 156d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki // Note: this method in this subclass called only by tests. 157a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Slog.i(TAG, "Stop the detector."); 158a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao cancelLocationRefresh(); 159a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao removePhoneStateListener(); 160a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao stopLocationBasedDetector(); 161a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mListener = null; 162a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mStopped = true; 163a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 164a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 165a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 166a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Get the country from different sources in order of the reliability. 167a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 168a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private Country getCountry() { 169a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Country result = null; 170a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao result = getNetworkBasedCountry(); 171a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (result == null) { 172a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao result = getLastKnownLocationBasedCountry(); 173a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 174a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (result == null) { 175a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao result = getSimBasedCountry(); 176a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 177a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (result == null) { 178a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao result = getLocaleCountry(); 179a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 180d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki addToLogs(result); 181a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return result; 182a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 183a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 184a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 185d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki * Attempt to add this {@link Country} to the debug logs. 186d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki */ 187d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private void addToLogs(Country country) { 188d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki if (country == null) { 189d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki return; 190d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki } 191d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki // If the country (ISO and source) are the same as before, then there is no 192d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki // need to add this country as another entry in the logs. Synchronize access to this 193d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki // variable since multiple threads could be calling this method. 194d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki synchronized (mObject) { 195d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki if (mLastCountryAddedToLogs != null && mLastCountryAddedToLogs.equals(country)) { 196d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki return; 197d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki } 198d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki mLastCountryAddedToLogs = country; 199d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki } 200d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki // Manually maintain a max limit for the list of logs 201d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki if (mDebugLogs.size() >= MAX_LENGTH_DEBUG_LOGS) { 202d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki mDebugLogs.poll(); 203d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki } 2040e87370077b322b3a88c345a44c6bf3d56617071Daniel Lehmann if (DEBUG) { 205d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki Slog.d(TAG, country.toString()); 206d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki } 207d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki mDebugLogs.add(country); 208d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki } 209d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 210d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki private boolean isNetworkCountryCodeAvailable() { 211d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki // On CDMA TelephonyManager.getNetworkCountryIso() just returns SIM country. We don't want 212d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki // to prioritize it over location based country, so ignore it. 213d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki final int phoneType = mTelephonyManager.getPhoneType(); 214d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki if (DEBUG) Slog.v(TAG, " phonetype=" + phoneType); 215d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki return phoneType == TelephonyManager.PHONE_TYPE_GSM; 216d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki } 217d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 218d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki /** 219a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @return the country from the mobile network. 220a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 221a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected Country getNetworkBasedCountry() { 222a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao String countryIso = null; 223d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki if (isNetworkCountryCodeAvailable()) { 224a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao countryIso = mTelephonyManager.getNetworkCountryIso(); 225a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (!TextUtils.isEmpty(countryIso)) { 226a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return new Country(countryIso, Country.COUNTRY_SOURCE_NETWORK); 227a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 228a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 229a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return null; 230a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 231a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 232a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 233a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @return the cached location based country. 234a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 235a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected Country getLastKnownLocationBasedCountry() { 236a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return mCountryFromLocation; 237a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 238a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 239a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 240a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @return the country from SIM card 241a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 242a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected Country getSimBasedCountry() { 243a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao String countryIso = null; 244a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao countryIso = mTelephonyManager.getSimCountryIso(); 245a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (!TextUtils.isEmpty(countryIso)) { 246a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return new Country(countryIso, Country.COUNTRY_SOURCE_SIM); 247a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 248a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return null; 249a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 250a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 251a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 252a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @return the country from the system's locale. 253a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 254a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected Country getLocaleCountry() { 255a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Locale defaultLocale = Locale.getDefault(); 256a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (defaultLocale != null) { 257a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return new Country(defaultLocale.getCountry(), Country.COUNTRY_SOURCE_LOCALE); 258a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } else { 259a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return null; 260a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 261a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 262a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 263a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 264a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @param notifyChange indicates whether the listener should be notified the change of the 265a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * country 266a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @param startLocationBasedDetection indicates whether the LocationBasedCountryDetector could 267a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * be started if the current country source is less reliable than the location. 268a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @return the current available UserCountry 269a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 270a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private Country detectCountry(boolean notifyChange, boolean startLocationBasedDetection) { 271a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Country country = getCountry(); 272a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao runAfterDetectionAsync(mCountry != null ? new Country(mCountry) : mCountry, country, 273a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao notifyChange, startLocationBasedDetection); 274a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mCountry = country; 275a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return mCountry; 276a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 277a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 278a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 279a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Run the tasks in the service's thread. 280a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 281a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected void runAfterDetectionAsync(final Country country, final Country detectedCountry, 282a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao final boolean notifyChange, final boolean startLocationBasedDetection) { 283a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mHandler.post(new Runnable() { 284a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa @Override 285a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void run() { 286a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao runAfterDetection( 287a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao country, detectedCountry, notifyChange, startLocationBasedDetection); 288a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 289a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao }); 290a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 291a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 292a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao @Override 293a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void setCountryListener(CountryListener listener) { 294a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao CountryListener prevListener = mListener; 295a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mListener = listener; 296a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mListener == null) { 297a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // Stop listening all services 298a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao removePhoneStateListener(); 299a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao stopLocationBasedDetector(); 300a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao cancelLocationRefresh(); 301d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki mStopTime = SystemClock.elapsedRealtime(); 302d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki mTotalTime += mStopTime; 303a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } else if (prevListener == null) { 304a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao addPhoneStateListener(); 305a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao detectCountry(false, true); 306d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki mStartTime = SystemClock.elapsedRealtime(); 307d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki mStopTime = 0; 308d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki mCountServiceStateChanges = 0; 309a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 310a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 311a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 312a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao void runAfterDetection(final Country country, final Country detectedCountry, 313a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao final boolean notifyChange, final boolean startLocationBasedDetection) { 314a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (notifyChange) { 315a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao notifyIfCountryChanged(country, detectedCountry); 316a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 317a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa if (DEBUG) { 318a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa Slog.d(TAG, "startLocationBasedDetection=" + startLocationBasedDetection 319a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa + " detectCountry=" + (detectedCountry == null ? null : 320a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa "(source: " + detectedCountry.getSource() 321a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa + ", countryISO: " + detectedCountry.getCountryIso() + ")") 322a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa + " isAirplaneModeOff()=" + isAirplaneModeOff() 323a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa + " mListener=" + mListener 324a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa + " isGeoCoderImplemnted()=" + isGeoCoderImplemented()); 325a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa } 326a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa 327a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (startLocationBasedDetection && (detectedCountry == null 328a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao || detectedCountry.getSource() > Country.COUNTRY_SOURCE_LOCATION) 329a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao && isAirplaneModeOff() && mListener != null && isGeoCoderImplemented()) { 330a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa if (DEBUG) Slog.d(TAG, "run startLocationBasedDetector()"); 331a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // Start finding location when the source is less reliable than the 332a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // location and the airplane mode is off (as geocoder will not 333a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // work). 334a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // TODO : Shall we give up starting the detector within a 335a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // period of time? 336a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao startLocationBasedDetector(mLocationBasedCountryDetectionListener); 337a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 338a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (detectedCountry == null 339a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao || detectedCountry.getSource() >= Country.COUNTRY_SOURCE_LOCATION) { 340a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // Schedule the location refresh if the country source is 341a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // not more reliable than the location or no country is 342a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // found. 343a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // TODO: Listen to the preference change of GPS, Wifi etc, 344a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // and start detecting the country. 345a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao scheduleLocationRefresh(); 346a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } else { 347a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // Cancel the location refresh once the current source is 348a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // more reliable than the location. 349a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao cancelLocationRefresh(); 350a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao stopLocationBasedDetector(); 351a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 352a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 353a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 354a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 355a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Find the country from LocationProvider. 356a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 357a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private synchronized void startLocationBasedDetector(CountryListener listener) { 358a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mLocationBasedCountryDetector != null) { 359a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return; 360a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 361a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa if (DEBUG) { 362a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa Slog.d(TAG, "starts LocationBasedDetector to detect Country code via Location info " 363a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa + "(e.g. GPS)"); 364a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa } 365a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationBasedCountryDetector = createLocationBasedCountryDetector(); 366a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationBasedCountryDetector.setCountryListener(listener); 367a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationBasedCountryDetector.detectCountry(); 368a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 369a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 370a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private synchronized void stopLocationBasedDetector() { 371a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa if (DEBUG) { 372a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa Slog.d(TAG, "tries to stop LocationBasedDetector " 373a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa + "(current detector: " + mLocationBasedCountryDetector + ")"); 374a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa } 375a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mLocationBasedCountryDetector != null) { 376a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationBasedCountryDetector.stop(); 377a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationBasedCountryDetector = null; 378a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 379a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 380a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 381a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected CountryDetectorBase createLocationBasedCountryDetector() { 382a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return new LocationBasedCountryDetector(mContext); 383a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 384a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 385a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected boolean isAirplaneModeOff() { 386c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate return Settings.Global.getInt( 387c09cdce1b05075da808ae080b9905a14a3e1e627Christopher Tate mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) == 0; 388a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 389a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 390a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 391a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Notify the country change. 392a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 393a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private void notifyIfCountryChanged(final Country country, final Country detectedCountry) { 394a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (detectedCountry != null && mListener != null 395a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao && (country == null || !country.equals(detectedCountry))) { 3960e87370077b322b3a88c345a44c6bf3d56617071Daniel Lehmann if (DEBUG) { 397d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki Slog.d(TAG, "" + country + " --> " + detectedCountry); 398d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki } 399a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao notifyListener(detectedCountry); 400a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 401a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 402a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 403a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 404a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Schedule the next location refresh. We will do nothing if the scheduled task exists. 405a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 406a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private synchronized void scheduleLocationRefresh() { 407a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mLocationRefreshTimer != null) return; 408a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa if (DEBUG) { 409a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa Slog.d(TAG, "start periodic location refresh timer. Interval: " 410a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa + LOCATION_REFRESH_INTERVAL); 411a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa } 412a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationRefreshTimer = new Timer(); 413a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationRefreshTimer.schedule(new TimerTask() { 414a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao @Override 415a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void run() { 416a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa if (DEBUG) { 417a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa Slog.d(TAG, "periodic location refresh event. Starts detecting Country code"); 418a550bdc84af70babb48091197bfb1b93d3671664Daisuke Miyakawa } 419a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationRefreshTimer = null; 420a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao detectCountry(false, true); 421a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 422a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao }, LOCATION_REFRESH_INTERVAL); 423a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 424a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 425a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 426a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Cancel the scheduled refresh task if it exists 427a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 428a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private synchronized void cancelLocationRefresh() { 429a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mLocationRefreshTimer != null) { 430a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationRefreshTimer.cancel(); 431a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationRefreshTimer = null; 432a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 433a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 434a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 435a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected synchronized void addPhoneStateListener() { 436d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki if (mPhoneStateListener == null) { 437a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mPhoneStateListener = new PhoneStateListener() { 438a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao @Override 439a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void onServiceStateChanged(ServiceState serviceState) { 440d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki mCountServiceStateChanges++; 441d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki mTotalCountServiceStateChanges++; 442d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 443d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki if (!isNetworkCountryCodeAvailable()) { 444d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki return; 445a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 446d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki if (DEBUG) Slog.d(TAG, "onServiceStateChanged: " + serviceState.getState()); 447d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 448d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki detectCountry(true, true); 449a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 450a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao }; 451a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE); 452a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 453a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 454a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 455a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected synchronized void removePhoneStateListener() { 456a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mPhoneStateListener != null) { 457a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); 458a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mPhoneStateListener = null; 459a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 460a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 461a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 462a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected boolean isGeoCoderImplemented() { 463141e00c212ab1cd9d6def55edadc3e709d88f9d5Marc Blank return Geocoder.isPresent(); 464a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 465d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki 466d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki @Override 467d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki public String toString() { 468d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki long currentTime = SystemClock.elapsedRealtime(); 469d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki long currentSessionLength = 0; 470d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki StringBuilder sb = new StringBuilder(); 471d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki sb.append("ComprehensiveCountryDetector{"); 472d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki // The detector hasn't stopped yet --> still running 473d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki if (mStopTime == 0) { 474d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki currentSessionLength = currentTime - mStartTime; 475d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki sb.append("timeRunning=" + currentSessionLength + ", "); 476d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki } else { 477d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki // Otherwise, it has already stopped, so take the last session 478d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki sb.append("lastRunTimeLength=" + (mStopTime - mStartTime) + ", "); 479d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki } 480d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki sb.append("totalCountServiceStateChanges=" + mTotalCountServiceStateChanges + ", "); 481d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki sb.append("currentCountServiceStateChanges=" + mCountServiceStateChanges + ", "); 482d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki sb.append("totalTime=" + (mTotalTime + currentSessionLength) + ", "); 483d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki sb.append("currentTime=" + currentTime + ", "); 484d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki sb.append("countries="); 485d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki for (Country country : mDebugLogs) { 486d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki sb.append("\n " + country.toString()); 487d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki } 488d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki sb.append("}"); 489d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki return sb.toString(); 490d73b79bb314dde86cf8ff9300fefc133b31841d1Makoto Onuki } 491a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao} 492