Merge "Use passive provider for location based country detection"
This commit is contained in:
committed by
Android (Google) Code Review
commit
efe2a0e6ac
@@ -1310,7 +1310,7 @@ public class LocationManager {
|
||||
* @param listener GPS status listener object to register
|
||||
*
|
||||
* @return true if the listener was successfully added
|
||||
*
|
||||
*
|
||||
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
|
||||
*/
|
||||
public boolean addGpsStatusListener(GpsStatus.Listener listener) {
|
||||
@@ -1434,7 +1434,7 @@ public class LocationManager {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used by NetInitiatedActivity to report user response
|
||||
* for network initiated GPS fix requests.
|
||||
@@ -1449,5 +1449,5 @@ public class LocationManager {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ import java.util.TimerTask;
|
||||
public class ComprehensiveCountryDetector extends CountryDetectorBase {
|
||||
|
||||
private final static String TAG = "ComprehensiveCountryDetector";
|
||||
/* package */ static final boolean DEBUG = false;
|
||||
|
||||
/**
|
||||
* The refresh interval when the location based country was used
|
||||
@@ -90,7 +91,9 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
|
||||
* The listener for receiving the notification from LocationBasedCountryDetector.
|
||||
*/
|
||||
private CountryListener mLocationBasedCountryDetectionListener = new CountryListener() {
|
||||
@Override
|
||||
public void onCountryDetected(Country country) {
|
||||
if (DEBUG) Slog.d(TAG, "Country detected via LocationBasedCountryDetector");
|
||||
mCountryFromLocation = country;
|
||||
// Don't start the LocationBasedCountryDetector.
|
||||
detectCountry(true, false);
|
||||
@@ -206,6 +209,7 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
|
||||
protected void runAfterDetectionAsync(final Country country, final Country detectedCountry,
|
||||
final boolean notifyChange, final boolean startLocationBasedDetection) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runAfterDetection(
|
||||
country, detectedCountry, notifyChange, startLocationBasedDetection);
|
||||
@@ -233,9 +237,20 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
|
||||
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).
|
||||
@@ -266,12 +281,20 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
|
||||
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();
|
||||
}
|
||||
|
||||
private synchronized void stopLocationBasedDetector() {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "tries to stop LocationBasedDetector "
|
||||
+ "(current detector: " + mLocationBasedCountryDetector + ")");
|
||||
}
|
||||
if (mLocationBasedCountryDetector != null) {
|
||||
mLocationBasedCountryDetector.stop();
|
||||
mLocationBasedCountryDetector = null;
|
||||
@@ -305,10 +328,17 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
|
||||
*/
|
||||
private synchronized void scheduleLocationRefresh() {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -16,12 +16,6 @@
|
||||
|
||||
package com.android.server.location;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Address;
|
||||
import android.location.Country;
|
||||
@@ -32,6 +26,12 @@ import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.util.Slog;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* This class detects which country the user currently is in through the enabled
|
||||
* location providers and the GeoCoder
|
||||
@@ -86,24 +86,23 @@ public class LocationBasedCountryDetector extends CountryDetectorBase {
|
||||
return country;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the listeners with the location providers
|
||||
*/
|
||||
protected void registerEnabledProviders(List<LocationListener> listeners) {
|
||||
int total = listeners.size();
|
||||
for (int i = 0; i< total; i++) {
|
||||
mLocationManager.requestLocationUpdates(
|
||||
mEnabledProviders.get(i), 0, 0, listeners.get(i));
|
||||
}
|
||||
protected boolean isAcceptableProvider(String provider) {
|
||||
// We don't want to actively initiate a location fix here (with gps or network providers).
|
||||
return LocationManager.PASSIVE_PROVIDER.equals(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the listeners with the location providers
|
||||
* Register a listener with a provider name
|
||||
*/
|
||||
protected void unregisterProviders(List<LocationListener> listeners) {
|
||||
for (LocationListener listener : listeners) {
|
||||
mLocationManager.removeUpdates(listener);
|
||||
}
|
||||
protected void registerListener(String provider, LocationListener listener) {
|
||||
mLocationManager.requestLocationUpdates(provider, 0, 0, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister an already registered listener
|
||||
*/
|
||||
protected void unregisterListener(LocationListener listener) {
|
||||
mLocationManager.removeUpdates(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,14 +129,11 @@ public class LocationBasedCountryDetector extends CountryDetectorBase {
|
||||
return QUERY_LOCATION_TIMEOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the total number of enabled location providers
|
||||
*/
|
||||
protected int getTotalEnabledProviders() {
|
||||
protected List<String> getEnabledProviders() {
|
||||
if (mEnabledProviders == null) {
|
||||
mEnabledProviders = mLocationManager.getProviders(true);
|
||||
}
|
||||
return mEnabledProviders.size();
|
||||
return mEnabledProviders;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,27 +148,36 @@ public class LocationBasedCountryDetector extends CountryDetectorBase {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
// Request the location from all enabled providers.
|
||||
int totalProviders = getTotalEnabledProviders();
|
||||
List<String> enabledProviders = getEnabledProviders();
|
||||
int totalProviders = enabledProviders.size();
|
||||
if (totalProviders > 0) {
|
||||
mLocationListeners = new ArrayList<LocationListener>(totalProviders);
|
||||
for (int i = 0; i < totalProviders; i++) {
|
||||
LocationListener listener = new LocationListener () {
|
||||
public void onLocationChanged(Location location) {
|
||||
if (location != null) {
|
||||
LocationBasedCountryDetector.this.stop();
|
||||
queryCountryCode(location);
|
||||
String provider = enabledProviders.get(i);
|
||||
if (isAcceptableProvider(provider)) {
|
||||
LocationListener listener = new LocationListener () {
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
if (location != null) {
|
||||
LocationBasedCountryDetector.this.stop();
|
||||
queryCountryCode(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void onProviderDisabled(String provider) {
|
||||
}
|
||||
public void onProviderEnabled(String provider) {
|
||||
}
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
}
|
||||
};
|
||||
mLocationListeners.add(listener);
|
||||
@Override
|
||||
public void onProviderDisabled(String provider) {
|
||||
}
|
||||
@Override
|
||||
public void onProviderEnabled(String provider) {
|
||||
}
|
||||
@Override
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
}
|
||||
};
|
||||
mLocationListeners.add(listener);
|
||||
registerListener(provider, listener);
|
||||
}
|
||||
}
|
||||
registerEnabledProviders(mLocationListeners);
|
||||
|
||||
mTimer = new Timer();
|
||||
mTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
@@ -197,7 +202,9 @@ public class LocationBasedCountryDetector extends CountryDetectorBase {
|
||||
@Override
|
||||
public synchronized void stop() {
|
||||
if (mLocationListeners != null) {
|
||||
unregisterProviders(mLocationListeners);
|
||||
for (LocationListener listener : mLocationListeners) {
|
||||
unregisterListener(listener);
|
||||
}
|
||||
mLocationListeners = null;
|
||||
}
|
||||
if (mTimer != null) {
|
||||
@@ -216,6 +223,7 @@ public class LocationBasedCountryDetector extends CountryDetectorBase {
|
||||
}
|
||||
if (mQueryThread != null) return;
|
||||
mQueryThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String countryIso = null;
|
||||
if (location != null) {
|
||||
|
||||
@@ -15,17 +15,25 @@
|
||||
*/
|
||||
package com.android.server.location;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
|
||||
import android.location.Country;
|
||||
import android.location.CountryListener;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
|
||||
public class LocationBasedCountryDetectorTest extends AndroidTestCase {
|
||||
private static final List<String> sEnabledProviders = Arrays.asList(
|
||||
LocationManager.GPS_PROVIDER, LocationManager.PASSIVE_PROVIDER);
|
||||
private class TestCountryDetector extends LocationBasedCountryDetector {
|
||||
public static final int TOTAL_PROVIDERS = 2;
|
||||
protected Object countryFoundLocker = new Object();
|
||||
@@ -33,7 +41,7 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
|
||||
private final Location mLocation;
|
||||
private final String mCountry;
|
||||
private final long mQueryLocationTimeout;
|
||||
private List<LocationListener> mListeners;
|
||||
private Map<String, LocationListener> mListeners;
|
||||
|
||||
public TestCountryDetector(String country, String provider) {
|
||||
this(country, provider, 1000 * 60 * 5);
|
||||
@@ -44,7 +52,7 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
|
||||
mCountry = country;
|
||||
mLocation = new Location(provider);
|
||||
mQueryLocationTimeout = queryLocationTimeout;
|
||||
mListeners = new ArrayList<LocationListener>();
|
||||
mListeners = new HashMap<String, LocationListener>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,26 +77,50 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
|
||||
return mLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerEnabledProviders(List<LocationListener> listeners) {
|
||||
mListeners.addAll(listeners);
|
||||
private Set<String> mAcceptableProviders;
|
||||
|
||||
public void setAcceptableProvider(Set<String> acceptableProviders) {
|
||||
mAcceptableProviders = acceptableProviders;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void unregisterProviders(List<LocationListener> listeners) {
|
||||
for (LocationListener listener : mLocationListeners) {
|
||||
assertTrue(mListeners.remove(listener));
|
||||
protected boolean isAcceptableProvider(String provider) {
|
||||
if (mAcceptableProviders != null) {
|
||||
return mAcceptableProviders.contains(provider);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerListener(String provider, LocationListener listener) {
|
||||
assertNotNull(provider);
|
||||
mListeners.put(provider, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void unregisterListener(LocationListener listener) {
|
||||
for (Entry<String, LocationListener> entry : mListeners.entrySet()) {
|
||||
if (entry.getValue().equals(listener)) {
|
||||
mListeners.remove(entry.getKey());
|
||||
return;
|
||||
}
|
||||
}
|
||||
fail("Not registered");
|
||||
}
|
||||
|
||||
public Map<String, LocationListener> getListeners() {
|
||||
return mListeners;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getQueryLocationTimeout() {
|
||||
return mQueryLocationTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTotalEnabledProviders() {
|
||||
return TOTAL_PROVIDERS;
|
||||
protected List<String> getEnabledProviders() {
|
||||
return sEnabledProviders;
|
||||
}
|
||||
|
||||
public void notifyLocationFound() {
|
||||
@@ -140,16 +172,39 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
public void testFindingCountry() {
|
||||
testFindingCountryCommon(null);
|
||||
}
|
||||
|
||||
public void testFindingCountryWithAcceptableProvider() {
|
||||
testFindingCountryCommon(new HashSet<String>(Arrays.asList("passive")));
|
||||
}
|
||||
|
||||
private void testFindingCountryCommon(Set<String> acceptableProviders) {
|
||||
final String country = "us";
|
||||
final String provider = "Good";
|
||||
CountryListenerImpl countryListener = new CountryListenerImpl();
|
||||
TestCountryDetector detector = new TestCountryDetector(country, provider);
|
||||
|
||||
if (acceptableProviders != null) {
|
||||
detector.setAcceptableProvider(acceptableProviders);
|
||||
}
|
||||
|
||||
detector.setCountryListener(countryListener);
|
||||
detector.detectCountry();
|
||||
assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
|
||||
|
||||
if (acceptableProviders != null) {
|
||||
assertEquals(acceptableProviders.size(), detector.getListenersCount());
|
||||
Map<String, LocationListener> listeners = detector.getListeners();
|
||||
for (String acceptableProvider : acceptableProviders) {
|
||||
assertTrue(listeners.containsKey(acceptableProvider));
|
||||
}
|
||||
} else {
|
||||
assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
|
||||
}
|
||||
|
||||
detector.notifyLocationFound();
|
||||
// All listeners should be unregistered
|
||||
assertEquals(detector.getListenersCount(), 0);
|
||||
assertEquals(0, detector.getListenersCount());
|
||||
assertNull(detector.getTimer());
|
||||
Thread queryThread = waitForQueryThreadLaunched(detector);
|
||||
detector.notifyCountryFound();
|
||||
@@ -168,10 +223,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
|
||||
TestCountryDetector detector = new TestCountryDetector(country, provider);
|
||||
detector.setCountryListener(countryListener);
|
||||
detector.detectCountry();
|
||||
assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
|
||||
assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
|
||||
detector.notifyLocationFound();
|
||||
// All listeners should be unregistered
|
||||
assertEquals(detector.getListenersCount(), 0);
|
||||
assertEquals(0, detector.getListenersCount());
|
||||
// The time should be stopped
|
||||
assertNull(detector.getTimer());
|
||||
Thread queryThread = waitForQueryThreadLaunched(detector);
|
||||
@@ -193,10 +248,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
|
||||
TestCountryDetector detector = new TestCountryDetector(country, provider);
|
||||
detector.setCountryListener(countryListener);
|
||||
detector.detectCountry();
|
||||
assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
|
||||
assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
|
||||
detector.stop();
|
||||
// All listeners should be unregistered
|
||||
assertEquals(detector.getListenersCount(), 0);
|
||||
assertEquals(0, detector.getListenersCount());
|
||||
// The time should be stopped
|
||||
assertNull(detector.getTimer());
|
||||
// QueryThread should still be NULL
|
||||
@@ -217,10 +272,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
|
||||
CountryListenerImpl countryListener = new CountryListenerImpl();
|
||||
detector.setCountryListener(countryListener);
|
||||
detector.detectCountry();
|
||||
assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
|
||||
assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
|
||||
waitForTimerReset(detector);
|
||||
// All listeners should be unregistered
|
||||
assertEquals(detector.getListenersCount(), 0);
|
||||
assertEquals(0, detector.getListenersCount());
|
||||
// QueryThread should still be NULL
|
||||
assertNull(detector.getQueryThread());
|
||||
assertTrue(countryListener.notified());
|
||||
@@ -248,10 +303,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
|
||||
CountryListenerImpl countryListener = new CountryListenerImpl();
|
||||
detector.setCountryListener(countryListener);
|
||||
detector.detectCountry();
|
||||
assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
|
||||
assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
|
||||
detector.notifyLocationFound();
|
||||
// All listeners should be unregistered
|
||||
assertEquals(detector.getListenersCount(), 0);
|
||||
assertEquals(0, detector.getListenersCount());
|
||||
assertNull(detector.getTimer());
|
||||
Thread queryThread = waitForQueryThreadLaunched(detector);
|
||||
detector.notifyCountryFound();
|
||||
@@ -272,10 +327,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
|
||||
CountryListenerImpl countryListener = new CountryListenerImpl();
|
||||
detector.setCountryListener(countryListener);
|
||||
detector.detectCountry();
|
||||
assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
|
||||
assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
|
||||
waitForTimerReset(detector);
|
||||
// All listeners should be unregistered
|
||||
assertEquals(detector.getListenersCount(), 0);
|
||||
assertEquals(0, detector.getListenersCount());
|
||||
Thread queryThread = waitForQueryThreadLaunched(detector);
|
||||
detector.notifyCountryFound();
|
||||
// Wait for query thread ending
|
||||
|
||||
Reference in New Issue
Block a user