| /* |
| * 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. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * 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. |
| */ |
| |
| package com.android.server; |
| |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.ArgumentMatchers.anyLong; |
| import static org.mockito.Mockito.doAnswer; |
| import static org.mockito.Mockito.doReturn; |
| import static org.mockito.Mockito.when; |
| |
| import android.content.Context; |
| import android.content.res.Resources; |
| 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 androidx.test.core.app.ApplicationProvider; |
| |
| import com.android.internal.R; |
| import com.android.server.location.ComprehensiveCountryDetector; |
| import com.android.server.location.CustomCountryDetectorTestClass; |
| |
| 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.Mock; |
| import org.mockito.Spy; |
| import org.mockito.junit.MockitoJUnitRunner; |
| |
| @RunWith(MockitoJUnitRunner.class) |
| public class CountryDetectorServiceTest { |
| |
| private static final String VALID_CUSTOM_TEST_CLASS = |
| "com.android.server.location.CustomCountryDetectorTestClass"; |
| private static final String INVALID_CUSTOM_TEST_CLASS = |
| "com.android.server.location.MissingCountryDetectorTestClass"; |
| |
| private static class CountryListenerTester extends ICountryListener.Stub { |
| private Country mCountry; |
| |
| @Override |
| public void onCountryDetected(Country country) { |
| mCountry = country; |
| } |
| |
| Country getCountry() { |
| return mCountry; |
| } |
| |
| public boolean isNotified() { |
| return mCountry != null; |
| } |
| } |
| |
| private static class CountryDetectorServiceTester extends CountryDetectorService { |
| private CountryListener mListener; |
| |
| CountryDetectorServiceTester(Context context, Handler handler) { |
| super(context, handler); |
| } |
| |
| @Override |
| public void notifyReceivers(Country country) { |
| super.notifyReceivers(country); |
| } |
| |
| @Override |
| protected void setCountryListener(final CountryListener listener) { |
| mListener = listener; |
| } |
| |
| boolean isListenerSet() { |
| return mListener != null; |
| } |
| } |
| |
| @Rule public final Expect expect = Expect.create(); |
| @Spy private Context mContext = ApplicationProvider.getApplicationContext(); |
| @Spy private Handler mHandler = new Handler(Looper.myLooper()); |
| @Mock private Resources mResources; |
| |
| private CountryDetectorServiceTester mCountryDetectorService; |
| |
| @BeforeClass |
| public static void oneTimeInitialization() { |
| if (Looper.myLooper() == null) { |
| Looper.prepare(); |
| } |
| } |
| |
| @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()); |
| |
| doReturn(mResources).when(mContext).getResources(); |
| } |
| |
| @Test |
| public void addCountryListener_validListener_listenerAdded() throws RemoteException { |
| CountryListenerTester countryListener = new CountryListenerTester(); |
| |
| mCountryDetectorService.systemRunning(); |
| expect.that(mCountryDetectorService.isListenerSet()).isFalse(); |
| mCountryDetectorService.addCountryListener(countryListener); |
| |
| expect.that(mCountryDetectorService.isListenerSet()).isTrue(); |
| } |
| |
| @Test |
| public void removeCountryListener_validListener_listenerRemoved() 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(expected = RemoteException.class) |
| public void addCountryListener_serviceNotReady_throwsException() throws RemoteException { |
| CountryListenerTester countryListener = new CountryListenerTester(); |
| |
| expect.that(mCountryDetectorService.isSystemReady()).isFalse(); |
| mCountryDetectorService.addCountryListener(countryListener); |
| } |
| |
| @Test(expected = RemoteException.class) |
| public void removeCountryListener_serviceNotReady_throwsException() throws RemoteException { |
| CountryListenerTester countryListener = new CountryListenerTester(); |
| |
| expect.that(mCountryDetectorService.isSystemReady()).isFalse(); |
| mCountryDetectorService.removeCountryListener(countryListener); |
| } |
| |
| @Test |
| public void detectCountry_serviceNotReady_returnNull() { |
| expect.that(mCountryDetectorService.isSystemReady()).isFalse(); |
| |
| expect.that(mCountryDetectorService.detectCountry()).isNull(); |
| } |
| |
| @Test |
| public void notifyReceivers_twoListenersRegistered_bothNotified() 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(); |
| } |
| |
| @Test |
| public void initialize_deviceWithCustomDetector_useCustomDetectorClass() { |
| when(mResources.getString(R.string.config_customCountryDetector)) |
| .thenReturn(VALID_CUSTOM_TEST_CLASS); |
| |
| mCountryDetectorService.initialize(); |
| |
| expect.that(mCountryDetectorService.getCountryDetector()) |
| .isInstanceOf(CustomCountryDetectorTestClass.class); |
| } |
| |
| @Test |
| public void initialize_deviceWithInvalidCustomDetector_useDefaultDetector() { |
| when(mResources.getString(R.string.config_customCountryDetector)) |
| .thenReturn(INVALID_CUSTOM_TEST_CLASS); |
| |
| mCountryDetectorService.initialize(); |
| |
| expect.that(mCountryDetectorService.getCountryDetector()) |
| .isInstanceOf(ComprehensiveCountryDetector.class); |
| } |
| } |