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