1 /*
2  * Copyright (C) 2021 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  */
16 
17 package com.android.server.uwb;
18 
19 import static com.android.server.uwb.UwbCountryCode.DEFAULT_COUNTRY_CODE;
20 import static com.android.server.uwb.data.UwbUciConstants.STATUS_CODE_FAILED;
21 import static com.android.server.uwb.data.UwbUciConstants.STATUS_CODE_OK;
22 
23 import static org.junit.Assert.assertEquals;
24 import static org.mockito.Mockito.any;
25 import static org.mockito.Mockito.anyDouble;
26 import static org.mockito.Mockito.anyFloat;
27 import static org.mockito.Mockito.anyInt;
28 import static org.mockito.Mockito.anyLong;
29 import static org.mockito.Mockito.anyString;
30 import static org.mockito.Mockito.clearInvocations;
31 import static org.mockito.Mockito.doThrow;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.never;
34 import static org.mockito.Mockito.verify;
35 import static org.mockito.Mockito.verifyNoMoreInteractions;
36 import static org.mockito.Mockito.when;
37 
38 import android.content.BroadcastReceiver;
39 import android.content.Context;
40 import android.content.Intent;
41 import android.content.pm.PackageManager;
42 import android.location.Address;
43 import android.location.Geocoder;
44 import android.location.Location;
45 import android.location.LocationListener;
46 import android.location.LocationManager;
47 import android.net.wifi.WifiManager;
48 import android.net.wifi.WifiManager.ActiveCountryCodeChangedCallback;
49 import android.os.Handler;
50 import android.os.test.TestLooper;
51 import android.telephony.SubscriptionInfo;
52 import android.telephony.SubscriptionManager;
53 import android.telephony.TelephonyManager;
54 import android.util.Pair;
55 
56 import androidx.test.filters.SmallTest;
57 
58 import com.android.server.uwb.jni.NativeUwbManager;
59 import com.android.uwb.flags.FeatureFlags;
60 
61 import org.junit.Before;
62 import org.junit.Test;
63 import org.mockito.ArgumentCaptor;
64 import org.mockito.Captor;
65 import org.mockito.Mock;
66 import org.mockito.MockitoAnnotations;
67 
68 import java.nio.charset.StandardCharsets;
69 import java.util.List;
70 
71 /**
72  * Unit tests for {@link com.android.server.uwb.UwbCountryCode}.
73  */
74 @SmallTest
75 public class UwbCountryCodeTest {
76     private static final String TEST_COUNTRY_CODE = "US";
77     private static final String TEST_COUNTRY_CODE_OTHER = "JP";
78     private static final String ISO_COUNTRY_CODE = "UK";
79     private static final int TEST_SUBSCRIPTION_ID = 0;
80     private static final int TEST_SLOT_IDX = 0;
81     private static final int TEST_SUBSCRIPTION_ID_OTHER = 1;
82     private static final int TEST_SLOT_IDX_OTHER = 1;
83 
84     @Mock Context mContext;
85     @Mock TelephonyManager mTelephonyManager;
86     @Mock SubscriptionManager mSubscriptionManager;
87     @Mock LocationManager mLocationManager;
88     @Mock Geocoder mGeocoder;
89     @Mock WifiManager mWifiManager;
90     @Mock NativeUwbManager mNativeUwbManager;
91     @Mock UwbInjector mUwbInjector;
92     @Mock PackageManager mPackageManager;
93     @Mock Location mLocation;
94     @Mock UwbCountryCode.CountryCodeChangedListener mListener;
95     @Mock DeviceConfigFacade mDeviceConfigFacade;
96     @Mock FeatureFlags mFeatureFlags;
97     @Mock UwbSettingsStore mUwbSettingsStore;
98 
99     private TestLooper mTestLooper;
100     private UwbCountryCode mUwbCountryCode;
101 
102     @Captor
103     private ArgumentCaptor<BroadcastReceiver> mTelephonyCountryCodeReceiverCaptor;
104     @Captor
105     private ArgumentCaptor<ActiveCountryCodeChangedCallback> mWifiCountryCodeReceiverCaptor;
106     @Captor
107     private ArgumentCaptor<LocationListener> mLocationListenerCaptor;
108     @Captor
109     private ArgumentCaptor<Geocoder.GeocodeListener> mGeocodeListenerCaptor;
110 
111     /**
112      * Setup test.
113      */
114     @Before
setUp()115     public void setUp() throws Exception {
116         MockitoAnnotations.initMocks(this);
117         mTestLooper = new TestLooper();
118 
119         // Setup the unit tests to have default behavior of using the getNetworkCountryIso(). This
120         // should not have any effect as below the TelephonyManager is setup to return some active
121         // subscription(s) (which should also be the typical behavior when phone has a SIM).
122         when(mUwbInjector.getFeatureFlags()).thenReturn(mFeatureFlags);
123 
124         when(mContext.createContext(any())).thenReturn(mContext);
125         when(mContext.getSystemService(TelephonyManager.class))
126                 .thenReturn(mTelephonyManager);
127         when(mContext.getSystemService(SubscriptionManager.class))
128                 .thenReturn(mSubscriptionManager);
129         when(mContext.getSystemService(WifiManager.class))
130                 .thenReturn(mWifiManager);
131         when(mContext.getSystemService(LocationManager.class))
132                 .thenReturn(mLocationManager);
133         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(List.of(
134                 new SubscriptionInfo(
135                 TEST_SUBSCRIPTION_ID, "", TEST_SLOT_IDX, "", "", 0, 0, "", 0, null, "", "", "",
136                         true /* isEmbedded */, null, "", 25, false, null, false, 0, 0, 0, null,
137                         null, true, 0),
138                 new SubscriptionInfo(
139                         TEST_SUBSCRIPTION_ID_OTHER, "", TEST_SLOT_IDX_OTHER, "", "", 0, 0, "", 0,
140                         null, "", "", "", true /* isEmbedded */, null, "", 25, false, null, false,
141                         0, 0, 0, null, null, true, 0)
142         ));
143         when(mContext.getPackageManager()).thenReturn(mPackageManager);
144         when(mLocation.getLatitude()).thenReturn(0.0);
145         when(mLocation.getLongitude()).thenReturn(0.0);
146         when(mUwbInjector.makeGeocoder()).thenReturn(mGeocoder);
147         when(mUwbInjector.isGeocoderPresent()).thenReturn(true);
148         when(mDeviceConfigFacade.isLocationUseForCountryCodeEnabled()).thenReturn(true);
149         when(mUwbInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
150         when(mUwbInjector.getUwbSettingsStore()).thenReturn(mUwbSettingsStore);
151         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)).thenReturn(true);
152         when(mNativeUwbManager.setCountryCode(any())).thenReturn(
153                 (byte) STATUS_CODE_OK);
154         mUwbCountryCode = new UwbCountryCode(
155                 mContext, mNativeUwbManager, new Handler(mTestLooper.getLooper()), mUwbInjector);
156 
157         mUwbCountryCode.addListener(mListener);
158     }
159 
160     @Test
testSetDefaultCountryCodeWhenNoCountryCodeAvailable()161     public void testSetDefaultCountryCodeWhenNoCountryCodeAvailable() {
162         mUwbCountryCode.initialize();
163         verify(mNativeUwbManager).setCountryCode(
164                 DEFAULT_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
165         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, DEFAULT_COUNTRY_CODE);
166     }
167 
168     @Test
testInitializeCountryCodeFromTelephony()169     public void testInitializeCountryCodeFromTelephony() {
170         when(mTelephonyManager.getNetworkCountryIso(anyInt())).thenReturn(TEST_COUNTRY_CODE);
171         mUwbCountryCode.initialize();
172         verify(mNativeUwbManager).setCountryCode(
173                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
174         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
175     }
176 
177     // Test that a country code is configured, when the list of active subscriptions is empty,
178     // the flag to use the NetworkCountryIso() is enabled, and it returns a valid country code.
179     @Test
testInitializeCountryCodeFromTelephonyWhenSubscriptionListEmptyAndFlagEnabled()180     public void testInitializeCountryCodeFromTelephonyWhenSubscriptionListEmptyAndFlagEnabled() {
181         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(List.of());
182         when(mTelephonyManager.getNetworkCountryIso()).thenReturn(ISO_COUNTRY_CODE);
183 
184         mUwbCountryCode.initialize();
185 
186         verify(mTelephonyManager).getNetworkCountryIso();
187         verify(mTelephonyManager, never()).getNetworkCountryIso(anyInt());
188         verify(mNativeUwbManager).setCountryCode(
189                 ISO_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
190         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, ISO_COUNTRY_CODE);
191     }
192 
193     // Test that a country code is configured, when the list of active subscriptions is null,
194     // the flag to use the NetworkCountryIso() is enabled, and it returns a valid country code.
195     @Test
testInitializeCountryCodeFromTelephonyWhenSubscriptionListNullAndFlagEnabled()196     public void testInitializeCountryCodeFromTelephonyWhenSubscriptionListNullAndFlagEnabled() {
197         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null);
198         when(mTelephonyManager.getNetworkCountryIso()).thenReturn(ISO_COUNTRY_CODE);
199 
200         mUwbCountryCode.initialize();
201 
202         verify(mTelephonyManager).getNetworkCountryIso();
203         verify(mTelephonyManager, never()).getNetworkCountryIso(anyInt());
204         verify(mNativeUwbManager).setCountryCode(
205                 ISO_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
206         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, ISO_COUNTRY_CODE);
207     }
208 
209     // Test that a country code is not configured, when the list of active subscriptions is empty,
210     // the flag to use the NetworkCountryIso() is enabled, and it returns an empty country code.
211     @Test
testInitializeCountryCodeFromTelephonyWhenSubscriptionListAndNetworkCountryEmpty()212     public void testInitializeCountryCodeFromTelephonyWhenSubscriptionListAndNetworkCountryEmpty() {
213         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(List.of());
214         when(mTelephonyManager.getNetworkCountryIso()).thenReturn("");
215 
216         mUwbCountryCode.initialize();
217 
218         verify(mTelephonyManager).getNetworkCountryIso();
219         verify(mTelephonyManager, never()).getNetworkCountryIso(anyInt());
220         verifyNoMoreInteractions(mNativeUwbManager, mListener);
221     }
222 
223     @Test
testSkipWhenExceptionThrownInInitializeCountryCodeFromTelephony()224     public void testSkipWhenExceptionThrownInInitializeCountryCodeFromTelephony() {
225         doThrow(new IllegalArgumentException()).when(mTelephonyManager).getNetworkCountryIso(
226                 anyInt());
227         mUwbCountryCode.initialize();
228         verify(mNativeUwbManager, never()).setCountryCode(any());
229         verify(mListener, never()).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
230     }
231 
232     @Test
testInitializeCountryCodeFromTelephonyVerifyListener()233     public void testInitializeCountryCodeFromTelephonyVerifyListener() {
234         when(mTelephonyManager.getNetworkCountryIso(anyInt())).thenReturn(TEST_COUNTRY_CODE);
235         mUwbCountryCode.initialize();
236         verify(mNativeUwbManager).setCountryCode(
237                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
238         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
239     }
240 
241     @Test
testSetCountryCodeFromTelephony()242     public void testSetCountryCodeFromTelephony() {
243         when(mTelephonyManager.getNetworkCountryIso(anyInt())).thenReturn(TEST_COUNTRY_CODE);
244         mUwbCountryCode.initialize();
245         verify(mNativeUwbManager).setCountryCode(
246                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
247         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
248         clearInvocations(mNativeUwbManager, mListener);
249 
250         assertEquals(Pair.create(STATUS_CODE_OK, TEST_COUNTRY_CODE),
251                 mUwbCountryCode.setCountryCode(false));
252         // already set.
253         verify(mNativeUwbManager, never()).setCountryCode(
254                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
255         verify(mListener, never()).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
256     }
257 
258     @Test
testSetCountryCodeFromLocation()259     public void testSetCountryCodeFromLocation() {
260         when(mLocationManager.getLastKnownLocation(LocationManager.FUSED_PROVIDER))
261                 .thenReturn(mLocation);
262         mUwbCountryCode.initialize();
263         verify(mGeocoder).getFromLocation(
264                 anyDouble(), anyDouble(), anyInt(), mGeocodeListenerCaptor.capture());
265         Address mockAddress = mock(Address.class);
266         when(mockAddress.getCountryCode()).thenReturn(TEST_COUNTRY_CODE);
267         List<Address> addresses = List.of(mockAddress);
268         mGeocodeListenerCaptor.getValue().onGeocode(addresses);
269         mTestLooper.dispatchAll();
270         verify(mNativeUwbManager).setCountryCode(
271                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
272         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
273         clearInvocations(mNativeUwbManager, mListener);
274 
275         assertEquals(Pair.create(STATUS_CODE_OK, TEST_COUNTRY_CODE),
276                 mUwbCountryCode.setCountryCode(false));
277         // already set.
278         verify(mNativeUwbManager, never()).setCountryCode(
279                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
280         verify(mListener, never()).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
281     }
282 
283     @Test
testSetCountryCodeWhenLocationUseIsDisabled()284     public void testSetCountryCodeWhenLocationUseIsDisabled() {
285         when(mDeviceConfigFacade.isLocationUseForCountryCodeEnabled()).thenReturn(false);
286         when(mLocationManager.getLastKnownLocation(LocationManager.FUSED_PROVIDER))
287                 .thenReturn(mLocation);
288         mUwbCountryCode.initialize();
289         verifyNoMoreInteractions(mGeocoder);
290     }
291 
292     @Test
testSetCountryCodeWithForceUpdateFromTelephony()293     public void testSetCountryCodeWithForceUpdateFromTelephony() {
294         when(mTelephonyManager.getNetworkCountryIso(anyInt())).thenReturn(TEST_COUNTRY_CODE);
295         mUwbCountryCode.initialize();
296         clearInvocations(mNativeUwbManager, mListener);
297 
298         assertEquals(Pair.create(STATUS_CODE_OK, TEST_COUNTRY_CODE),
299                 mUwbCountryCode.setCountryCode(true));
300         // set again
301         verify(mNativeUwbManager).setCountryCode(
302                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
303         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
304     }
305 
306     @Test
testSetCountryCodeFromOemWhenTelephonyAndWifiNotAvailable()307     public void testSetCountryCodeFromOemWhenTelephonyAndWifiNotAvailable() {
308         when(mTelephonyManager.getNetworkCountryIso(anyInt())).thenReturn(TEST_COUNTRY_CODE);
309         mUwbCountryCode.initialize();
310         clearInvocations(mNativeUwbManager, mListener);
311 
312         assertEquals(Pair.create(STATUS_CODE_OK, TEST_COUNTRY_CODE),
313                 mUwbCountryCode.setCountryCode(false));
314         // already set.
315         verify(mNativeUwbManager, never()).setCountryCode(
316                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
317         verify(mListener, never()).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
318     }
319 
320     @Test
testSetCountryCode_statusError()321     public void testSetCountryCode_statusError() {
322         when(mTelephonyManager.getNetworkCountryIso(anyInt())).thenReturn(TEST_COUNTRY_CODE);
323         mUwbCountryCode.initialize();
324         clearInvocations(mNativeUwbManager);
325 
326         when(mNativeUwbManager.setCountryCode(any())).thenReturn((byte) STATUS_CODE_FAILED);
327         assertEquals(Pair.create(STATUS_CODE_FAILED, TEST_COUNTRY_CODE),
328                 mUwbCountryCode.setCountryCode(true));
329         verify(mNativeUwbManager).setCountryCode(
330                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
331         verify(mListener).onCountryCodeChanged(STATUS_CODE_FAILED, TEST_COUNTRY_CODE);
332     }
333 
334     @Test
testChangeInTelephonyCountryCode()335     public void testChangeInTelephonyCountryCode() {
336         mUwbCountryCode.initialize();
337         verify(mContext).registerReceiver(
338                 mTelephonyCountryCodeReceiverCaptor.capture(), any(), any(), any());
339         Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED)
340                 .putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, TEST_COUNTRY_CODE)
341                         .putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, TEST_SLOT_IDX);
342         mTelephonyCountryCodeReceiverCaptor.getValue().onReceive(mock(Context.class), intent);
343         verify(mNativeUwbManager).setCountryCode(
344                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
345         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
346     }
347 
348     @Test
testChangeInWifiCountryCode()349     public void testChangeInWifiCountryCode() {
350         mUwbCountryCode.initialize();
351         verify(mWifiManager).registerActiveCountryCodeChangedCallback(
352                 any(), mWifiCountryCodeReceiverCaptor.capture());
353         mWifiCountryCodeReceiverCaptor.getValue().onActiveCountryCodeChanged(TEST_COUNTRY_CODE);
354         verify(mNativeUwbManager).setCountryCode(
355                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
356         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
357     }
358 
359     @Test
testWifiECallback_error()360     public void testWifiECallback_error() {
361         // Disable other sources (Geocoder) for the Wifi location error test.
362         when(mUwbInjector.isGeocoderPresent()).thenReturn(false);
363         when(mDeviceConfigFacade.isLocationUseForCountryCodeEnabled()).thenReturn(false);
364 
365         doThrow(new SecurityException()).when(mWifiManager)
366                 .registerActiveCountryCodeChangedCallback(any(), any());
367         mUwbCountryCode.initialize();
368 
369         verify(mWifiManager).registerActiveCountryCodeChangedCallback(any(), any());
370         verify(mNativeUwbManager).setCountryCode(
371                 DEFAULT_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
372         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, DEFAULT_COUNTRY_CODE);
373     }
374 
375     @Test
testGeocodingLocation_error()376     public void testGeocodingLocation_error() {
377         doThrow(new IllegalArgumentException()).when(mLocation).getLatitude();
378         when(mLocation.getLongitude()).thenReturn(0.0);
379         mUwbCountryCode.initialize();
380 
381         verify(mLocationManager).requestLocationUpdates(
382                 anyString(), anyLong(), anyFloat(), mLocationListenerCaptor.capture());
383         mLocationListenerCaptor.getValue().onLocationChanged(mLocation);
384         verify(mNativeUwbManager).setCountryCode(
385                 DEFAULT_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
386         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, DEFAULT_COUNTRY_CODE);
387     }
388 
389     @Test
testChangeInLocationCountryCode()390     public void testChangeInLocationCountryCode() {
391         mUwbCountryCode.initialize();
392         verify(mLocationManager).requestLocationUpdates(
393                 anyString(), anyLong(), anyFloat(), mLocationListenerCaptor.capture());
394         mLocationListenerCaptor.getValue().onLocationChanged(mLocation);
395         verify(mGeocoder).getFromLocation(
396                 anyDouble(), anyDouble(), anyInt(), mGeocodeListenerCaptor.capture());
397         Address mockAddress = mock(Address.class);
398         when(mockAddress.getCountryCode()).thenReturn(TEST_COUNTRY_CODE);
399         List<Address> addresses = List.of(mockAddress);
400         mGeocodeListenerCaptor.getValue().onGeocode(addresses);
401         mTestLooper.dispatchAll();
402         verify(mNativeUwbManager).setCountryCode(
403                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
404         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
405     }
406 
407     @Test
testChangeInTelephonyCountryCodeWhenWifiAndLocationCountryCodeAvailable()408     public void testChangeInTelephonyCountryCodeWhenWifiAndLocationCountryCodeAvailable() {
409         mUwbCountryCode.initialize();
410         verify(mWifiManager).registerActiveCountryCodeChangedCallback(
411                 any(), mWifiCountryCodeReceiverCaptor.capture());
412         mWifiCountryCodeReceiverCaptor.getValue().onActiveCountryCodeChanged(TEST_COUNTRY_CODE);
413         verify(mContext).registerReceiver(
414                 mTelephonyCountryCodeReceiverCaptor.capture(), any(), any(), any());
415         verify(mNativeUwbManager).setCountryCode(
416                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
417         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
418         verify(mLocationManager).requestLocationUpdates(
419                 anyString(), anyLong(), anyFloat(), mLocationListenerCaptor.capture());
420         mLocationListenerCaptor.getValue().onLocationChanged(mLocation);
421         verify(mGeocoder).getFromLocation(
422                 anyDouble(), anyDouble(), anyInt(), mGeocodeListenerCaptor.capture());
423         Address mockAddress = mock(Address.class);
424         when(mockAddress.getCountryCode()).thenReturn(TEST_COUNTRY_CODE);
425         List<Address> addresses = List.of(mockAddress);
426         mGeocodeListenerCaptor.getValue().onGeocode(addresses);
427         mTestLooper.dispatchAll();
428 
429         Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED)
430                 .putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, TEST_COUNTRY_CODE_OTHER)
431                 .putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, TEST_SLOT_IDX);
432         mTelephonyCountryCodeReceiverCaptor.getValue().onReceive(mock(Context.class), intent);
433         verify(mNativeUwbManager).setCountryCode(
434                 TEST_COUNTRY_CODE_OTHER.getBytes(StandardCharsets.UTF_8));
435         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE_OTHER);
436     }
437 
438     @Test
testUseLastKnownTelephonyCountryCodeWhenWifiAndTelephonyCountryCodeNotAvailable()439     public void testUseLastKnownTelephonyCountryCodeWhenWifiAndTelephonyCountryCodeNotAvailable() {
440         mUwbCountryCode.initialize();
441         verify(mWifiManager).registerActiveCountryCodeChangedCallback(
442                 any(), mWifiCountryCodeReceiverCaptor.capture());
443         mWifiCountryCodeReceiverCaptor.getValue().onActiveCountryCodeChanged("");
444         verify(mContext).registerReceiver(
445                 mTelephonyCountryCodeReceiverCaptor.capture(), any(), any(), any());
446         verify(mNativeUwbManager).setCountryCode(
447                 DEFAULT_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
448 
449         Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED)
450                 .putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, "")
451                 .putExtra(UwbCountryCode.EXTRA_LAST_KNOWN_NETWORK_COUNTRY, TEST_COUNTRY_CODE)
452                 .putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, TEST_SLOT_IDX);
453         mTelephonyCountryCodeReceiverCaptor.getValue().onReceive(mock(Context.class), intent);
454         verify(mNativeUwbManager).setCountryCode(
455                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
456         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
457     }
458 
459     @Test
testChangeInTelephonyCountryCodeWhenMoreThanOneSimWifiCountryCodeAvailable()460     public void testChangeInTelephonyCountryCodeWhenMoreThanOneSimWifiCountryCodeAvailable() {
461         mUwbCountryCode.initialize();
462         verify(mWifiManager).registerActiveCountryCodeChangedCallback(
463                 any(), mWifiCountryCodeReceiverCaptor.capture());
464         mWifiCountryCodeReceiverCaptor.getValue().onActiveCountryCodeChanged(TEST_COUNTRY_CODE);
465         verify(mContext).registerReceiver(
466                 mTelephonyCountryCodeReceiverCaptor.capture(), any(), any(), any());
467         verify(mNativeUwbManager).setCountryCode(
468                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
469         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
470 
471         Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED)
472                 .putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, TEST_COUNTRY_CODE_OTHER)
473                 .putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, TEST_SLOT_IDX);
474         mTelephonyCountryCodeReceiverCaptor.getValue().onReceive(mock(Context.class), intent);
475         verify(mNativeUwbManager).setCountryCode(
476                 TEST_COUNTRY_CODE_OTHER.getBytes(StandardCharsets.UTF_8));
477         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE_OTHER);
478 
479         intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED)
480                 .putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, TEST_COUNTRY_CODE_OTHER)
481                 .putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, TEST_SLOT_IDX_OTHER);
482         mTelephonyCountryCodeReceiverCaptor.getValue().onReceive(mock(Context.class), intent);
483         verify(mNativeUwbManager).setCountryCode(
484                 TEST_COUNTRY_CODE_OTHER.getBytes(StandardCharsets.UTF_8));
485         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE_OTHER);
486     }
487 
488     @Test
testForceOverrideCodeWhenTelephonyAndWifiAvailable()489     public void testForceOverrideCodeWhenTelephonyAndWifiAvailable() {
490         when(mTelephonyManager.getNetworkCountryIso(anyInt())).thenReturn(TEST_COUNTRY_CODE);
491         mUwbCountryCode.initialize();
492 
493         verify(mWifiManager).registerActiveCountryCodeChangedCallback(
494                 any(), mWifiCountryCodeReceiverCaptor.capture());
495         mWifiCountryCodeReceiverCaptor.getValue().onActiveCountryCodeChanged(TEST_COUNTRY_CODE);
496         clearInvocations(mNativeUwbManager, mListener);
497 
498         mUwbCountryCode.setOverrideCountryCode(TEST_COUNTRY_CODE_OTHER);
499         verify(mNativeUwbManager).setCountryCode(
500                 TEST_COUNTRY_CODE_OTHER.getBytes(StandardCharsets.UTF_8));
501         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE_OTHER);
502         clearInvocations(mNativeUwbManager, mListener);
503 
504         mUwbCountryCode.clearOverrideCountryCode();
505         verify(mNativeUwbManager).setCountryCode(
506                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
507         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
508     }
509 
510     @Test
testUseCacheWhenTelephonyAndWifiNotAvailable()511     public void testUseCacheWhenTelephonyAndWifiNotAvailable() {
512         when(mDeviceConfigFacade.isPersistentCacheUseForCountryCodeEnabled()).thenReturn(true);
513         mUwbCountryCode.initialize();
514         verify(mContext).registerReceiver(
515                 mTelephonyCountryCodeReceiverCaptor.capture(), any(), any(), any());
516         verify(mWifiManager).registerActiveCountryCodeChangedCallback(
517                 any(), mWifiCountryCodeReceiverCaptor.capture());
518         clearInvocations(mNativeUwbManager, mListener);
519 
520         // Set other country code sources
521         Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED)
522                 .putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, TEST_COUNTRY_CODE)
523                 .putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, TEST_SLOT_IDX);
524         mTelephonyCountryCodeReceiverCaptor.getValue().onReceive(mock(Context.class), intent);
525         mWifiCountryCodeReceiverCaptor.getValue().onActiveCountryCodeChanged(TEST_COUNTRY_CODE);
526         verify(mNativeUwbManager).setCountryCode(
527                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
528         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
529         verify(mUwbSettingsStore).put(
530                 UwbSettingsStore.SETTINGS_CACHED_COUNTRY_CODE, TEST_COUNTRY_CODE);
531         clearInvocations(mNativeUwbManager, mListener);
532 
533         // Clear all other country code sources and ensure we use the cache.
534         intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED)
535                 .putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, DEFAULT_COUNTRY_CODE)
536                 .putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, TEST_SLOT_IDX);
537         mTelephonyCountryCodeReceiverCaptor.getValue().onReceive(mock(Context.class), intent);
538         mWifiCountryCodeReceiverCaptor.getValue().onActiveCountryCodeChanged(DEFAULT_COUNTRY_CODE);
539         verifyNoMoreInteractions(mNativeUwbManager, mListener);
540 
541         // Now clear the cache and ensure we reset the country code.
542         mUwbCountryCode.clearCachedCountryCode();
543         mUwbCountryCode.setCountryCode(true);
544         verify(mNativeUwbManager).setCountryCode(
545                 DEFAULT_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
546         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, DEFAULT_COUNTRY_CODE);
547     }
548 
549     @Test
testUsePersistentCacheAtBootupWhenTelephonyAndWifiNotAvailable()550     public void testUsePersistentCacheAtBootupWhenTelephonyAndWifiNotAvailable() {
551         when(mDeviceConfigFacade.isPersistentCacheUseForCountryCodeEnabled()).thenReturn(true);
552         when(mUwbSettingsStore.get(UwbSettingsStore.SETTINGS_CACHED_COUNTRY_CODE))
553                 .thenReturn(TEST_COUNTRY_CODE);
554         mUwbCountryCode.initialize();
555         verify(mUwbSettingsStore).get(UwbSettingsStore.SETTINGS_CACHED_COUNTRY_CODE);
556         verify(mNativeUwbManager).setCountryCode(
557                 TEST_COUNTRY_CODE.getBytes(StandardCharsets.UTF_8));
558         verify(mListener).onCountryCodeChanged(STATUS_CODE_OK, TEST_COUNTRY_CODE);
559     }
560 }
561