1 /*
2  * Copyright (C) 2020 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.vcn;
18 
19 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
20 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
21 import static android.net.vcn.VcnManager.VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY;
22 import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
23 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
24 import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
25 import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED;
26 
27 import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
28 import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
29 import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
30 
31 import static org.junit.Assert.assertEquals;
32 import static org.junit.Assert.assertNotNull;
33 import static org.junit.Assert.assertNull;
34 import static org.junit.Assert.assertTrue;
35 import static org.mockito.ArgumentMatchers.any;
36 import static org.mockito.ArgumentMatchers.anyInt;
37 import static org.mockito.ArgumentMatchers.argThat;
38 import static org.mockito.ArgumentMatchers.eq;
39 import static org.mockito.Mockito.atLeastOnce;
40 import static org.mockito.Mockito.doReturn;
41 import static org.mockito.Mockito.mock;
42 import static org.mockito.Mockito.reset;
43 import static org.mockito.Mockito.times;
44 import static org.mockito.Mockito.verify;
45 import static org.mockito.Mockito.verifyNoMoreInteractions;
46 
47 import static java.util.Collections.emptyMap;
48 import static java.util.Collections.emptySet;
49 import static java.util.Collections.singletonMap;
50 
51 import android.annotation.NonNull;
52 import android.content.Context;
53 import android.content.Intent;
54 import android.content.IntentFilter;
55 import android.net.vcn.VcnManager;
56 import android.os.Handler;
57 import android.os.HandlerExecutor;
58 import android.os.ParcelUuid;
59 import android.os.PersistableBundle;
60 import android.os.test.TestLooper;
61 import android.telephony.CarrierConfigManager;
62 import android.telephony.SubscriptionInfo;
63 import android.telephony.SubscriptionManager;
64 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
65 import android.telephony.TelephonyCallback;
66 import android.telephony.TelephonyManager;
67 import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
68 import android.util.ArrayMap;
69 import android.util.ArraySet;
70 
71 import androidx.test.filters.SmallTest;
72 import androidx.test.runner.AndroidJUnit4;
73 
74 import org.junit.Before;
75 import org.junit.Test;
76 import org.junit.runner.RunWith;
77 import org.mockito.ArgumentCaptor;
78 
79 import java.util.ArrayList;
80 import java.util.Arrays;
81 import java.util.Collections;
82 import java.util.HashMap;
83 import java.util.List;
84 import java.util.Map;
85 import java.util.Set;
86 import java.util.UUID;
87 
88 /** Tests for TelephonySubscriptionTracker */
89 @RunWith(AndroidJUnit4.class)
90 @SmallTest
91 public class TelephonySubscriptionTrackerTest {
92     private static final String PACKAGE_NAME =
93             TelephonySubscriptionTrackerTest.class.getPackage().getName();
94     private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID());
95     private static final int TEST_SIM_SLOT_INDEX = 0;
96     private static final int TEST_SUBSCRIPTION_ID_1 = 2;
97     private static final SubscriptionInfo TEST_SUBINFO_1 = mock(SubscriptionInfo.class);
98     private static final int TEST_SUBSCRIPTION_ID_2 = 3;
99     private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class);
100     private static final Map<ParcelUuid, Set<String>> TEST_PRIVILEGED_PACKAGES =
101             Collections.singletonMap(TEST_PARCEL_UUID, Collections.singleton(PACKAGE_NAME));
102     private static final Map<Integer, SubscriptionInfo> TEST_SUBID_TO_INFO_MAP;
103 
104     static {
105         final Map<Integer, SubscriptionInfo> subIdToGroupMap = new HashMap<>();
subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_SUBINFO_1)106         subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_SUBINFO_1);
subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_SUBINFO_2)107         subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_SUBINFO_2);
108         TEST_SUBID_TO_INFO_MAP = Collections.unmodifiableMap(subIdToGroupMap);
109     }
110 
111     private static final String TEST_CARRIER_CONFIG_KEY_1 = "TEST_CARRIER_CONFIG_KEY_1";
112     private static final String TEST_CARRIER_CONFIG_KEY_2 = "TEST_CARRIER_CONFIG_KEY_2";
113     private static final PersistableBundle TEST_CARRIER_CONFIG = new PersistableBundle();
114     private static final PersistableBundleWrapper TEST_CARRIER_CONFIG_WRAPPER;
115     private static final Map<Integer, PersistableBundleWrapper> TEST_SUBID_TO_CARRIER_CONFIG_MAP;
116 
117     static {
TEST_CARRIER_CONFIG.putString( VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY, VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY)118         TEST_CARRIER_CONFIG.putString(
119                 VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY,
120                 VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY);
TEST_CARRIER_CONFIG.putString( VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY, VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY)121         TEST_CARRIER_CONFIG.putString(
122                 VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
123                 VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY);
124         TEST_CARRIER_CONFIG_WRAPPER = new PersistableBundleWrapper(TEST_CARRIER_CONFIG);
125 
126         final Map<Integer, PersistableBundleWrapper> subIdToCarrierConfigMap = new HashMap<>();
subIdToCarrierConfigMap.put(TEST_SUBSCRIPTION_ID_1, TEST_CARRIER_CONFIG_WRAPPER)127         subIdToCarrierConfigMap.put(TEST_SUBSCRIPTION_ID_1, TEST_CARRIER_CONFIG_WRAPPER);
128         TEST_SUBID_TO_CARRIER_CONFIG_MAP = Collections.unmodifiableMap(subIdToCarrierConfigMap);
129     }
130 
131     @NonNull private final Context mContext;
132     @NonNull private final TestLooper mTestLooper;
133     @NonNull private final Handler mHandler;
134     @NonNull private final TelephonySubscriptionTracker.Dependencies mDeps;
135 
136     @NonNull private final TelephonyManager mTelephonyManager;
137     @NonNull private final SubscriptionManager mSubscriptionManager;
138     @NonNull private final CarrierConfigManager mCarrierConfigManager;
139 
140     @NonNull private TelephonySubscriptionTrackerCallback mCallback;
141     @NonNull private TelephonySubscriptionTracker mTelephonySubscriptionTracker;
142 
143     @NonNull private CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener;
144 
TelephonySubscriptionTrackerTest()145     public TelephonySubscriptionTrackerTest() {
146         mContext = mock(Context.class);
147         mTestLooper = new TestLooper();
148         mHandler = new Handler(mTestLooper.getLooper());
149         mDeps = mock(TelephonySubscriptionTracker.Dependencies.class);
150 
151         mTelephonyManager = mock(TelephonyManager.class);
152         mSubscriptionManager = mock(SubscriptionManager.class);
153         mCarrierConfigManager = mock(CarrierConfigManager.class);
154 
155         doReturn(Context.TELEPHONY_SERVICE)
156                 .when(mContext)
157                 .getSystemServiceName(TelephonyManager.class);
158         doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
159 
160         doReturn(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
161                 .when(mContext)
162                 .getSystemServiceName(SubscriptionManager.class);
163         doReturn(mSubscriptionManager)
164                 .when(mContext)
165                 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
166 
167         doReturn(Context.CARRIER_CONFIG_SERVICE)
168                 .when(mContext)
169                 .getSystemServiceName(CarrierConfigManager.class);
170         doReturn(mCarrierConfigManager)
171                 .when(mContext)
172                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
173         doReturn(TEST_CARRIER_CONFIG)
174                 .when(mCarrierConfigManager)
175                 .getConfigForSubId(eq(TEST_SUBSCRIPTION_ID_1), any());
176 
177         // subId 1, 2 are in same subGrp, only subId 1 is active
178         doReturn(TEST_PARCEL_UUID).when(TEST_SUBINFO_1).getGroupUuid();
179         doReturn(TEST_PARCEL_UUID).when(TEST_SUBINFO_2).getGroupUuid();
180         doReturn(TEST_SIM_SLOT_INDEX).when(TEST_SUBINFO_1).getSimSlotIndex();
181         doReturn(INVALID_SIM_SLOT_INDEX).when(TEST_SUBINFO_2).getSimSlotIndex();
182         doReturn(TEST_SUBSCRIPTION_ID_1).when(TEST_SUBINFO_1).getSubscriptionId();
183         doReturn(TEST_SUBSCRIPTION_ID_2).when(TEST_SUBINFO_2).getSubscriptionId();
184     }
185 
186     @Before
setUp()187     public void setUp() throws Exception {
188         doReturn(2).when(mTelephonyManager).getActiveModemCount();
189 
190         mCallback = mock(TelephonySubscriptionTrackerCallback.class);
191         // Capture CarrierConfigChangeListener to emulate the carrier config change notification
192         ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
193                 ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
194         mTelephonySubscriptionTracker =
195                 new TelephonySubscriptionTracker(mContext, mHandler, mCallback, mDeps);
196         mTelephonySubscriptionTracker.register();
197         verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
198                 listenerArgumentCaptor.capture());
199         mCarrierConfigChangeListener = listenerArgumentCaptor.getAllValues().get(0);
200 
201         doReturn(true).when(mDeps).isConfigForIdentifiedCarrier(any());
202         doReturn(Arrays.asList(TEST_SUBINFO_1, TEST_SUBINFO_2))
203                 .when(mSubscriptionManager)
204                 .getAllSubscriptionInfoList();
205 
206         doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
207         setPrivilegedPackagesForMock(Collections.singletonList(PACKAGE_NAME));
208     }
209 
getIntentFilter()210     private IntentFilter getIntentFilter() {
211         final ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class);
212         verify(mContext).registerReceiver(any(), captor.capture(), any(), any());
213 
214         return captor.getValue();
215     }
216 
getOnSubscriptionsChangedListener()217     private OnSubscriptionsChangedListener getOnSubscriptionsChangedListener() {
218         final ArgumentCaptor<OnSubscriptionsChangedListener> captor =
219                 ArgumentCaptor.forClass(OnSubscriptionsChangedListener.class);
220         verify(mSubscriptionManager).addOnSubscriptionsChangedListener(any(), captor.capture());
221 
222         return captor.getValue();
223     }
224 
getCarrierPrivilegesCallbacks()225     private List<CarrierPrivilegesCallback> getCarrierPrivilegesCallbacks() {
226         final ArgumentCaptor<CarrierPrivilegesCallback> captor =
227                 ArgumentCaptor.forClass(CarrierPrivilegesCallback.class);
228         verify(mTelephonyManager, atLeastOnce())
229                 .registerCarrierPrivilegesCallback(anyInt(), any(), captor.capture());
230 
231         return captor.getAllValues();
232     }
233 
getActiveDataSubscriptionIdListener()234     private ActiveDataSubscriptionIdListener getActiveDataSubscriptionIdListener() {
235         final ArgumentCaptor<TelephonyCallback> captor =
236                 ArgumentCaptor.forClass(TelephonyCallback.class);
237         verify(mTelephonyManager).registerTelephonyCallback(any(), captor.capture());
238 
239         return (ActiveDataSubscriptionIdListener) captor.getValue();
240     }
241 
buildTestMultiSimConfigBroadcastIntent()242     private Intent buildTestMultiSimConfigBroadcastIntent() {
243         Intent intent = new Intent(ACTION_MULTI_SIM_CONFIG_CHANGED);
244         return intent;
245     }
246 
sendCarrierConfigChange(boolean hasValidSubscription)247     private void sendCarrierConfigChange(boolean hasValidSubscription) {
248         mCarrierConfigChangeListener.onCarrierConfigChanged(
249                 TEST_SIM_SLOT_INDEX,
250                 hasValidSubscription ? TEST_SUBSCRIPTION_ID_1 : INVALID_SUBSCRIPTION_ID,
251                 TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
252     }
253 
buildExpectedSnapshot( Map<ParcelUuid, Set<String>> privilegedPackages)254     private TelephonySubscriptionSnapshot buildExpectedSnapshot(
255             Map<ParcelUuid, Set<String>> privilegedPackages) {
256         return buildExpectedSnapshot(TEST_SUBID_TO_INFO_MAP, privilegedPackages);
257     }
258 
buildExpectedSnapshot( Map<Integer, SubscriptionInfo> subIdToInfoMap, Map<ParcelUuid, Set<String>> privilegedPackages)259     private TelephonySubscriptionSnapshot buildExpectedSnapshot(
260             Map<Integer, SubscriptionInfo> subIdToInfoMap,
261             Map<ParcelUuid, Set<String>> privilegedPackages) {
262         return buildExpectedSnapshot(0, subIdToInfoMap, privilegedPackages);
263     }
264 
buildExpectedSnapshot( int activeSubId, Map<Integer, SubscriptionInfo> subIdToInfoMap, Map<ParcelUuid, Set<String>> privilegedPackages)265     private TelephonySubscriptionSnapshot buildExpectedSnapshot(
266             int activeSubId,
267             Map<Integer, SubscriptionInfo> subIdToInfoMap,
268             Map<ParcelUuid, Set<String>> privilegedPackages) {
269         return buildExpectedSnapshot(
270                 activeSubId, subIdToInfoMap, TEST_SUBID_TO_CARRIER_CONFIG_MAP, privilegedPackages);
271     }
272 
buildExpectedSnapshot( int activeSubId, Map<Integer, SubscriptionInfo> subIdToInfoMap, Map<Integer, PersistableBundleWrapper> subIdToCarrierConfigMap, Map<ParcelUuid, Set<String>> privilegedPackages)273     private TelephonySubscriptionSnapshot buildExpectedSnapshot(
274             int activeSubId,
275             Map<Integer, SubscriptionInfo> subIdToInfoMap,
276             Map<Integer, PersistableBundleWrapper> subIdToCarrierConfigMap,
277             Map<ParcelUuid, Set<String>> privilegedPackages) {
278         return new TelephonySubscriptionSnapshot(
279                 activeSubId, subIdToInfoMap, subIdToCarrierConfigMap, privilegedPackages);
280     }
281 
verifyNoActiveSubscriptions()282     private void verifyNoActiveSubscriptions() {
283         verify(mCallback).onNewSnapshot(
284                 argThat(snapshot -> snapshot.getActiveSubscriptionGroups().isEmpty()));
285     }
286 
setupReadySubIds()287     private void setupReadySubIds() {
288         mTelephonySubscriptionTracker.setReadySubIdsBySlotId(
289                 Collections.singletonMap(TEST_SIM_SLOT_INDEX, TEST_SUBSCRIPTION_ID_1));
290         mTelephonySubscriptionTracker.setSubIdToCarrierConfigMap(
291                 Collections.singletonMap(TEST_SUBSCRIPTION_ID_1, TEST_CARRIER_CONFIG_WRAPPER));
292     }
293 
setPrivilegedPackagesForMock(@onNull List<String> privilegedPackages)294     private void setPrivilegedPackagesForMock(@NonNull List<String> privilegedPackages) {
295         doReturn(privilegedPackages).when(mTelephonyManager).getPackagesWithCarrierPrivileges();
296     }
297 
298     @Test
testRegister()299     public void testRegister() throws Exception {
300         verify(mContext)
301                 .registerReceiver(
302                         eq(mTelephonySubscriptionTracker),
303                         any(IntentFilter.class),
304                         any(),
305                         eq(mHandler));
306         final IntentFilter filter = getIntentFilter();
307         assertEquals(1, filter.countActions());
308         assertTrue(filter.hasAction(ACTION_MULTI_SIM_CONFIG_CHANGED));
309 
310         verify(mSubscriptionManager)
311                 .addOnSubscriptionsChangedListener(any(HandlerExecutor.class), any());
312         assertNotNull(getOnSubscriptionsChangedListener());
313 
314         verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(), any());
315 
316         verify(mTelephonyManager, times(2))
317                 .registerCarrierPrivilegesCallback(anyInt(), any(HandlerExecutor.class), any());
318         verify(mTelephonyManager)
319                 .registerCarrierPrivilegesCallback(eq(0), any(HandlerExecutor.class), any());
320         verify(mTelephonyManager)
321                 .registerCarrierPrivilegesCallback(eq(1), any(HandlerExecutor.class), any());
322         assertEquals(2, getCarrierPrivilegesCallbacks().size());
323     }
324 
325     @Test
testUnregister()326     public void testUnregister() throws Exception {
327         mTelephonySubscriptionTracker.unregister();
328 
329         verify(mContext).unregisterReceiver(eq(mTelephonySubscriptionTracker));
330 
331         final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
332         verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(eq(listener));
333 
334         for (CarrierPrivilegesCallback carrierPrivilegesCallback :
335                 getCarrierPrivilegesCallbacks()) {
336             verify(mTelephonyManager)
337                     .unregisterCarrierPrivilegesCallback(eq(carrierPrivilegesCallback));
338         }
339     }
340 
341     @Test
testMultiSimConfigChanged()342     public void testMultiSimConfigChanged() throws Exception {
343         final ArrayMap<Integer, Integer> readySubIdsBySlotId = new ArrayMap<>();
344         readySubIdsBySlotId.put(TEST_SIM_SLOT_INDEX, TEST_SUBSCRIPTION_ID_1);
345         readySubIdsBySlotId.put(TEST_SIM_SLOT_INDEX + 1, TEST_SUBSCRIPTION_ID_1);
346 
347         mTelephonySubscriptionTracker.setReadySubIdsBySlotId(readySubIdsBySlotId);
348         mTelephonySubscriptionTracker.setSubIdToCarrierConfigMap(TEST_SUBID_TO_CARRIER_CONFIG_MAP);
349         doReturn(1).when(mTelephonyManager).getActiveModemCount();
350 
351         List<CarrierPrivilegesCallback> carrierPrivilegesCallbacks =
352                 getCarrierPrivilegesCallbacks();
353 
354         mTelephonySubscriptionTracker.onReceive(mContext, buildTestMultiSimConfigBroadcastIntent());
355         mTestLooper.dispatchAll();
356 
357         for (CarrierPrivilegesCallback carrierPrivilegesCallback : carrierPrivilegesCallbacks) {
358             verify(mTelephonyManager)
359                     .unregisterCarrierPrivilegesCallback(eq(carrierPrivilegesCallback));
360         }
361 
362         // Expect cache cleared for inactive slots.
363         assertNull(
364                 mTelephonySubscriptionTracker
365                         .getReadySubIdsBySlotId()
366                         .get(TEST_SIM_SLOT_INDEX + 1));
367 
368         // Expect a new CarrierPrivilegesListener to have been registered for slot 0, and none other
369         // (2 previously registered during startup, for slots 0 & 1)
370         verify(mTelephonyManager, times(3))
371                 .registerCarrierPrivilegesCallback(anyInt(), any(HandlerExecutor.class), any());
372         verify(mTelephonyManager, times(2))
373                 .registerCarrierPrivilegesCallback(eq(0), any(HandlerExecutor.class), any());
374 
375         // Verify that this triggers a re-evaluation
376         verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
377     }
378 
379     @Test
testOnSubscriptionsChangedFired_NoReadySubIds()380     public void testOnSubscriptionsChangedFired_NoReadySubIds() throws Exception {
381         final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
382         listener.onSubscriptionsChanged();
383         mTestLooper.dispatchAll();
384 
385         verifyNoActiveSubscriptions();
386     }
387 
388     @Test
testOnSubscriptionsChangedFired_onActiveSubIdsChanged()389     public void testOnSubscriptionsChangedFired_onActiveSubIdsChanged() throws Exception {
390         setupReadySubIds();
391         setPrivilegedPackagesForMock(Collections.emptyList());
392 
393         doReturn(TEST_SUBSCRIPTION_ID_2).when(mDeps).getActiveDataSubscriptionId();
394         final ActiveDataSubscriptionIdListener listener = getActiveDataSubscriptionIdListener();
395         listener.onActiveDataSubscriptionIdChanged(TEST_SUBSCRIPTION_ID_2);
396         mTestLooper.dispatchAll();
397 
398         ArgumentCaptor<TelephonySubscriptionSnapshot> snapshotCaptor =
399                 ArgumentCaptor.forClass(TelephonySubscriptionSnapshot.class);
400         verify(mCallback).onNewSnapshot(snapshotCaptor.capture());
401 
402         TelephonySubscriptionSnapshot snapshot = snapshotCaptor.getValue();
403         assertNotNull(snapshot);
404         assertEquals(TEST_SUBSCRIPTION_ID_2, snapshot.getActiveDataSubscriptionId());
405         assertEquals(TEST_PARCEL_UUID, snapshot.getActiveDataSubscriptionGroup());
406     }
407 
408     @Test
testOnSubscriptionsChangedFired_WithReadySubidsNoPrivilegedPackages()409     public void testOnSubscriptionsChangedFired_WithReadySubidsNoPrivilegedPackages()
410             throws Exception {
411         setupReadySubIds();
412         setPrivilegedPackagesForMock(Collections.emptyList());
413 
414         final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
415         listener.onSubscriptionsChanged();
416         mTestLooper.dispatchAll();
417 
418         final Map<ParcelUuid, Set<String>> privilegedPackages =
419                 Collections.singletonMap(TEST_PARCEL_UUID, new ArraySet<>());
420         verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(privilegedPackages)));
421     }
422 
423     @Test
testOnSubscriptionsChangedFired_WithReadySubidsAndPrivilegedPackages()424     public void testOnSubscriptionsChangedFired_WithReadySubidsAndPrivilegedPackages()
425             throws Exception {
426         setupReadySubIds();
427 
428         final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
429         listener.onSubscriptionsChanged();
430         mTestLooper.dispatchAll();
431 
432         verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
433     }
434 
435     @Test
testOnCarrierPrivilegesChanged()436     public void testOnCarrierPrivilegesChanged() throws Exception {
437         setupReadySubIds();
438 
439         final CarrierPrivilegesCallback callback = getCarrierPrivilegesCallbacks().get(0);
440         callback.onCarrierPrivilegesChanged(Collections.emptySet(), Collections.emptySet());
441         mTestLooper.dispatchAll();
442 
443         verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
444     }
445 
446     @Test
testReceiveBroadcast_ConfigReadyWithSubscriptions()447     public void testReceiveBroadcast_ConfigReadyWithSubscriptions() throws Exception {
448         sendCarrierConfigChange(true /* hasValidSubscription */);
449         mTestLooper.dispatchAll();
450 
451         verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
452     }
453 
454     @Test
testReceiveBroadcast_ConfigReadyNoSubscriptions()455     public void testReceiveBroadcast_ConfigReadyNoSubscriptions() throws Exception {
456         doReturn(new ArrayList<SubscriptionInfo>())
457                 .when(mSubscriptionManager)
458                 .getAllSubscriptionInfoList();
459 
460         sendCarrierConfigChange(true /* hasValidSubscription */);
461         mTestLooper.dispatchAll();
462 
463         // Expect an empty snapshot
464         verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(emptyMap(), emptyMap())));
465     }
466 
467     @Test
testReceiveBroadcast_SlotCleared()468     public void testReceiveBroadcast_SlotCleared() throws Exception {
469         setupReadySubIds();
470 
471         sendCarrierConfigChange(false /* hasValidSubscription */);
472         mTestLooper.dispatchAll();
473 
474         verifyNoActiveSubscriptions();
475         assertTrue(mTelephonySubscriptionTracker.getReadySubIdsBySlotId().isEmpty());
476     }
477 
478     @Test
testReceiveBroadcast_ConfigNotReady()479     public void testReceiveBroadcast_ConfigNotReady() throws Exception {
480         doReturn(false).when(mDeps).isConfigForIdentifiedCarrier(any());
481 
482         sendCarrierConfigChange(true /* hasValidSubscription */);
483         mTestLooper.dispatchAll();
484 
485         // No interactions expected; config was not loaded
486         verifyNoMoreInteractions(mCallback);
487     }
488 
489     @Test
testSubscriptionsClearedAfterValidTriggersCallbacks()490     public void testSubscriptionsClearedAfterValidTriggersCallbacks() throws Exception {
491         sendCarrierConfigChange(true /* hasValidSubscription */);
492         mTestLooper.dispatchAll();
493         verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
494         assertNotNull(
495                 mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX));
496 
497         doReturn(Collections.emptyList()).when(mSubscriptionManager).getAllSubscriptionInfoList();
498         sendCarrierConfigChange(true /* hasValidSubscription */);
499         mTestLooper.dispatchAll();
500         verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(emptyMap(), emptyMap())));
501     }
502 
503     @Test
testCarrierConfigUpdatedAfterValidTriggersCallbacks()504     public void testCarrierConfigUpdatedAfterValidTriggersCallbacks() throws Exception {
505         sendCarrierConfigChange(true /* hasValidSubscription */);
506         mTestLooper.dispatchAll();
507         verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
508         reset(mCallback);
509 
510         final PersistableBundle updatedConfig = new PersistableBundle();
511         updatedConfig.putIntArray(
512                 VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY,
513                 new int[] {TRANSPORT_WIFI, TRANSPORT_CELLULAR});
514         doReturn(updatedConfig)
515                 .when(mCarrierConfigManager)
516                 .getConfigForSubId(eq(TEST_SUBSCRIPTION_ID_1), any());
517 
518         Map<Integer, PersistableBundleWrapper> subIdToCarrierConfigMap = new HashMap<>();
519         subIdToCarrierConfigMap.put(
520                 TEST_SUBSCRIPTION_ID_1, new PersistableBundleWrapper(updatedConfig));
521         sendCarrierConfigChange(true /* hasValidSubscription */);
522         mTestLooper.dispatchAll();
523 
524         verify(mCallback)
525                 .onNewSnapshot(
526                         eq(
527                                 buildExpectedSnapshot(
528                                         0,
529                                         TEST_SUBID_TO_INFO_MAP,
530                                         subIdToCarrierConfigMap,
531                                         TEST_PRIVILEGED_PACKAGES)));
532     }
533 
534     @Test
testSlotClearedAfterValidTriggersCallbacks()535     public void testSlotClearedAfterValidTriggersCallbacks() throws Exception {
536         sendCarrierConfigChange(true /* hasValidSubscription */);
537         mTestLooper.dispatchAll();
538         verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
539         assertNotNull(
540                 mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX));
541 
542         sendCarrierConfigChange(false /* hasValidSubscription */);
543         mTestLooper.dispatchAll();
544         verify(mCallback)
545                 .onNewSnapshot(
546                         eq(
547                                 buildExpectedSnapshot(
548                                         0, TEST_SUBID_TO_INFO_MAP, emptyMap(), emptyMap())));
549         assertNull(mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX));
550         assertNull(
551                 mTelephonySubscriptionTracker
552                         .getSubIdToCarrierConfigMap()
553                         .get(TEST_SUBSCRIPTION_ID_1));
554     }
555 
556     @Test
testChangingPrivilegedPackagesAfterValidTriggersCallbacks()557     public void testChangingPrivilegedPackagesAfterValidTriggersCallbacks() throws Exception {
558         setupReadySubIds();
559 
560         // Setup initial "valid" state
561         final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
562         listener.onSubscriptionsChanged();
563         mTestLooper.dispatchAll();
564 
565         verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES)));
566 
567         // Simulate a loss of carrier privileges
568         setPrivilegedPackagesForMock(Collections.emptyList());
569         listener.onSubscriptionsChanged();
570         mTestLooper.dispatchAll();
571 
572         verify(mCallback)
573                 .onNewSnapshot(
574                         eq(buildExpectedSnapshot(singletonMap(TEST_PARCEL_UUID, emptySet()))));
575     }
576 
577     @Test
testTelephonySubscriptionSnapshotGetGroupForSubId()578     public void testTelephonySubscriptionSnapshotGetGroupForSubId() throws Exception {
579         final TelephonySubscriptionSnapshot snapshot =
580                 new TelephonySubscriptionSnapshot(
581                         TEST_SUBSCRIPTION_ID_1, TEST_SUBID_TO_INFO_MAP, emptyMap(), emptyMap());
582 
583         assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_1));
584         assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_2));
585     }
586 
587     @Test
testTelephonySubscriptionSnapshotGetAllSubIdsInGroup()588     public void testTelephonySubscriptionSnapshotGetAllSubIdsInGroup() throws Exception {
589         final TelephonySubscriptionSnapshot snapshot =
590                 new TelephonySubscriptionSnapshot(
591                         TEST_SUBSCRIPTION_ID_1, TEST_SUBID_TO_INFO_MAP, emptyMap(), emptyMap());
592 
593         assertEquals(
594                 new ArraySet<>(Arrays.asList(TEST_SUBSCRIPTION_ID_1, TEST_SUBSCRIPTION_ID_2)),
595                 snapshot.getAllSubIdsInGroup(TEST_PARCEL_UUID));
596     }
597 }
598