LocationBasedCountryDetectorTest.java revision a58a8751b4c2ce457f0082a0baaee61312d56195
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 java.util.ArrayList;
19import java.util.List;
20import java.util.Timer;
21
22import android.location.Country;
23import android.location.CountryListener;
24import android.location.Location;
25import android.location.LocationListener;
26import android.test.AndroidTestCase;
27
28public class LocationBasedCountryDetectorTest extends AndroidTestCase {
29    private class TestCountryDetector extends LocationBasedCountryDetector {
30        public static final int TOTAL_PROVIDERS = 2;
31        protected Object countryFoundLocker = new Object();
32        protected boolean notifyCountry = false;
33        private final Location mLocation;
34        private final String mCountry;
35        private final long mQueryLocationTimeout;
36        private List<LocationListener> mListeners;
37
38        public TestCountryDetector(String country, String provider) {
39            this(country, provider, 1000 * 60 * 5);
40        }
41
42        public TestCountryDetector(String country, String provider, long queryLocationTimeout) {
43            super(getContext());
44            mCountry = country;
45            mLocation = new Location(provider);
46            mQueryLocationTimeout = queryLocationTimeout;
47            mListeners = new ArrayList<LocationListener>();
48        }
49
50        @Override
51        protected String getCountryFromLocation(Location location) {
52            synchronized (countryFoundLocker) {
53                if (!notifyCountry) {
54                    try {
55                        countryFoundLocker.wait();
56                    } catch (InterruptedException e) {
57                    }
58                }
59            }
60            if (mLocation.getProvider().endsWith(location.getProvider())) {
61                return mCountry;
62            } else {
63                return null;
64            }
65        }
66
67        @Override
68        protected Location getLastKnownLocation() {
69            return mLocation;
70        }
71
72        @Override
73        protected void registerEnabledProviders(List<LocationListener> listeners) {
74            mListeners.addAll(listeners);
75        }
76
77        @Override
78        protected void unregisterProviders(List<LocationListener> listeners) {
79            for (LocationListener listener : mLocationListeners) {
80                assertTrue(mListeners.remove(listener));
81            }
82        }
83
84        @Override
85        protected long getQueryLocationTimeout() {
86            return mQueryLocationTimeout;
87        }
88
89        @Override
90        protected int getTotalEnabledProviders() {
91            return TOTAL_PROVIDERS;
92        }
93
94        public void notifyLocationFound() {
95            // Listener could be removed in the notification.
96            LocationListener[] listeners = new LocationListener[mListeners.size()];
97            mLocationListeners.toArray(listeners);
98            for (LocationListener listener :listeners) {
99                listener.onLocationChanged(mLocation);
100            }
101        }
102
103        public int getListenersCount() {
104            return mListeners.size();
105        }
106
107        public void notifyCountryFound() {
108            synchronized (countryFoundLocker) {
109                notifyCountry = true;
110                countryFoundLocker.notify();
111            }
112        }
113
114        public Timer getTimer() {
115            return mTimer;
116        }
117
118        public Thread getQueryThread() {
119            return mQueryThread;
120        }
121    }
122
123    private class CountryListenerImpl implements CountryListener {
124        private boolean mNotified;
125        private String mCountryCode;
126        public void onCountryDetected(Country country) {
127            mNotified = true;
128            if (country != null) {
129                mCountryCode = country.getCountryIso();
130            }
131        }
132
133        public boolean notified() {
134            return mNotified;
135        }
136
137        public String getCountry() {
138            return mCountryCode;
139        }
140    }
141
142    public void testFindingCountry() {
143        final String country = "us";
144        final String provider = "Good";
145        CountryListenerImpl countryListener = new CountryListenerImpl();
146        TestCountryDetector detector = new TestCountryDetector(country, provider);
147        detector.setCountryListener(countryListener);
148        detector.detectCountry();
149        assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
150        detector.notifyLocationFound();
151        // All listeners should be unregistered
152        assertEquals(detector.getListenersCount(), 0);
153        assertNull(detector.getTimer());
154        Thread queryThread = waitForQueryThreadLaunched(detector);
155        detector.notifyCountryFound();
156        // Wait for query thread ending
157        waitForThreadEnding(queryThread);
158        // QueryThread should be set to NULL
159        assertNull(detector.getQueryThread());
160        assertTrue(countryListener.notified());
161        assertEquals(countryListener.getCountry(), country);
162    }
163
164    public void testFindingCountryCancelled() {
165        final String country = "us";
166        final String provider = "Good";
167        CountryListenerImpl countryListener = new CountryListenerImpl();
168        TestCountryDetector detector = new TestCountryDetector(country, provider);
169        detector.setCountryListener(countryListener);
170        detector.detectCountry();
171        assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
172        detector.notifyLocationFound();
173        // All listeners should be unregistered
174        assertEquals(detector.getListenersCount(), 0);
175        // The time should be stopped
176        assertNull(detector.getTimer());
177        Thread queryThread = waitForQueryThreadLaunched(detector);
178        detector.stop();
179        // There is no way to stop the thread, let's test it could be stopped, after get country
180        detector.notifyCountryFound();
181        // Wait for query thread ending
182        waitForThreadEnding(queryThread);
183        // QueryThread should be set to NULL
184        assertNull(detector.getQueryThread());
185        assertTrue(countryListener.notified());
186        assertEquals(countryListener.getCountry(), country);
187    }
188
189    public void testFindingLocationCancelled() {
190        final String country = "us";
191        final String provider = "Good";
192        CountryListenerImpl countryListener = new CountryListenerImpl();
193        TestCountryDetector detector = new TestCountryDetector(country, provider);
194        detector.setCountryListener(countryListener);
195        detector.detectCountry();
196        assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
197        detector.stop();
198        // All listeners should be unregistered
199        assertEquals(detector.getListenersCount(), 0);
200        // The time should be stopped
201        assertNull(detector.getTimer());
202        // QueryThread should still be NULL
203        assertNull(detector.getQueryThread());
204        assertFalse(countryListener.notified());
205    }
206
207    public void testFindingLocationFailed() {
208        final String country = "us";
209        final String provider = "Good";
210        long timeout = 1000;
211        TestCountryDetector detector = new TestCountryDetector(country, provider, timeout) {
212            @Override
213            protected Location getLastKnownLocation() {
214                return null;
215            }
216        };
217        CountryListenerImpl countryListener = new CountryListenerImpl();
218        detector.setCountryListener(countryListener);
219        detector.detectCountry();
220        assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
221        waitForTimerReset(detector);
222        // All listeners should be unregistered
223        assertEquals(detector.getListenersCount(), 0);
224        // QueryThread should still be NULL
225        assertNull(detector.getQueryThread());
226        assertTrue(countryListener.notified());
227        assertNull(countryListener.getCountry());
228    }
229
230    public void testFindingCountryFailed() {
231        final String country = "us";
232        final String provider = "Good";
233        TestCountryDetector detector = new TestCountryDetector(country, provider) {
234            @Override
235            protected String getCountryFromLocation(Location location) {
236                synchronized (countryFoundLocker) {
237                    if (! notifyCountry) {
238                        try {
239                            countryFoundLocker.wait();
240                        } catch (InterruptedException e) {
241                        }
242                    }
243                }
244                // We didn't find country.
245                return null;
246            }
247        };
248        CountryListenerImpl countryListener = new CountryListenerImpl();
249        detector.setCountryListener(countryListener);
250        detector.detectCountry();
251        assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
252        detector.notifyLocationFound();
253        // All listeners should be unregistered
254        assertEquals(detector.getListenersCount(), 0);
255        assertNull(detector.getTimer());
256        Thread queryThread = waitForQueryThreadLaunched(detector);
257        detector.notifyCountryFound();
258        // Wait for query thread ending
259        waitForThreadEnding(queryThread);
260        // QueryThread should be set to NULL
261        assertNull(detector.getQueryThread());
262        // CountryListener should be notified
263        assertTrue(countryListener.notified());
264        assertNull(countryListener.getCountry());
265    }
266
267    public void testFindingCountryWithLastKnownLocation() {
268        final String country = "us";
269        final String provider = "Good";
270        long timeout = 1000;
271        TestCountryDetector detector = new TestCountryDetector(country, provider, timeout);
272        CountryListenerImpl countryListener = new CountryListenerImpl();
273        detector.setCountryListener(countryListener);
274        detector.detectCountry();
275        assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
276        waitForTimerReset(detector);
277        // All listeners should be unregistered
278        assertEquals(detector.getListenersCount(), 0);
279        Thread queryThread = waitForQueryThreadLaunched(detector);
280        detector.notifyCountryFound();
281        // Wait for query thread ending
282        waitForThreadEnding(queryThread);
283        // QueryThread should be set to NULL
284        assertNull(detector.getQueryThread());
285        // CountryListener should be notified
286        assertTrue(countryListener.notified());
287        assertEquals(countryListener.getCountry(), country);
288    }
289
290    private void waitForTimerReset(TestCountryDetector detector) {
291        int count = 5;
292        long interval = 1000;
293        try {
294            while (count-- > 0 && detector.getTimer() != null) {
295                Thread.sleep(interval);
296            }
297        } catch (InterruptedException e) {
298        }
299        Timer timer = detector.getTimer();
300        assertTrue(timer == null);
301    }
302
303    private void waitForThreadEnding(Thread thread) {
304        try {
305            thread.join(5000);
306        } catch (InterruptedException e) {
307            e.printStackTrace();
308        }
309    }
310
311    private Thread waitForQueryThreadLaunched(TestCountryDetector detector) {
312        int count = 5;
313        long interval = 1000;
314        try {
315            while (count-- > 0 && detector.getQueryThread() == null) {
316                Thread.sleep(interval);
317            }
318        } catch (InterruptedException e) {
319        }
320        Thread thread = detector.getQueryThread();
321        assertTrue(thread != null);
322        return thread;
323    }
324}
325