Loading location/java/android/location/Country.java +43 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.location; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import java.util.Locale; Loading Loading @@ -58,8 +59,14 @@ public class Country implements Parcelable { private final int mSource; private int mHashCode; /** * Time that this object was created (which we assume to be the time that the source was * consulted). This time is in milliseconds since boot up. */ private final long mTimestamp; /** * * @param countryIso the ISO 3166-1 two letters country code. * @param source where the countryIso came from, could be one of below * values Loading @@ -78,11 +85,23 @@ public class Country implements Parcelable { } mCountryIso = countryIso.toUpperCase(Locale.US); mSource = source; mTimestamp = SystemClock.elapsedRealtime(); } private Country(final String countryIso, final int source, long timestamp) { if (countryIso == null || source < COUNTRY_SOURCE_NETWORK || source > COUNTRY_SOURCE_LOCALE) { throw new IllegalArgumentException(); } mCountryIso = countryIso.toUpperCase(Locale.US); mSource = source; mTimestamp = timestamp; } public Country(Country country) { mCountryIso = country.mCountryIso; mSource = country.mSource; mTimestamp = country.mTimestamp; } /** Loading @@ -106,9 +125,17 @@ public class Country implements Parcelable { return mSource; } /** * Returns the time that this object was created (which we assume to be the time that the source * was consulted). */ public final long getTimestamp() { return mTimestamp; } public static final Parcelable.Creator<Country> CREATOR = new Parcelable.Creator<Country>() { public Country createFromParcel(Parcel in) { return new Country(in.readString(), in.readInt()); return new Country(in.readString(), in.readInt(), in.readLong()); } public Country[] newArray(int size) { Loading @@ -123,8 +150,14 @@ public class Country implements Parcelable { public void writeToParcel(Parcel parcel, int flags) { parcel.writeString(mCountryIso); parcel.writeInt(mSource); parcel.writeLong(mTimestamp); } /** * Returns true if this {@link Country} is equivalent to the given object. This ignores * the timestamp value and just checks for equivalence of countryIso and source values. * Returns false otherwise. */ @Override public boolean equals(Object object) { if (object == this) { Loading @@ -132,6 +165,7 @@ public class Country implements Parcelable { } if (object instanceof Country) { Country c = (Country) object; // No need to check the equivalence of the timestamp return mCountryIso.equals(c.getCountryIso()) && mSource == c.getSource(); } return false; Loading @@ -150,8 +184,8 @@ public class Country implements Parcelable { } /** * Compare the specified country to this country object ignoring the mSource * field, return true if the countryIso fields are equal * Compare the specified country to this country object ignoring the source * and timestamp fields, return true if the countryIso fields are equal * * @param country the country to compare * @return true if the specified country's countryIso field is equal to this Loading @@ -160,4 +194,9 @@ public class Country implements Parcelable { public boolean equalsIgnoreSource(Country country) { return country != null && mCountryIso.equals(country.getCountryIso()); } @Override public String toString() { return "Country {ISO=" + mCountryIso + ", source=" + mSource + ", time=" + mTimestamp + "}"; } } services/java/com/android/server/CountryDetectorService.java +21 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.HashMap; import com.android.server.location.ComprehensiveCountryDetector; Loading @@ -30,6 +32,8 @@ import android.os.IBinder; import android.os.Looper; import android.os.Process; import android.os.RemoteException; import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.Slog; /** Loading Loading @@ -75,7 +79,7 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run } } private final static String TAG = "CountryDetectorService"; private final static String TAG = "CountryDetector"; private final HashMap<IBinder, Receiver> mReceivers; private final Context mContext; Loading Loading @@ -201,4 +205,20 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run boolean isSystemReady() { return mSystemReady; } @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { try { final Printer p = new PrintWriterPrinter(fout); p.println("CountryDetectorService state:"); p.println(" Number of listeners=" + mReceivers.keySet().size()); if (mCountryDetector == null) { p.println(" ComprehensiveCountryDetector not initialized"); } else { p.println(" " + mCountryDetector.toString()); } } catch (Exception e) { Slog.e(TAG, "Failed to dump CountryDetectorService: ", e); } } } services/java/com/android/server/location/ComprehensiveCountryDetector.java +137 −34 Original line number Diff line number Diff line Loading @@ -20,16 +20,19 @@ import android.content.Context; import android.location.Country; import android.location.CountryListener; import android.location.Geocoder; import android.os.SystemClock; import android.provider.Settings; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import java.util.Locale; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentLinkedQueue; /** * This class is used to detect the country where the user is. The sources of Loading @@ -55,9 +58,14 @@ import java.util.TimerTask; */ public class ComprehensiveCountryDetector extends CountryDetectorBase { private final static String TAG = "ComprehensiveCountryDetector"; private final static String TAG = "CountryDetector"; /* package */ static final boolean DEBUG = false; /** * Max length of logs to maintain for debugging. */ private static final int MAX_LENGTH_DEBUG_LOGS = 20; /** * The refresh interval when the location based country was used */ Loading @@ -66,26 +74,58 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { protected CountryDetectorBase mLocationBasedCountryDetector; protected Timer mLocationRefreshTimer; private final int mPhoneType; private Country mCountry; private TelephonyManager mTelephonyManager; private final TelephonyManager mTelephonyManager; private Country mCountryFromLocation; private boolean mStopped = false; private ServiceState mLastState; private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { @Override public void onServiceStateChanged(ServiceState serviceState) { // TODO: Find out how often we will be notified, if this method is called too // many times, let's consider querying the network. Slog.d(TAG, "onServiceStateChanged"); // We only care the state change if (mLastState == null || mLastState.getState() != serviceState.getState()) { detectCountry(true, true); mLastState = new ServiceState(serviceState); } } }; private PhoneStateListener mPhoneStateListener; /** * List of the most recent country state changes for debugging. This should have * a max length of MAX_LENGTH_LOGS. */ private final ConcurrentLinkedQueue<Country> mDebugLogs = new ConcurrentLinkedQueue<Country>(); /** * Most 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 Country mLastCountryAddedToLogs; /** * Object used to synchronize access to {@link #mLastCountryAddedToLogs}. Be careful if * using it to synchronize anything else in this file. */ private final Object mObject = new Object(); /** * Start time of the current session for which the detector has been active. */ private long mStartTime; /** * Stop time of the most recent session for which the detector was active. */ private long mStopTime; /** * The sum of all the time intervals in which the detector was active. */ private long mTotalTime; /** * Number of {@link PhoneStateListener#onServiceStateChanged(ServiceState state)} events that * have occurred for the current session for which the detector has been active. */ private int mCountServiceStateChanges; /** * Total number of {@link PhoneStateListener#onServiceStateChanged(ServiceState state)} events * that have occurred for all time intervals in which the detector has been active. */ private int mTotalCountServiceStateChanges; /** * The listener for receiving the notification from LocationBasedCountryDetector. Loading @@ -104,7 +144,6 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { public ComprehensiveCountryDetector(Context context) { super(context); mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); mPhoneType = mTelephonyManager.getPhoneType(); } @Override Loading @@ -115,6 +154,7 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { @Override public void stop() { // Note: this method in this subclass called only by tests. Slog.i(TAG, "Stop the detector."); cancelLocationRefresh(); removePhoneStateListener(); Loading @@ -138,17 +178,50 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { if (result == null) { result = getLocaleCountry(); } addToLogs(result); return result; } /** * Attempt to add this {@link Country} to the debug logs. */ private void addToLogs(Country country) { 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 (Log.isLoggable(TAG, Log.DEBUG)) { Slog.d(TAG, country.toString()); } mDebugLogs.add(country); } 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; } /** * @return the country from the mobile network. */ protected Country getNetworkBasedCountry() { String countryIso = null; // TODO: The document says the result may be unreliable on CDMA networks. Shall we use // it on CDMA phone? We may test the Android primarily used countries. if (mPhoneType == TelephonyManager.PHONE_TYPE_GSM) { if (isNetworkCountryCodeAvailable()) { countryIso = mTelephonyManager.getNetworkCountryIso(); if (!TextUtils.isEmpty(countryIso)) { return new Country(countryIso, Country.COUNTRY_SOURCE_NETWORK); Loading Loading @@ -226,9 +299,14 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { removePhoneStateListener(); stopLocationBasedDetector(); cancelLocationRefresh(); mStopTime = SystemClock.elapsedRealtime(); mTotalTime += mStopTime; } else if (prevListener == null) { addPhoneStateListener(); detectCountry(false, true); mStartTime = SystemClock.elapsedRealtime(); mStopTime = 0; mCountServiceStateChanges = 0; } } Loading Loading @@ -316,9 +394,9 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { private void notifyIfCountryChanged(final Country country, final Country detectedCountry) { if (detectedCountry != null && mListener != null && (country == null || !country.equals(detectedCountry))) { Slog.d(TAG, "The country was changed from " + country != null ? country.getCountryIso() : country + " to " + detectedCountry.getCountryIso()); if (Log.isLoggable(TAG, Log.DEBUG)) { Slog.d(TAG, "" + country + " --> " + detectedCountry); } notifyListener(detectedCountry); } } Loading Loading @@ -356,20 +434,19 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { } protected synchronized void addPhoneStateListener() { if (mPhoneStateListener == null && mPhoneType == TelephonyManager.PHONE_TYPE_GSM) { mLastState = null; if (mPhoneStateListener == null) { mPhoneStateListener = new PhoneStateListener() { @Override public void onServiceStateChanged(ServiceState serviceState) { // TODO: Find out how often we will be notified, if this // method is called too // many times, let's consider querying the network. Slog.d(TAG, "onServiceStateChanged"); // We only care the state change if (mLastState == null || mLastState.getState() != serviceState.getState()) { detectCountry(true, true); mLastState = new 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); Loading @@ -386,4 +463,30 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { protected boolean isGeoCoderImplemented() { return Geocoder.isPresent(); } @Override public 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(); } } services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java +3 −3 Original line number Diff line number Diff line Loading @@ -213,7 +213,7 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { // QueryThread should be set to NULL assertNull(detector.getQueryThread()); assertTrue(countryListener.notified()); assertEquals(countryListener.getCountry(), country); assertEquals("us", countryListener.getCountry().toLowerCase()); } public void testFindingCountryCancelled() { Loading @@ -238,7 +238,7 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { // QueryThread should be set to NULL assertNull(detector.getQueryThread()); assertTrue(countryListener.notified()); assertEquals(countryListener.getCountry(), country); assertEquals("us", countryListener.getCountry().toLowerCase()); } public void testFindingLocationCancelled() { Loading Loading @@ -339,7 +339,7 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { assertNull(detector.getQueryThread()); // CountryListener should be notified assertTrue(countryListener.notified()); assertEquals(countryListener.getCountry(), country); assertEquals("us", countryListener.getCountry().toLowerCase()); } private void waitForTimerReset(TestCountryDetector detector) { Loading Loading
location/java/android/location/Country.java +43 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.location; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import java.util.Locale; Loading Loading @@ -58,8 +59,14 @@ public class Country implements Parcelable { private final int mSource; private int mHashCode; /** * Time that this object was created (which we assume to be the time that the source was * consulted). This time is in milliseconds since boot up. */ private final long mTimestamp; /** * * @param countryIso the ISO 3166-1 two letters country code. * @param source where the countryIso came from, could be one of below * values Loading @@ -78,11 +85,23 @@ public class Country implements Parcelable { } mCountryIso = countryIso.toUpperCase(Locale.US); mSource = source; mTimestamp = SystemClock.elapsedRealtime(); } private Country(final String countryIso, final int source, long timestamp) { if (countryIso == null || source < COUNTRY_SOURCE_NETWORK || source > COUNTRY_SOURCE_LOCALE) { throw new IllegalArgumentException(); } mCountryIso = countryIso.toUpperCase(Locale.US); mSource = source; mTimestamp = timestamp; } public Country(Country country) { mCountryIso = country.mCountryIso; mSource = country.mSource; mTimestamp = country.mTimestamp; } /** Loading @@ -106,9 +125,17 @@ public class Country implements Parcelable { return mSource; } /** * Returns the time that this object was created (which we assume to be the time that the source * was consulted). */ public final long getTimestamp() { return mTimestamp; } public static final Parcelable.Creator<Country> CREATOR = new Parcelable.Creator<Country>() { public Country createFromParcel(Parcel in) { return new Country(in.readString(), in.readInt()); return new Country(in.readString(), in.readInt(), in.readLong()); } public Country[] newArray(int size) { Loading @@ -123,8 +150,14 @@ public class Country implements Parcelable { public void writeToParcel(Parcel parcel, int flags) { parcel.writeString(mCountryIso); parcel.writeInt(mSource); parcel.writeLong(mTimestamp); } /** * Returns true if this {@link Country} is equivalent to the given object. This ignores * the timestamp value and just checks for equivalence of countryIso and source values. * Returns false otherwise. */ @Override public boolean equals(Object object) { if (object == this) { Loading @@ -132,6 +165,7 @@ public class Country implements Parcelable { } if (object instanceof Country) { Country c = (Country) object; // No need to check the equivalence of the timestamp return mCountryIso.equals(c.getCountryIso()) && mSource == c.getSource(); } return false; Loading @@ -150,8 +184,8 @@ public class Country implements Parcelable { } /** * Compare the specified country to this country object ignoring the mSource * field, return true if the countryIso fields are equal * Compare the specified country to this country object ignoring the source * and timestamp fields, return true if the countryIso fields are equal * * @param country the country to compare * @return true if the specified country's countryIso field is equal to this Loading @@ -160,4 +194,9 @@ public class Country implements Parcelable { public boolean equalsIgnoreSource(Country country) { return country != null && mCountryIso.equals(country.getCountryIso()); } @Override public String toString() { return "Country {ISO=" + mCountryIso + ", source=" + mSource + ", time=" + mTimestamp + "}"; } }
services/java/com/android/server/CountryDetectorService.java +21 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.HashMap; import com.android.server.location.ComprehensiveCountryDetector; Loading @@ -30,6 +32,8 @@ import android.os.IBinder; import android.os.Looper; import android.os.Process; import android.os.RemoteException; import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.Slog; /** Loading Loading @@ -75,7 +79,7 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run } } private final static String TAG = "CountryDetectorService"; private final static String TAG = "CountryDetector"; private final HashMap<IBinder, Receiver> mReceivers; private final Context mContext; Loading Loading @@ -201,4 +205,20 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run boolean isSystemReady() { return mSystemReady; } @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { try { final Printer p = new PrintWriterPrinter(fout); p.println("CountryDetectorService state:"); p.println(" Number of listeners=" + mReceivers.keySet().size()); if (mCountryDetector == null) { p.println(" ComprehensiveCountryDetector not initialized"); } else { p.println(" " + mCountryDetector.toString()); } } catch (Exception e) { Slog.e(TAG, "Failed to dump CountryDetectorService: ", e); } } }
services/java/com/android/server/location/ComprehensiveCountryDetector.java +137 −34 Original line number Diff line number Diff line Loading @@ -20,16 +20,19 @@ import android.content.Context; import android.location.Country; import android.location.CountryListener; import android.location.Geocoder; import android.os.SystemClock; import android.provider.Settings; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import java.util.Locale; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentLinkedQueue; /** * This class is used to detect the country where the user is. The sources of Loading @@ -55,9 +58,14 @@ import java.util.TimerTask; */ public class ComprehensiveCountryDetector extends CountryDetectorBase { private final static String TAG = "ComprehensiveCountryDetector"; private final static String TAG = "CountryDetector"; /* package */ static final boolean DEBUG = false; /** * Max length of logs to maintain for debugging. */ private static final int MAX_LENGTH_DEBUG_LOGS = 20; /** * The refresh interval when the location based country was used */ Loading @@ -66,26 +74,58 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { protected CountryDetectorBase mLocationBasedCountryDetector; protected Timer mLocationRefreshTimer; private final int mPhoneType; private Country mCountry; private TelephonyManager mTelephonyManager; private final TelephonyManager mTelephonyManager; private Country mCountryFromLocation; private boolean mStopped = false; private ServiceState mLastState; private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { @Override public void onServiceStateChanged(ServiceState serviceState) { // TODO: Find out how often we will be notified, if this method is called too // many times, let's consider querying the network. Slog.d(TAG, "onServiceStateChanged"); // We only care the state change if (mLastState == null || mLastState.getState() != serviceState.getState()) { detectCountry(true, true); mLastState = new ServiceState(serviceState); } } }; private PhoneStateListener mPhoneStateListener; /** * List of the most recent country state changes for debugging. This should have * a max length of MAX_LENGTH_LOGS. */ private final ConcurrentLinkedQueue<Country> mDebugLogs = new ConcurrentLinkedQueue<Country>(); /** * Most 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 Country mLastCountryAddedToLogs; /** * Object used to synchronize access to {@link #mLastCountryAddedToLogs}. Be careful if * using it to synchronize anything else in this file. */ private final Object mObject = new Object(); /** * Start time of the current session for which the detector has been active. */ private long mStartTime; /** * Stop time of the most recent session for which the detector was active. */ private long mStopTime; /** * The sum of all the time intervals in which the detector was active. */ private long mTotalTime; /** * Number of {@link PhoneStateListener#onServiceStateChanged(ServiceState state)} events that * have occurred for the current session for which the detector has been active. */ private int mCountServiceStateChanges; /** * Total number of {@link PhoneStateListener#onServiceStateChanged(ServiceState state)} events * that have occurred for all time intervals in which the detector has been active. */ private int mTotalCountServiceStateChanges; /** * The listener for receiving the notification from LocationBasedCountryDetector. Loading @@ -104,7 +144,6 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { public ComprehensiveCountryDetector(Context context) { super(context); mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); mPhoneType = mTelephonyManager.getPhoneType(); } @Override Loading @@ -115,6 +154,7 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { @Override public void stop() { // Note: this method in this subclass called only by tests. Slog.i(TAG, "Stop the detector."); cancelLocationRefresh(); removePhoneStateListener(); Loading @@ -138,17 +178,50 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { if (result == null) { result = getLocaleCountry(); } addToLogs(result); return result; } /** * Attempt to add this {@link Country} to the debug logs. */ private void addToLogs(Country country) { 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 (Log.isLoggable(TAG, Log.DEBUG)) { Slog.d(TAG, country.toString()); } mDebugLogs.add(country); } 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; } /** * @return the country from the mobile network. */ protected Country getNetworkBasedCountry() { String countryIso = null; // TODO: The document says the result may be unreliable on CDMA networks. Shall we use // it on CDMA phone? We may test the Android primarily used countries. if (mPhoneType == TelephonyManager.PHONE_TYPE_GSM) { if (isNetworkCountryCodeAvailable()) { countryIso = mTelephonyManager.getNetworkCountryIso(); if (!TextUtils.isEmpty(countryIso)) { return new Country(countryIso, Country.COUNTRY_SOURCE_NETWORK); Loading Loading @@ -226,9 +299,14 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { removePhoneStateListener(); stopLocationBasedDetector(); cancelLocationRefresh(); mStopTime = SystemClock.elapsedRealtime(); mTotalTime += mStopTime; } else if (prevListener == null) { addPhoneStateListener(); detectCountry(false, true); mStartTime = SystemClock.elapsedRealtime(); mStopTime = 0; mCountServiceStateChanges = 0; } } Loading Loading @@ -316,9 +394,9 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { private void notifyIfCountryChanged(final Country country, final Country detectedCountry) { if (detectedCountry != null && mListener != null && (country == null || !country.equals(detectedCountry))) { Slog.d(TAG, "The country was changed from " + country != null ? country.getCountryIso() : country + " to " + detectedCountry.getCountryIso()); if (Log.isLoggable(TAG, Log.DEBUG)) { Slog.d(TAG, "" + country + " --> " + detectedCountry); } notifyListener(detectedCountry); } } Loading Loading @@ -356,20 +434,19 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { } protected synchronized void addPhoneStateListener() { if (mPhoneStateListener == null && mPhoneType == TelephonyManager.PHONE_TYPE_GSM) { mLastState = null; if (mPhoneStateListener == null) { mPhoneStateListener = new PhoneStateListener() { @Override public void onServiceStateChanged(ServiceState serviceState) { // TODO: Find out how often we will be notified, if this // method is called too // many times, let's consider querying the network. Slog.d(TAG, "onServiceStateChanged"); // We only care the state change if (mLastState == null || mLastState.getState() != serviceState.getState()) { detectCountry(true, true); mLastState = new 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); Loading @@ -386,4 +463,30 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { protected boolean isGeoCoderImplemented() { return Geocoder.isPresent(); } @Override public 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(); } }
services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java +3 −3 Original line number Diff line number Diff line Loading @@ -213,7 +213,7 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { // QueryThread should be set to NULL assertNull(detector.getQueryThread()); assertTrue(countryListener.notified()); assertEquals(countryListener.getCountry(), country); assertEquals("us", countryListener.getCountry().toLowerCase()); } public void testFindingCountryCancelled() { Loading @@ -238,7 +238,7 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { // QueryThread should be set to NULL assertNull(detector.getQueryThread()); assertTrue(countryListener.notified()); assertEquals(countryListener.getCountry(), country); assertEquals("us", countryListener.getCountry().toLowerCase()); } public void testFindingLocationCancelled() { Loading Loading @@ -339,7 +339,7 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { assertNull(detector.getQueryThread()); // CountryListener should be notified assertTrue(countryListener.notified()); assertEquals(countryListener.getCountry(), country); assertEquals("us", countryListener.getCountry().toLowerCase()); } private void waitForTimerReset(TestCountryDetector detector) { Loading