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.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED; 20 import static android.telephony.CarrierConfigManager.EXTRA_SLOT_INDEX; 21 import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX; 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 26 import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; 27 import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback; 28 29 import static org.junit.Assert.assertEquals; 30 import static org.junit.Assert.assertNotNull; 31 import static org.junit.Assert.assertNull; 32 import static org.junit.Assert.assertTrue; 33 import static org.mockito.ArgumentMatchers.any; 34 import static org.mockito.ArgumentMatchers.anyInt; 35 import static org.mockito.ArgumentMatchers.argThat; 36 import static org.mockito.ArgumentMatchers.eq; 37 import static org.mockito.Mockito.doReturn; 38 import static org.mockito.Mockito.mock; 39 import static org.mockito.Mockito.verify; 40 import static org.mockito.Mockito.verifyNoMoreInteractions; 41 42 import static java.util.Collections.emptyMap; 43 import static java.util.Collections.emptySet; 44 import static java.util.Collections.singletonMap; 45 46 import android.annotation.NonNull; 47 import android.content.Context; 48 import android.content.Intent; 49 import android.content.IntentFilter; 50 import android.os.Handler; 51 import android.os.HandlerExecutor; 52 import android.os.ParcelUuid; 53 import android.os.test.TestLooper; 54 import android.telephony.CarrierConfigManager; 55 import android.telephony.SubscriptionInfo; 56 import android.telephony.SubscriptionManager; 57 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 58 import android.telephony.TelephonyCallback; 59 import android.telephony.TelephonyManager; 60 import android.util.ArraySet; 61 62 import androidx.test.filters.SmallTest; 63 import androidx.test.runner.AndroidJUnit4; 64 65 import org.junit.Before; 66 import org.junit.Test; 67 import org.junit.runner.RunWith; 68 import org.mockito.ArgumentCaptor; 69 70 import java.util.ArrayList; 71 import java.util.Arrays; 72 import java.util.Collections; 73 import java.util.HashMap; 74 import java.util.List; 75 import java.util.Map; 76 import java.util.Set; 77 import java.util.UUID; 78 79 /** Tests for TelephonySubscriptionTracker */ 80 @RunWith(AndroidJUnit4.class) 81 @SmallTest 82 public class TelephonySubscriptionTrackerTest { 83 private static final String PACKAGE_NAME = 84 TelephonySubscriptionTrackerTest.class.getPackage().getName(); 85 private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID()); 86 private static final int TEST_SIM_SLOT_INDEX = 1; 87 private static final int TEST_SUBSCRIPTION_ID_1 = 2; 88 private static final SubscriptionInfo TEST_SUBINFO_1 = mock(SubscriptionInfo.class); 89 private static final int TEST_SUBSCRIPTION_ID_2 = 3; 90 private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class); 91 private static final Map<ParcelUuid, Set<String>> TEST_PRIVILEGED_PACKAGES = 92 Collections.singletonMap(TEST_PARCEL_UUID, Collections.singleton(PACKAGE_NAME)); 93 private static final Map<Integer, SubscriptionInfo> TEST_SUBID_TO_INFO_MAP; 94 95 static { 96 final Map<Integer, SubscriptionInfo> subIdToGroupMap = new HashMap<>(); subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_SUBINFO_1)97 subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_SUBINFO_1); subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_SUBINFO_2)98 subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_SUBINFO_2); 99 TEST_SUBID_TO_INFO_MAP = Collections.unmodifiableMap(subIdToGroupMap); 100 } 101 102 @NonNull private final Context mContext; 103 @NonNull private final TestLooper mTestLooper; 104 @NonNull private final Handler mHandler; 105 @NonNull private final TelephonySubscriptionTracker.Dependencies mDeps; 106 107 @NonNull private final TelephonyManager mTelephonyManager; 108 @NonNull private final SubscriptionManager mSubscriptionManager; 109 @NonNull private final CarrierConfigManager mCarrierConfigManager; 110 111 @NonNull private TelephonySubscriptionTrackerCallback mCallback; 112 @NonNull private TelephonySubscriptionTracker mTelephonySubscriptionTracker; 113 TelephonySubscriptionTrackerTest()114 public TelephonySubscriptionTrackerTest() { 115 mContext = mock(Context.class); 116 mTestLooper = new TestLooper(); 117 mHandler = new Handler(mTestLooper.getLooper()); 118 mDeps = mock(TelephonySubscriptionTracker.Dependencies.class); 119 120 mTelephonyManager = mock(TelephonyManager.class); 121 mSubscriptionManager = mock(SubscriptionManager.class); 122 mCarrierConfigManager = mock(CarrierConfigManager.class); 123 124 doReturn(Context.TELEPHONY_SERVICE) 125 .when(mContext) 126 .getSystemServiceName(TelephonyManager.class); 127 doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE); 128 129 doReturn(Context.TELEPHONY_SUBSCRIPTION_SERVICE) 130 .when(mContext) 131 .getSystemServiceName(SubscriptionManager.class); 132 doReturn(mSubscriptionManager) 133 .when(mContext) 134 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); 135 136 doReturn(Context.CARRIER_CONFIG_SERVICE) 137 .when(mContext) 138 .getSystemServiceName(CarrierConfigManager.class); 139 doReturn(mCarrierConfigManager) 140 .when(mContext) 141 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 142 143 // subId 1, 2 are in same subGrp, only subId 1 is active 144 doReturn(TEST_PARCEL_UUID).when(TEST_SUBINFO_1).getGroupUuid(); 145 doReturn(TEST_PARCEL_UUID).when(TEST_SUBINFO_2).getGroupUuid(); 146 doReturn(TEST_SIM_SLOT_INDEX).when(TEST_SUBINFO_1).getSimSlotIndex(); 147 doReturn(INVALID_SIM_SLOT_INDEX).when(TEST_SUBINFO_2).getSimSlotIndex(); 148 doReturn(TEST_SUBSCRIPTION_ID_1).when(TEST_SUBINFO_1).getSubscriptionId(); 149 doReturn(TEST_SUBSCRIPTION_ID_2).when(TEST_SUBINFO_2).getSubscriptionId(); 150 } 151 152 @Before setUp()153 public void setUp() throws Exception { 154 mCallback = mock(TelephonySubscriptionTrackerCallback.class); 155 mTelephonySubscriptionTracker = 156 new TelephonySubscriptionTracker(mContext, mHandler, mCallback, mDeps); 157 mTelephonySubscriptionTracker.register(); 158 159 doReturn(true).when(mDeps).isConfigForIdentifiedCarrier(any()); 160 doReturn(Arrays.asList(TEST_SUBINFO_1, TEST_SUBINFO_2)) 161 .when(mSubscriptionManager) 162 .getAllSubscriptionInfoList(); 163 164 doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt()); 165 setPrivilegedPackagesForMock(Collections.singletonList(PACKAGE_NAME)); 166 } 167 getIntentFilter()168 private IntentFilter getIntentFilter() { 169 final ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class); 170 verify(mContext).registerReceiver(any(), captor.capture(), any(), any()); 171 172 return captor.getValue(); 173 } 174 getOnSubscriptionsChangedListener()175 private OnSubscriptionsChangedListener getOnSubscriptionsChangedListener() { 176 final ArgumentCaptor<OnSubscriptionsChangedListener> captor = 177 ArgumentCaptor.forClass(OnSubscriptionsChangedListener.class); 178 verify(mSubscriptionManager).addOnSubscriptionsChangedListener(any(), captor.capture()); 179 180 return captor.getValue(); 181 } 182 getActiveDataSubscriptionIdListener()183 private ActiveDataSubscriptionIdListener getActiveDataSubscriptionIdListener() { 184 final ArgumentCaptor<TelephonyCallback> captor = 185 ArgumentCaptor.forClass(TelephonyCallback.class); 186 verify(mTelephonyManager).registerTelephonyCallback(any(), captor.capture()); 187 188 return (ActiveDataSubscriptionIdListener) captor.getValue(); 189 } 190 buildTestBroadcastIntent(boolean hasValidSubscription)191 private Intent buildTestBroadcastIntent(boolean hasValidSubscription) { 192 Intent intent = new Intent(ACTION_CARRIER_CONFIG_CHANGED); 193 intent.putExtra(EXTRA_SLOT_INDEX, TEST_SIM_SLOT_INDEX); 194 intent.putExtra( 195 EXTRA_SUBSCRIPTION_INDEX, 196 hasValidSubscription ? TEST_SUBSCRIPTION_ID_1 : INVALID_SUBSCRIPTION_ID); 197 198 return intent; 199 } 200 buildExpectedSnapshot( Map<ParcelUuid, Set<String>> privilegedPackages)201 private TelephonySubscriptionSnapshot buildExpectedSnapshot( 202 Map<ParcelUuid, Set<String>> privilegedPackages) { 203 return buildExpectedSnapshot(TEST_SUBID_TO_INFO_MAP, privilegedPackages); 204 } 205 buildExpectedSnapshot( Map<Integer, SubscriptionInfo> subIdToInfoMap, Map<ParcelUuid, Set<String>> privilegedPackages)206 private TelephonySubscriptionSnapshot buildExpectedSnapshot( 207 Map<Integer, SubscriptionInfo> subIdToInfoMap, 208 Map<ParcelUuid, Set<String>> privilegedPackages) { 209 return new TelephonySubscriptionSnapshot(0, subIdToInfoMap, privilegedPackages); 210 } 211 buildExpectedSnapshot( int activeSubId, Map<Integer, SubscriptionInfo> subIdToInfoMap, Map<ParcelUuid, Set<String>> privilegedPackages)212 private TelephonySubscriptionSnapshot buildExpectedSnapshot( 213 int activeSubId, 214 Map<Integer, SubscriptionInfo> subIdToInfoMap, 215 Map<ParcelUuid, Set<String>> privilegedPackages) { 216 return new TelephonySubscriptionSnapshot(activeSubId, subIdToInfoMap, privilegedPackages); 217 } 218 verifyNoActiveSubscriptions()219 private void verifyNoActiveSubscriptions() { 220 verify(mCallback).onNewSnapshot( 221 argThat(snapshot -> snapshot.getActiveSubscriptionGroups().isEmpty())); 222 } 223 setupReadySubIds()224 private void setupReadySubIds() { 225 mTelephonySubscriptionTracker.setReadySubIdsBySlotId( 226 Collections.singletonMap(TEST_SIM_SLOT_INDEX, TEST_SUBSCRIPTION_ID_1)); 227 } 228 setPrivilegedPackagesForMock(@onNull List<String> privilegedPackages)229 private void setPrivilegedPackagesForMock(@NonNull List<String> privilegedPackages) { 230 doReturn(privilegedPackages).when(mTelephonyManager).getPackagesWithCarrierPrivileges(); 231 } 232 233 @Test testRegister()234 public void testRegister() throws Exception { 235 verify(mContext) 236 .registerReceiver( 237 eq(mTelephonySubscriptionTracker), 238 any(IntentFilter.class), 239 any(), 240 eq(mHandler)); 241 final IntentFilter filter = getIntentFilter(); 242 assertEquals(1, filter.countActions()); 243 assertTrue(filter.hasAction(ACTION_CARRIER_CONFIG_CHANGED)); 244 245 verify(mSubscriptionManager) 246 .addOnSubscriptionsChangedListener(any(HandlerExecutor.class), any()); 247 assertNotNull(getOnSubscriptionsChangedListener()); 248 } 249 250 @Test testUnregister()251 public void testUnregister() throws Exception { 252 mTelephonySubscriptionTracker.unregister(); 253 254 verify(mContext).unregisterReceiver(eq(mTelephonySubscriptionTracker)); 255 256 final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener(); 257 verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(eq(listener)); 258 } 259 260 @Test testOnSubscriptionsChangedFired_NoReadySubIds()261 public void testOnSubscriptionsChangedFired_NoReadySubIds() throws Exception { 262 final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener(); 263 listener.onSubscriptionsChanged(); 264 mTestLooper.dispatchAll(); 265 266 verifyNoActiveSubscriptions(); 267 } 268 269 @Test testOnSubscriptionsChangedFired_onActiveSubIdsChanged()270 public void testOnSubscriptionsChangedFired_onActiveSubIdsChanged() throws Exception { 271 setupReadySubIds(); 272 setPrivilegedPackagesForMock(Collections.emptyList()); 273 274 doReturn(TEST_SUBSCRIPTION_ID_2).when(mDeps).getActiveDataSubscriptionId(); 275 final ActiveDataSubscriptionIdListener listener = getActiveDataSubscriptionIdListener(); 276 listener.onActiveDataSubscriptionIdChanged(TEST_SUBSCRIPTION_ID_2); 277 mTestLooper.dispatchAll(); 278 279 ArgumentCaptor<TelephonySubscriptionSnapshot> snapshotCaptor = 280 ArgumentCaptor.forClass(TelephonySubscriptionSnapshot.class); 281 verify(mCallback).onNewSnapshot(snapshotCaptor.capture()); 282 283 TelephonySubscriptionSnapshot snapshot = snapshotCaptor.getValue(); 284 assertNotNull(snapshot); 285 assertEquals(TEST_SUBSCRIPTION_ID_2, snapshot.getActiveDataSubscriptionId()); 286 assertEquals(TEST_PARCEL_UUID, snapshot.getActiveDataSubscriptionGroup()); 287 } 288 289 @Test testOnSubscriptionsChangedFired_WithReadySubidsNoPrivilegedPackages()290 public void testOnSubscriptionsChangedFired_WithReadySubidsNoPrivilegedPackages() 291 throws Exception { 292 setupReadySubIds(); 293 setPrivilegedPackagesForMock(Collections.emptyList()); 294 295 final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener(); 296 listener.onSubscriptionsChanged(); 297 mTestLooper.dispatchAll(); 298 299 final Map<ParcelUuid, Set<String>> privilegedPackages = 300 Collections.singletonMap(TEST_PARCEL_UUID, new ArraySet<>()); 301 verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(privilegedPackages))); 302 } 303 304 @Test testOnSubscriptionsChangedFired_WithReadySubidsAndPrivilegedPackages()305 public void testOnSubscriptionsChangedFired_WithReadySubidsAndPrivilegedPackages() 306 throws Exception { 307 setupReadySubIds(); 308 309 final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener(); 310 listener.onSubscriptionsChanged(); 311 mTestLooper.dispatchAll(); 312 313 verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); 314 } 315 316 @Test testReceiveBroadcast_ConfigReadyWithSubscriptions()317 public void testReceiveBroadcast_ConfigReadyWithSubscriptions() throws Exception { 318 mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); 319 mTestLooper.dispatchAll(); 320 321 verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); 322 } 323 324 @Test testReceiveBroadcast_ConfigReadyNoSubscriptions()325 public void testReceiveBroadcast_ConfigReadyNoSubscriptions() throws Exception { 326 doReturn(new ArrayList<SubscriptionInfo>()) 327 .when(mSubscriptionManager) 328 .getAllSubscriptionInfoList(); 329 330 mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); 331 mTestLooper.dispatchAll(); 332 333 // Expect an empty snapshot 334 verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(emptyMap(), emptyMap()))); 335 } 336 337 @Test testReceiveBroadcast_SlotCleared()338 public void testReceiveBroadcast_SlotCleared() throws Exception { 339 setupReadySubIds(); 340 341 mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(false)); 342 mTestLooper.dispatchAll(); 343 344 verifyNoActiveSubscriptions(); 345 assertTrue(mTelephonySubscriptionTracker.getReadySubIdsBySlotId().isEmpty()); 346 } 347 348 @Test testReceiveBroadcast_ConfigNotReady()349 public void testReceiveBroadcast_ConfigNotReady() throws Exception { 350 doReturn(false).when(mDeps).isConfigForIdentifiedCarrier(any()); 351 352 mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); 353 mTestLooper.dispatchAll(); 354 355 // No interactions expected; config was not loaded 356 verifyNoMoreInteractions(mCallback); 357 } 358 359 @Test testSubscriptionsClearedAfterValidTriggersCallbacks()360 public void testSubscriptionsClearedAfterValidTriggersCallbacks() throws Exception { 361 mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); 362 mTestLooper.dispatchAll(); 363 verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); 364 assertNotNull( 365 mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX)); 366 367 doReturn(Collections.emptyList()).when(mSubscriptionManager).getAllSubscriptionInfoList(); 368 mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); 369 mTestLooper.dispatchAll(); 370 verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(emptyMap(), emptyMap()))); 371 } 372 373 @Test testSlotClearedAfterValidTriggersCallbacks()374 public void testSlotClearedAfterValidTriggersCallbacks() throws Exception { 375 mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true)); 376 mTestLooper.dispatchAll(); 377 verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); 378 assertNotNull( 379 mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX)); 380 381 mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(false)); 382 mTestLooper.dispatchAll(); 383 verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(emptyMap()))); 384 assertNull(mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX)); 385 } 386 387 @Test testChangingPrivilegedPackagesAfterValidTriggersCallbacks()388 public void testChangingPrivilegedPackagesAfterValidTriggersCallbacks() throws Exception { 389 setupReadySubIds(); 390 391 // Setup initial "valid" state 392 final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener(); 393 listener.onSubscriptionsChanged(); 394 mTestLooper.dispatchAll(); 395 396 verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(TEST_PRIVILEGED_PACKAGES))); 397 398 // Simulate a loss of carrier privileges 399 setPrivilegedPackagesForMock(Collections.emptyList()); 400 listener.onSubscriptionsChanged(); 401 mTestLooper.dispatchAll(); 402 403 verify(mCallback) 404 .onNewSnapshot( 405 eq(buildExpectedSnapshot(singletonMap(TEST_PARCEL_UUID, emptySet())))); 406 } 407 408 @Test testTelephonySubscriptionSnapshotGetGroupForSubId()409 public void testTelephonySubscriptionSnapshotGetGroupForSubId() throws Exception { 410 final TelephonySubscriptionSnapshot snapshot = 411 new TelephonySubscriptionSnapshot( 412 TEST_SUBSCRIPTION_ID_1, TEST_SUBID_TO_INFO_MAP, emptyMap()); 413 414 assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_1)); 415 assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_2)); 416 } 417 418 @Test testTelephonySubscriptionSnapshotGetAllSubIdsInGroup()419 public void testTelephonySubscriptionSnapshotGetAllSubIdsInGroup() throws Exception { 420 final TelephonySubscriptionSnapshot snapshot = 421 new TelephonySubscriptionSnapshot( 422 TEST_SUBSCRIPTION_ID_1, TEST_SUBID_TO_INFO_MAP, emptyMap()); 423 424 assertEquals( 425 new ArraySet<>(Arrays.asList(TEST_SUBSCRIPTION_ID_1, TEST_SUBSCRIPTION_ID_2)), 426 snapshot.getAllSubIdsInGroup(TEST_PARCEL_UUID)); 427 } 428 } 429