diff options
| author | 2019-12-17 16:40:47 -0800 | |
|---|---|---|
| committer | 2020-01-10 00:12:11 +0000 | |
| commit | 611bad95564695d6b5fa87efa89c9a4e1979dc80 (patch) | |
| tree | 61d438ba30cfa6d22ff8544be1f2d8385a97fde7 | |
| parent | b43b52a2e138b7648005ba8187947da2bd749d73 (diff) | |
Refactor CountryDetectorService
Clean-up the test to use Mockito instead of the deprecated
AndroidTestCase, also getting rid of 1.5s of Thread.sleep.
No logic change.
Bug: 141626568
Test: atest CountryDetectorServiceTest
Merged-in: Ic0782b1ffcd1dcb30b9f1d91b37521d1f9887f03
Change-Id: Ic0782b1ffcd1dcb30b9f1d91b37521d1f9887f03
(cherry picked from commit 50361687ba6bc20877af43eb5367a5ba3a2911df)
3 files changed, 129 insertions, 91 deletions
diff --git a/services/core/java/com/android/server/CountryDetectorService.java b/services/core/java/com/android/server/CountryDetectorService.java index d8a2fe35c7e8..861c731c69e0 100644 --- a/services/core/java/com/android/server/CountryDetectorService.java +++ b/services/core/java/com/android/server/CountryDetectorService.java @@ -16,14 +16,6 @@ package com.android.server; -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.HashMap; - -import com.android.internal.os.BackgroundThread; -import com.android.internal.util.DumpUtils; -import com.android.server.location.ComprehensiveCountryDetector; - import android.content.Context; import android.location.Country; import android.location.CountryListener; @@ -36,17 +28,25 @@ import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.os.BackgroundThread; +import com.android.internal.util.DumpUtils; +import com.android.server.location.ComprehensiveCountryDetector; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.HashMap; + /** - * This class detects the country that the user is in through - * {@link ComprehensiveCountryDetector}. + * This class detects the country that the user is in through {@link ComprehensiveCountryDetector}. * * @hide */ -public class CountryDetectorService extends ICountryDetector.Stub implements Runnable { +public class CountryDetectorService extends ICountryDetector.Stub { /** - * The class represents the remote listener, it will also removes itself - * from listener list when the remote process was died. + * The class represents the remote listener, it will also removes itself from listener list when + * the remote process was died. */ private final class Receiver implements IBinder.DeathRecipient { private final ICountryListener mListener; @@ -79,9 +79,11 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run } } - private final static String TAG = "CountryDetector"; + private static final String TAG = "CountryDetector"; - /** Whether to dump the state of the country detector service to bugreports */ + /** + * Whether to dump the state of the country detector service to bugreports + */ private static final boolean DEBUG = false; private final HashMap<IBinder, Receiver> mReceivers; @@ -92,15 +94,21 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run private CountryListener mLocationBasedDetectorListener; public CountryDetectorService(Context context) { + this(context, BackgroundThread.getHandler()); + } + + @VisibleForTesting + CountryDetectorService(Context context, Handler handler) { super(); - mReceivers = new HashMap<IBinder, Receiver>(); + mReceivers = new HashMap<>(); mContext = context; + mHandler = handler; } @Override public Country detectCountry() { if (!mSystemReady) { - return null; // server not yet active + return null; // server not yet active } else { return mCountryDetector.detectCountry(); } @@ -154,9 +162,8 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run } } - protected void notifyReceivers(Country country) { - synchronized(mReceivers) { + synchronized (mReceivers) { for (Receiver receiver : mReceivers.values()) { try { receiver.getListener().onCountryDetected(country); @@ -170,38 +177,23 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run void systemRunning() { // Shall we wait for the initialization finish. - BackgroundThread.getHandler().post(this); + mHandler.post( + () -> { + initialize(); + mSystemReady = true; + }); } private void initialize() { mCountryDetector = new ComprehensiveCountryDetector(mContext); - mLocationBasedDetectorListener = new CountryListener() { - public void onCountryDetected(final Country country) { - mHandler.post(new Runnable() { - public void run() { - notifyReceivers(country); - } - }); - } - }; - } - - public void run() { - mHandler = new Handler(); - initialize(); - mSystemReady = true; + mLocationBasedDetectorListener = country -> mHandler.post(() -> notifyReceivers(country)); } protected void setCountryListener(final CountryListener listener) { - mHandler.post(new Runnable() { - @Override - public void run() { - mCountryDetector.setCountryListener(listener); - } - }); + mHandler.post(() -> mCountryDetector.setCountryListener(listener)); } - // For testing + @VisibleForTesting boolean isSystemReady() { return mSystemReady; } diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index 3edbd7ee6eed..d42042d3641d 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -28,6 +28,7 @@ android_test { "services.net", "services.usage", "guava", + "androidx.test.core", "androidx.test.runner", "androidx.test.rules", "mockito-target-minus-junit4", diff --git a/services/tests/servicestests/src/com/android/server/CountryDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/CountryDetectorServiceTest.java index 192c50c7dc19..e9c5ce7127de 100644 --- a/services/tests/servicestests/src/com/android/server/CountryDetectorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/CountryDetectorServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -11,28 +11,48 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ package com.android.server; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doAnswer; + import android.content.Context; import android.location.Country; import android.location.CountryListener; import android.location.ICountryListener; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; import android.os.RemoteException; -import android.test.AndroidTestCase; -public class CountryDetectorServiceTest extends AndroidTestCase { - private class CountryListenerTester extends ICountryListener.Stub { +import androidx.test.core.app.ApplicationProvider; + +import com.google.common.truth.Expect; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class CountryDetectorServiceTest { + + private static class CountryListenerTester extends ICountryListener.Stub { private Country mCountry; @Override - public void onCountryDetected(Country country) throws RemoteException { + public void onCountryDetected(Country country) { mCountry = country; } - public Country getCountry() { + Country getCountry() { return mCountry; } @@ -41,12 +61,11 @@ public class CountryDetectorServiceTest extends AndroidTestCase { } } - private class CountryDetectorServiceTester extends CountryDetectorService { - + private static class CountryDetectorServiceTester extends CountryDetectorService { private CountryListener mListener; - public CountryDetectorServiceTester(Context context) { - super(context); + CountryDetectorServiceTester(Context context, Handler handler) { + super(context, handler); } @Override @@ -59,51 +78,77 @@ public class CountryDetectorServiceTest extends AndroidTestCase { mListener = listener; } - public boolean isListenerSet() { + boolean isListenerSet() { return mListener != null; } } - public void testAddRemoveListener() throws RemoteException { - CountryDetectorServiceTester serviceTester = new CountryDetectorServiceTester(getContext()); - serviceTester.systemRunning(); - waitForSystemReady(serviceTester); - CountryListenerTester listenerTester = new CountryListenerTester(); - serviceTester.addCountryListener(listenerTester); - assertTrue(serviceTester.isListenerSet()); - serviceTester.removeCountryListener(listenerTester); - assertFalse(serviceTester.isListenerSet()); + @Rule + public final Expect expect = Expect.create(); + @Spy + private Context mContext = ApplicationProvider.getApplicationContext(); + @Spy + private Handler mHandler = new Handler(Looper.myLooper()); + private CountryDetectorServiceTester mCountryDetectorService; + + @BeforeClass + public static void oneTimeInitialization() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } } - public void testNotifyListeners() throws RemoteException { - CountryDetectorServiceTester serviceTester = new CountryDetectorServiceTester(getContext()); - CountryListenerTester listenerTesterA = new CountryListenerTester(); - CountryListenerTester listenerTesterB = new CountryListenerTester(); - Country country = new Country("US", Country.COUNTRY_SOURCE_NETWORK); - serviceTester.systemRunning(); - waitForSystemReady(serviceTester); - serviceTester.addCountryListener(listenerTesterA); - serviceTester.addCountryListener(listenerTesterB); - serviceTester.notifyReceivers(country); - assertTrue(serviceTester.isListenerSet()); - assertTrue(listenerTesterA.isNotified()); - assertTrue(listenerTesterB.isNotified()); - serviceTester.removeCountryListener(listenerTesterA); - serviceTester.removeCountryListener(listenerTesterB); - assertFalse(serviceTester.isListenerSet()); + @Before + public void setUp() { + mCountryDetectorService = new CountryDetectorServiceTester(mContext, mHandler); + + // Immediately invoke run on the Runnable posted to the handler + doAnswer(invocation -> { + Message message = invocation.getArgument(0); + message.getCallback().run(); + return true; + }).when(mHandler).sendMessageAtTime(any(Message.class), anyLong()); } - private void waitForSystemReady(CountryDetectorService service) { - int count = 5; - while (count-- > 0) { - try { - Thread.sleep(500); - } catch (Exception e) { - } - if (service.isSystemReady()) { - return; - } - } - throw new RuntimeException("Wait System Ready timeout"); + @Test + public void countryListener_add_successful() throws RemoteException { + CountryListenerTester countryListener = new CountryListenerTester(); + + mCountryDetectorService.systemRunning(); + expect.that(mCountryDetectorService.isListenerSet()).isFalse(); + mCountryDetectorService.addCountryListener(countryListener); + + expect.that(mCountryDetectorService.isListenerSet()).isTrue(); + } + + @Test + public void countryListener_remove_successful() throws RemoteException { + CountryListenerTester countryListener = new CountryListenerTester(); + + mCountryDetectorService.systemRunning(); + mCountryDetectorService.addCountryListener(countryListener); + expect.that(mCountryDetectorService.isListenerSet()).isTrue(); + mCountryDetectorService.removeCountryListener(countryListener); + + expect.that(mCountryDetectorService.isListenerSet()).isFalse(); + } + + @Test + public void countryListener_notify_successful() throws RemoteException { + CountryListenerTester countryListenerA = new CountryListenerTester(); + CountryListenerTester countryListenerB = new CountryListenerTester(); + Country country = new Country("US", Country.COUNTRY_SOURCE_NETWORK); + + mCountryDetectorService.systemRunning(); + mCountryDetectorService.addCountryListener(countryListenerA); + mCountryDetectorService.addCountryListener(countryListenerB); + expect.that(countryListenerA.isNotified()).isFalse(); + expect.that(countryListenerB.isNotified()).isFalse(); + mCountryDetectorService.notifyReceivers(country); + + expect.that(countryListenerA.isNotified()).isTrue(); + expect.that(countryListenerB.isNotified()).isTrue(); + expect.that(countryListenerA.getCountry().equalsIgnoreSource(country)).isTrue(); + expect.that(countryListenerB.getCountry().equalsIgnoreSource(country)).isTrue(); } } |