Home | History | Annotate | Download | only in location
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 package com.android.server.location;
     17 
     18 import android.location.Country;
     19 import android.location.CountryListener;
     20 import android.location.Location;
     21 import android.location.LocationListener;
     22 import android.location.LocationManager;
     23 import android.test.AndroidTestCase;
     24 
     25 import java.util.Arrays;
     26 import java.util.HashMap;
     27 import java.util.HashSet;
     28 import java.util.List;
     29 import java.util.Map;
     30 import java.util.Map.Entry;
     31 import java.util.Set;
     32 import java.util.Timer;
     33 
     34 public class LocationBasedCountryDetectorTest extends AndroidTestCase {
     35     private static final List<String> sEnabledProviders = Arrays.asList(
     36             LocationManager.GPS_PROVIDER, LocationManager.PASSIVE_PROVIDER);
     37     private class TestCountryDetector extends LocationBasedCountryDetector {
     38         public static final int TOTAL_PROVIDERS = 2;
     39         protected Object countryFoundLocker = new Object();
     40         protected boolean notifyCountry = false;
     41         private final Location mLocation;
     42         private final String mCountry;
     43         private final long mQueryLocationTimeout;
     44         private Map<String, LocationListener> mListeners;
     45 
     46         public TestCountryDetector(String country, String provider) {
     47             this(country, provider, 1000 * 60 * 5);
     48         }
     49 
     50         public TestCountryDetector(String country, String provider, long queryLocationTimeout) {
     51             super(getContext());
     52             mCountry = country;
     53             mLocation = new Location(provider);
     54             mQueryLocationTimeout = queryLocationTimeout;
     55             mListeners = new HashMap<String, LocationListener>();
     56         }
     57 
     58         @Override
     59         protected String getCountryFromLocation(Location location) {
     60             synchronized (countryFoundLocker) {
     61                 if (!notifyCountry) {
     62                     try {
     63                         countryFoundLocker.wait();
     64                     } catch (InterruptedException e) {
     65                     }
     66                 }
     67             }
     68             if (mLocation.getProvider().endsWith(location.getProvider())) {
     69                 return mCountry;
     70             } else {
     71                 return null;
     72             }
     73         }
     74 
     75         @Override
     76         protected Location getLastKnownLocation() {
     77             return mLocation;
     78         }
     79 
     80         private Set<String> mAcceptableProviders;
     81 
     82         public void setAcceptableProvider(Set<String> acceptableProviders) {
     83             mAcceptableProviders = acceptableProviders;
     84         }
     85 
     86         @Override
     87         protected boolean isAcceptableProvider(String provider) {
     88             if (mAcceptableProviders != null) {
     89                 return mAcceptableProviders.contains(provider);
     90             } else {
     91                 return true;
     92             }
     93         }
     94 
     95         @Override
     96         protected void registerListener(String provider, LocationListener listener) {
     97             assertNotNull(provider);
     98             mListeners.put(provider, listener);
     99         }
    100 
    101         @Override
    102         protected void unregisterListener(LocationListener listener) {
    103             for (Entry<String, LocationListener> entry : mListeners.entrySet()) {
    104                 if (entry.getValue().equals(listener)) {
    105                     mListeners.remove(entry.getKey());
    106                     return;
    107                 }
    108             }
    109             fail("Not registered");
    110         }
    111 
    112         public Map<String, LocationListener> getListeners() {
    113             return mListeners;
    114         }
    115 
    116         @Override
    117         protected long getQueryLocationTimeout() {
    118             return mQueryLocationTimeout;
    119         }
    120 
    121         @Override
    122         protected List<String> getEnabledProviders() {
    123             return sEnabledProviders;
    124         }
    125 
    126         public void notifyLocationFound() {
    127             // Listener could be removed in the notification.
    128             LocationListener[] listeners = new LocationListener[mListeners.size()];
    129             mLocationListeners.toArray(listeners);
    130             for (LocationListener listener :listeners) {
    131                 listener.onLocationChanged(mLocation);
    132             }
    133         }
    134 
    135         public int getListenersCount() {
    136             return mListeners.size();
    137         }
    138 
    139         public void notifyCountryFound() {
    140             synchronized (countryFoundLocker) {
    141                 notifyCountry = true;
    142                 countryFoundLocker.notify();
    143             }
    144         }
    145 
    146         public Timer getTimer() {
    147             return mTimer;
    148         }
    149 
    150         public Thread getQueryThread() {
    151             return mQueryThread;
    152         }
    153     }
    154 
    155     private class CountryListenerImpl implements CountryListener {
    156         private boolean mNotified;
    157         private String mCountryCode;
    158         public void onCountryDetected(Country country) {
    159             mNotified = true;
    160             if (country != null) {
    161                 mCountryCode = country.getCountryIso();
    162             }
    163         }
    164 
    165         public boolean notified() {
    166             return mNotified;
    167         }
    168 
    169         public String getCountry() {
    170             return mCountryCode;
    171         }
    172     }
    173 
    174     public void testFindingCountry() {
    175         testFindingCountryCommon(null);
    176     }
    177 
    178     public void testFindingCountryWithAcceptableProvider() {
    179         testFindingCountryCommon(new HashSet<String>(Arrays.asList("passive")));
    180     }
    181 
    182     private void testFindingCountryCommon(Set<String> acceptableProviders) {
    183         final String country = "us";
    184         final String provider = "Good";
    185         CountryListenerImpl countryListener = new CountryListenerImpl();
    186         TestCountryDetector detector = new TestCountryDetector(country, provider);
    187 
    188         if (acceptableProviders != null) {
    189             detector.setAcceptableProvider(acceptableProviders);
    190         }
    191 
    192         detector.setCountryListener(countryListener);
    193         detector.detectCountry();
    194 
    195         if (acceptableProviders != null) {
    196             assertEquals(acceptableProviders.size(), detector.getListenersCount());
    197             Map<String, LocationListener> listeners = detector.getListeners();
    198             for (String acceptableProvider : acceptableProviders) {
    199                 assertTrue(listeners.containsKey(acceptableProvider));
    200             }
    201         } else {
    202             assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
    203         }
    204 
    205         detector.notifyLocationFound();
    206         // All listeners should be unregistered
    207         assertEquals(0, detector.getListenersCount());
    208         assertNull(detector.getTimer());
    209         Thread queryThread = waitForQueryThreadLaunched(detector);
    210         detector.notifyCountryFound();
    211         // Wait for query thread ending
    212         waitForThreadEnding(queryThread);
    213         // QueryThread should be set to NULL
    214         assertNull(detector.getQueryThread());
    215         assertTrue(countryListener.notified());
    216         assertEquals("us", countryListener.getCountry().toLowerCase());
    217     }
    218 
    219     public void testFindingCountryCancelled() {
    220         final String country = "us";
    221         final String provider = "Good";
    222         CountryListenerImpl countryListener = new CountryListenerImpl();
    223         TestCountryDetector detector = new TestCountryDetector(country, provider);
    224         detector.setCountryListener(countryListener);
    225         detector.detectCountry();
    226         assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
    227         detector.notifyLocationFound();
    228         // All listeners should be unregistered
    229         assertEquals(0, detector.getListenersCount());
    230         // The time should be stopped
    231         assertNull(detector.getTimer());
    232         Thread queryThread = waitForQueryThreadLaunched(detector);
    233         detector.stop();
    234         // There is no way to stop the thread, let's test it could be stopped, after get country
    235         detector.notifyCountryFound();
    236         // Wait for query thread ending
    237         waitForThreadEnding(queryThread);
    238         // QueryThread should be set to NULL
    239         assertNull(detector.getQueryThread());
    240         assertTrue(countryListener.notified());
    241         assertEquals("us", countryListener.getCountry().toLowerCase());
    242     }
    243 
    244     public void testFindingLocationCancelled() {
    245         final String country = "us";
    246         final String provider = "Good";
    247         CountryListenerImpl countryListener = new CountryListenerImpl();
    248         TestCountryDetector detector = new TestCountryDetector(country, provider);
    249         detector.setCountryListener(countryListener);
    250         detector.detectCountry();
    251         assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
    252         detector.stop();
    253         // All listeners should be unregistered
    254         assertEquals(0, detector.getListenersCount());
    255         // The time should be stopped
    256         assertNull(detector.getTimer());
    257         // QueryThread should still be NULL
    258         assertNull(detector.getQueryThread());
    259         assertFalse(countryListener.notified());
    260     }
    261 
    262     public void testFindingLocationFailed() {
    263         final String country = "us";
    264         final String provider = "Good";
    265         long timeout = 1000;
    266         TestCountryDetector detector = new TestCountryDetector(country, provider, timeout) {
    267             @Override
    268             protected Location getLastKnownLocation() {
    269                 return null;
    270             }
    271         };
    272         CountryListenerImpl countryListener = new CountryListenerImpl();
    273         detector.setCountryListener(countryListener);
    274         detector.detectCountry();
    275         assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
    276         waitForTimerReset(detector);
    277         // All listeners should be unregistered
    278         assertEquals(0, detector.getListenersCount());
    279         // QueryThread should still be NULL
    280         assertNull(detector.getQueryThread());
    281         assertTrue(countryListener.notified());
    282         assertNull(countryListener.getCountry());
    283     }
    284 
    285     public void testFindingCountryFailed() {
    286         final String country = "us";
    287         final String provider = "Good";
    288         TestCountryDetector detector = new TestCountryDetector(country, provider) {
    289             @Override
    290             protected String getCountryFromLocation(Location location) {
    291                 synchronized (countryFoundLocker) {
    292                     if (! notifyCountry) {
    293                         try {
    294                             countryFoundLocker.wait();
    295                         } catch (InterruptedException e) {
    296                         }
    297                     }
    298                 }
    299                 // We didn't find country.
    300                 return null;
    301             }
    302         };
    303         CountryListenerImpl countryListener = new CountryListenerImpl();
    304         detector.setCountryListener(countryListener);
    305         detector.detectCountry();
    306         assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
    307         detector.notifyLocationFound();
    308         // All listeners should be unregistered
    309         assertEquals(0, detector.getListenersCount());
    310         assertNull(detector.getTimer());
    311         Thread queryThread = waitForQueryThreadLaunched(detector);
    312         detector.notifyCountryFound();
    313         // Wait for query thread ending
    314         waitForThreadEnding(queryThread);
    315         // QueryThread should be set to NULL
    316         assertNull(detector.getQueryThread());
    317         // CountryListener should be notified
    318         assertTrue(countryListener.notified());
    319         assertNull(countryListener.getCountry());
    320     }
    321 
    322     public void testFindingCountryWithLastKnownLocation() {
    323         final String country = "us";
    324         final String provider = "Good";
    325         long timeout = 1000;
    326         TestCountryDetector detector = new TestCountryDetector(country, provider, timeout);
    327         CountryListenerImpl countryListener = new CountryListenerImpl();
    328         detector.setCountryListener(countryListener);
    329         detector.detectCountry();
    330         assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
    331         waitForTimerReset(detector);
    332         // All listeners should be unregistered
    333         assertEquals(0, detector.getListenersCount());
    334         Thread queryThread = waitForQueryThreadLaunched(detector);
    335         detector.notifyCountryFound();
    336         // Wait for query thread ending
    337         waitForThreadEnding(queryThread);
    338         // QueryThread should be set to NULL
    339         assertNull(detector.getQueryThread());
    340         // CountryListener should be notified
    341         assertTrue(countryListener.notified());
    342         assertEquals("us", countryListener.getCountry().toLowerCase());
    343     }
    344 
    345     private void waitForTimerReset(TestCountryDetector detector) {
    346         int count = 5;
    347         long interval = 1000;
    348         try {
    349             while (count-- > 0 && detector.getTimer() != null) {
    350                 Thread.sleep(interval);
    351             }
    352         } catch (InterruptedException e) {
    353         }
    354         Timer timer = detector.getTimer();
    355         assertTrue(timer == null);
    356     }
    357 
    358     private void waitForThreadEnding(Thread thread) {
    359         try {
    360             thread.join(5000);
    361         } catch (InterruptedException e) {
    362             e.printStackTrace();
    363         }
    364     }
    365 
    366     private Thread waitForQueryThreadLaunched(TestCountryDetector detector) {
    367         int count = 5;
    368         long interval = 1000;
    369         try {
    370             while (count-- > 0 && detector.getQueryThread() == null) {
    371                 Thread.sleep(interval);
    372             }
    373         } catch (InterruptedException e) {
    374         }
    375         Thread thread = detector.getQueryThread();
    376         assertTrue(thread != null);
    377         return thread;
    378     }
    379 }
    380