Fields Summary |
---|
private static final String | TAG |
static final boolean | DEBUG |
private static final int | MAX_LENGTH_DEBUG_LOGSMax length of logs to maintain for debugging. |
private static final long | LOCATION_REFRESH_INTERVALThe refresh interval when the location based country was used |
protected CountryDetectorBase | mLocationBasedCountryDetector |
protected Timer | mLocationRefreshTimer |
private android.location.Country | mCountry |
private final android.telephony.TelephonyManager | mTelephonyManager |
private android.location.Country | mCountryFromLocation |
private boolean | mStopped |
private android.telephony.PhoneStateListener | mPhoneStateListener |
private final ConcurrentLinkedQueue | mDebugLogsList of the most recent country state changes for debugging. This should have
a max length of MAX_LENGTH_LOGS. |
private android.location.Country | mLastCountryAddedToLogsMost recent {@link Country} result that was added to the debug logs {@link #mDebugLogs}.
We keep track of this value to help prevent adding many of the same {@link Country} objects
to the logs. |
private final Object | mObjectObject used to synchronize access to {@link #mLastCountryAddedToLogs}. Be careful if
using it to synchronize anything else in this file. |
private long | mStartTimeStart time of the current session for which the detector has been active. |
private long | mStopTimeStop time of the most recent session for which the detector was active. |
private long | mTotalTimeThe sum of all the time intervals in which the detector was active. |
private int | mCountServiceStateChangesNumber of {@link PhoneStateListener#onServiceStateChanged(ServiceState state)} events that
have occurred for the current session for which the detector has been active. |
private int | mTotalCountServiceStateChangesTotal number of {@link PhoneStateListener#onServiceStateChanged(ServiceState state)} events
that have occurred for all time intervals in which the detector has been active. |
private android.location.CountryListener | mLocationBasedCountryDetectionListenerThe listener for receiving the notification from LocationBasedCountryDetector. |
Methods Summary |
---|
protected synchronized void | addPhoneStateListener()
if (mPhoneStateListener == null) {
mPhoneStateListener = new PhoneStateListener() {
@Override
public void onServiceStateChanged(ServiceState serviceState) {
mCountServiceStateChanges++;
mTotalCountServiceStateChanges++;
if (!isNetworkCountryCodeAvailable()) {
return;
}
if (DEBUG) Slog.d(TAG, "onServiceStateChanged: " + serviceState.getState());
detectCountry(true, true);
}
};
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
}
|
private void | addToLogs(android.location.Country country)Attempt to add this {@link Country} to the debug logs.
if (country == null) {
return;
}
// If the country (ISO and source) are the same as before, then there is no
// need to add this country as another entry in the logs. Synchronize access to this
// variable since multiple threads could be calling this method.
synchronized (mObject) {
if (mLastCountryAddedToLogs != null && mLastCountryAddedToLogs.equals(country)) {
return;
}
mLastCountryAddedToLogs = country;
}
// Manually maintain a max limit for the list of logs
if (mDebugLogs.size() >= MAX_LENGTH_DEBUG_LOGS) {
mDebugLogs.poll();
}
if (DEBUG) {
Slog.d(TAG, country.toString());
}
mDebugLogs.add(country);
|
private synchronized void | cancelLocationRefresh()Cancel the scheduled refresh task if it exists
if (mLocationRefreshTimer != null) {
mLocationRefreshTimer.cancel();
mLocationRefreshTimer = null;
}
|
protected CountryDetectorBase | createLocationBasedCountryDetector()
return new LocationBasedCountryDetector(mContext);
|
private android.location.Country | detectCountry(boolean notifyChange, boolean startLocationBasedDetection)
Country country = getCountry();
runAfterDetectionAsync(mCountry != null ? new Country(mCountry) : mCountry, country,
notifyChange, startLocationBasedDetection);
mCountry = country;
return mCountry;
|
public android.location.Country | detectCountry()
// Don't start the LocationBasedCountryDetector if we have been stopped.
return detectCountry(false, !mStopped);
|
private android.location.Country | getCountry()Get the country from different sources in order of the reliability.
Country result = null;
result = getNetworkBasedCountry();
if (result == null) {
result = getLastKnownLocationBasedCountry();
}
if (result == null) {
result = getSimBasedCountry();
}
if (result == null) {
result = getLocaleCountry();
}
addToLogs(result);
return result;
|
protected android.location.Country | getLastKnownLocationBasedCountry()
return mCountryFromLocation;
|
protected android.location.Country | getLocaleCountry()
Locale defaultLocale = Locale.getDefault();
if (defaultLocale != null) {
return new Country(defaultLocale.getCountry(), Country.COUNTRY_SOURCE_LOCALE);
} else {
return null;
}
|
protected android.location.Country | getNetworkBasedCountry()
String countryIso = null;
if (isNetworkCountryCodeAvailable()) {
countryIso = mTelephonyManager.getNetworkCountryIso();
if (!TextUtils.isEmpty(countryIso)) {
return new Country(countryIso, Country.COUNTRY_SOURCE_NETWORK);
}
}
return null;
|
protected android.location.Country | getSimBasedCountry()
String countryIso = null;
countryIso = mTelephonyManager.getSimCountryIso();
if (!TextUtils.isEmpty(countryIso)) {
return new Country(countryIso, Country.COUNTRY_SOURCE_SIM);
}
return null;
|
protected boolean | isAirplaneModeOff()
return Settings.Global.getInt(
mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) == 0;
|
protected boolean | isGeoCoderImplemented()
return Geocoder.isPresent();
|
private boolean | isNetworkCountryCodeAvailable()
// On CDMA TelephonyManager.getNetworkCountryIso() just returns SIM country. We don't want
// to prioritize it over location based country, so ignore it.
final int phoneType = mTelephonyManager.getPhoneType();
if (DEBUG) Slog.v(TAG, " phonetype=" + phoneType);
return phoneType == TelephonyManager.PHONE_TYPE_GSM;
|
private void | notifyIfCountryChanged(android.location.Country country, android.location.Country detectedCountry)Notify the country change.
if (detectedCountry != null && mListener != null
&& (country == null || !country.equals(detectedCountry))) {
if (DEBUG) {
Slog.d(TAG, "" + country + " --> " + detectedCountry);
}
notifyListener(detectedCountry);
}
|
protected synchronized void | removePhoneStateListener()
if (mPhoneStateListener != null) {
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
mPhoneStateListener = null;
}
|
void | runAfterDetection(android.location.Country country, android.location.Country detectedCountry, boolean notifyChange, boolean startLocationBasedDetection)
if (notifyChange) {
notifyIfCountryChanged(country, detectedCountry);
}
if (DEBUG) {
Slog.d(TAG, "startLocationBasedDetection=" + startLocationBasedDetection
+ " detectCountry=" + (detectedCountry == null ? null :
"(source: " + detectedCountry.getSource()
+ ", countryISO: " + detectedCountry.getCountryIso() + ")")
+ " isAirplaneModeOff()=" + isAirplaneModeOff()
+ " mListener=" + mListener
+ " isGeoCoderImplemnted()=" + isGeoCoderImplemented());
}
if (startLocationBasedDetection && (detectedCountry == null
|| detectedCountry.getSource() > Country.COUNTRY_SOURCE_LOCATION)
&& isAirplaneModeOff() && mListener != null && isGeoCoderImplemented()) {
if (DEBUG) Slog.d(TAG, "run startLocationBasedDetector()");
// Start finding location when the source is less reliable than the
// location and the airplane mode is off (as geocoder will not
// work).
// TODO : Shall we give up starting the detector within a
// period of time?
startLocationBasedDetector(mLocationBasedCountryDetectionListener);
}
if (detectedCountry == null
|| detectedCountry.getSource() >= Country.COUNTRY_SOURCE_LOCATION) {
// Schedule the location refresh if the country source is
// not more reliable than the location or no country is
// found.
// TODO: Listen to the preference change of GPS, Wifi etc,
// and start detecting the country.
scheduleLocationRefresh();
} else {
// Cancel the location refresh once the current source is
// more reliable than the location.
cancelLocationRefresh();
stopLocationBasedDetector();
}
|
protected void | runAfterDetectionAsync(android.location.Country country, android.location.Country detectedCountry, boolean notifyChange, boolean startLocationBasedDetection)Run the tasks in the service's thread.
mHandler.post(new Runnable() {
@Override
public void run() {
runAfterDetection(
country, detectedCountry, notifyChange, startLocationBasedDetection);
}
});
|
private synchronized void | scheduleLocationRefresh()Schedule the next location refresh. We will do nothing if the scheduled task exists.
if (mLocationRefreshTimer != null) return;
if (DEBUG) {
Slog.d(TAG, "start periodic location refresh timer. Interval: "
+ LOCATION_REFRESH_INTERVAL);
}
mLocationRefreshTimer = new Timer();
mLocationRefreshTimer.schedule(new TimerTask() {
@Override
public void run() {
if (DEBUG) {
Slog.d(TAG, "periodic location refresh event. Starts detecting Country code");
}
mLocationRefreshTimer = null;
detectCountry(false, true);
}
}, LOCATION_REFRESH_INTERVAL);
|
public void | setCountryListener(android.location.CountryListener listener)
CountryListener prevListener = mListener;
mListener = listener;
if (mListener == null) {
// Stop listening all services
removePhoneStateListener();
stopLocationBasedDetector();
cancelLocationRefresh();
mStopTime = SystemClock.elapsedRealtime();
mTotalTime += mStopTime;
} else if (prevListener == null) {
addPhoneStateListener();
detectCountry(false, true);
mStartTime = SystemClock.elapsedRealtime();
mStopTime = 0;
mCountServiceStateChanges = 0;
}
|
private synchronized void | startLocationBasedDetector(android.location.CountryListener listener)Find the country from LocationProvider.
if (mLocationBasedCountryDetector != null) {
return;
}
if (DEBUG) {
Slog.d(TAG, "starts LocationBasedDetector to detect Country code via Location info "
+ "(e.g. GPS)");
}
mLocationBasedCountryDetector = createLocationBasedCountryDetector();
mLocationBasedCountryDetector.setCountryListener(listener);
mLocationBasedCountryDetector.detectCountry();
|
public void | stop()
// Note: this method in this subclass called only by tests.
Slog.i(TAG, "Stop the detector.");
cancelLocationRefresh();
removePhoneStateListener();
stopLocationBasedDetector();
mListener = null;
mStopped = true;
|
private synchronized void | stopLocationBasedDetector()
if (DEBUG) {
Slog.d(TAG, "tries to stop LocationBasedDetector "
+ "(current detector: " + mLocationBasedCountryDetector + ")");
}
if (mLocationBasedCountryDetector != null) {
mLocationBasedCountryDetector.stop();
mLocationBasedCountryDetector = null;
}
|
public java.lang.String | toString()
long currentTime = SystemClock.elapsedRealtime();
long currentSessionLength = 0;
StringBuilder sb = new StringBuilder();
sb.append("ComprehensiveCountryDetector{");
// The detector hasn't stopped yet --> still running
if (mStopTime == 0) {
currentSessionLength = currentTime - mStartTime;
sb.append("timeRunning=" + currentSessionLength + ", ");
} else {
// Otherwise, it has already stopped, so take the last session
sb.append("lastRunTimeLength=" + (mStopTime - mStartTime) + ", ");
}
sb.append("totalCountServiceStateChanges=" + mTotalCountServiceStateChanges + ", ");
sb.append("currentCountServiceStateChanges=" + mCountServiceStateChanges + ", ");
sb.append("totalTime=" + (mTotalTime + currentSessionLength) + ", ");
sb.append("currentTime=" + currentTime + ", ");
sb.append("countries=");
for (Country country : mDebugLogs) {
sb.append("\n " + country.toString());
}
sb.append("}");
return sb.toString();
|