LocationBasedCountryDetectorTest.java revision a550bdc84af70babb48091197bfb1b93d3671664
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 */
16package com.android.server.location;
17
18import android.location.Country;
19import android.location.CountryListener;
20import android.location.Location;
21import android.location.LocationListener;
22import android.location.LocationManager;
23import android.test.AndroidTestCase;
24
25import java.util.Arrays;
26import java.util.HashMap;
27import java.util.HashSet;
28import java.util.List;
29import java.util.Map;
30import java.util.Map.Entry;
31import java.util.Set;
32import java.util.Timer;
33
34public 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(countryListener.getCountry(), country);
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(countryListener.getCountry(), country);
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(countryListener.getCountry(), country);
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