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