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