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.car.settings.system; 18 19 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; 20 import static android.telephony.SubscriptionManager.MIN_SUBSCRIPTION_ID_VALUE; 21 22 import static com.android.car.settings.common.PreferenceController.AVAILABLE; 23 import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING; 24 import static com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE; 25 import static com.android.car.settings.common.PreferenceController.UNSUPPORTED_ON_DEVICE; 26 27 import static com.google.common.truth.Truth.assertThat; 28 29 import static org.mockito.ArgumentMatchers.anyInt; 30 import static org.mockito.Mockito.mock; 31 import static org.mockito.Mockito.spy; 32 import static org.mockito.Mockito.when; 33 import static org.mockito.Mockito.withSettings; 34 35 import android.car.drivingstate.CarUxRestrictions; 36 import android.content.Context; 37 import android.content.pm.PackageManager; 38 import android.telephony.SubscriptionInfo; 39 import android.telephony.SubscriptionManager; 40 41 import androidx.lifecycle.LifecycleOwner; 42 import androidx.preference.ListPreference; 43 import androidx.test.core.app.ApplicationProvider; 44 import androidx.test.ext.junit.runners.AndroidJUnit4; 45 46 import com.android.car.settings.common.FragmentController; 47 import com.android.car.settings.common.PreferenceControllerTestUtil; 48 import com.android.car.settings.testutils.TestLifecycleOwner; 49 import com.android.dx.mockito.inline.extended.ExtendedMockito; 50 51 import org.junit.After; 52 import org.junit.Before; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.mockito.Mock; 56 import org.mockito.MockitoAnnotations; 57 import org.mockito.MockitoSession; 58 59 import java.util.Arrays; 60 import java.util.Collections; 61 import java.util.List; 62 63 /** Unit test for {@link ResetNetworkSubscriptionPreferenceController}. */ 64 @RunWith(AndroidJUnit4.class) 65 public class ResetNetworkSubscriptionPreferenceControllerTest { 66 private static final int SUBID_1 = MIN_SUBSCRIPTION_ID_VALUE; 67 private static final int SUBID_2 = SUBID_1 + 1; 68 private static final int SUBID_3 = SUBID_2 + 1; 69 private static final int SUBID_4 = SUBID_3 + 1; 70 71 private Context mContext = spy(ApplicationProvider.getApplicationContext()); 72 private LifecycleOwner mLifecycleOwner; 73 private ListPreference mPreference; 74 private ResetNetworkSubscriptionPreferenceController mPreferenceController; 75 private CarUxRestrictions mCarUxRestrictions; 76 private MockitoSession mSession; 77 78 @Mock 79 private FragmentController mFragmentController; 80 @Mock 81 private PackageManager mMockPm; 82 @Mock 83 private SubscriptionManager mMockSubscriptionManager; 84 85 @Before setUp()86 public void setUp() { 87 MockitoAnnotations.initMocks(this); 88 mLifecycleOwner = new TestLifecycleOwner(); 89 90 mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true, 91 CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build(); 92 93 when(mContext.getPackageManager()).thenReturn(mMockPm); 94 // Default to AVAILABLE status. Tests for this behavior will do their own setup. 95 when(mMockPm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(true); 96 when(mContext.getSystemService(SubscriptionManager.class)) 97 .thenReturn(mMockSubscriptionManager); 98 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null); 99 mSession = ExtendedMockito.mockitoSession().mockStatic( 100 SubscriptionManager.class, withSettings().lenient()).startMocking(); 101 // Default to having no defaults. Tests for this behavior will do their own setup. 102 when(SubscriptionManager.isUsableSubIdValue(anyInt())).thenCallRealMethod(); 103 when(SubscriptionManager.getDefaultSubscriptionId()).thenReturn(INVALID_SUBSCRIPTION_ID); 104 when(SubscriptionManager.getDefaultSmsSubscriptionId()).thenReturn(INVALID_SUBSCRIPTION_ID); 105 when(SubscriptionManager.getDefaultVoiceSubscriptionId()).thenReturn( 106 INVALID_SUBSCRIPTION_ID); 107 when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn( 108 INVALID_SUBSCRIPTION_ID); 109 110 mPreference = new ListPreference(mContext); 111 mPreferenceController = new ResetNetworkSubscriptionPreferenceController(mContext, 112 "key", mFragmentController, mCarUxRestrictions); 113 PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference); 114 mPreferenceController.onCreate(mLifecycleOwner); 115 } 116 117 @After tearDown()118 public void tearDown() { 119 if (mSession != null) { 120 mSession.finishMocking(); 121 } 122 } 123 124 @Test getAvailabilityStatus_telephonyAvailable_available()125 public void getAvailabilityStatus_telephonyAvailable_available() { 126 assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(AVAILABLE); 127 } 128 129 @Test getAvailabilityStatus_telephonyAvailable_available_zoneWrite()130 public void getAvailabilityStatus_telephonyAvailable_available_zoneWrite() { 131 mPreferenceController.setAvailabilityStatusForZone("write"); 132 PreferenceControllerTestUtil.assertAvailability( 133 mPreferenceController.getAvailabilityStatus(), AVAILABLE); 134 } 135 136 @Test getAvailabilityStatus_telephonyAvailable_available_zoneRead()137 public void getAvailabilityStatus_telephonyAvailable_available_zoneRead() { 138 mPreferenceController.setAvailabilityStatusForZone("read"); 139 PreferenceControllerTestUtil.assertAvailability( 140 mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING); 141 } 142 143 @Test getAvailabilityStatus_telephonyAvailable_available_zoneHidden()144 public void getAvailabilityStatus_telephonyAvailable_available_zoneHidden() { 145 mPreferenceController.setAvailabilityStatusForZone("hidden"); 146 PreferenceControllerTestUtil.assertAvailability( 147 mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE); 148 } 149 150 @Test getAvailabilityStatus_telephonyNotAvailable_unsupportedOnDevice()151 public void getAvailabilityStatus_telephonyNotAvailable_unsupportedOnDevice() { 152 when(mMockPm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(false); 153 154 assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); 155 } 156 157 @Test getAvailabilityStatus_telephonyNotAvailable_unsupportedOnDevice_zoneWrite()158 public void getAvailabilityStatus_telephonyNotAvailable_unsupportedOnDevice_zoneWrite() { 159 when(mMockPm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(false); 160 mPreferenceController.setAvailabilityStatusForZone("write"); 161 162 PreferenceControllerTestUtil.assertAvailability( 163 mPreferenceController.getAvailabilityStatus(), UNSUPPORTED_ON_DEVICE); 164 } 165 166 @Test getAvailabilityStatus_telephonyNotAvailable_unsupportedOnDevice_zoneRead()167 public void getAvailabilityStatus_telephonyNotAvailable_unsupportedOnDevice_zoneRead() { 168 when(mMockPm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(false); 169 mPreferenceController.setAvailabilityStatusForZone("read"); 170 171 PreferenceControllerTestUtil.assertAvailability( 172 mPreferenceController.getAvailabilityStatus(), UNSUPPORTED_ON_DEVICE); 173 } 174 175 @Test getAvailabilityStatus_telephonyNotAvailable_unsupportedOnDevice_zoneHidden()176 public void getAvailabilityStatus_telephonyNotAvailable_unsupportedOnDevice_zoneHidden() { 177 when(mMockPm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(false); 178 mPreferenceController.setAvailabilityStatusForZone("hidden"); 179 180 PreferenceControllerTestUtil.assertAvailability( 181 mPreferenceController.getAvailabilityStatus(), UNSUPPORTED_ON_DEVICE); 182 } 183 184 @Test refreshUi_nullSubscriptions_hidesPreference()185 public void refreshUi_nullSubscriptions_hidesPreference() { 186 mPreferenceController.refreshUi(); 187 188 assertThat(mPreference.isVisible()).isFalse(); 189 } 190 191 @Test refreshUi_nullSubscriptions_setsValue()192 public void refreshUi_nullSubscriptions_setsValue() { 193 mPreferenceController.refreshUi(); 194 195 assertThat(mPreference.getValue()).isEqualTo( 196 String.valueOf(INVALID_SUBSCRIPTION_ID)); 197 } 198 199 @Test refreshUi_noSubscriptions_hidesPreference()200 public void refreshUi_noSubscriptions_hidesPreference() { 201 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 202 .thenReturn(Collections.emptyList()); 203 204 mPreferenceController.refreshUi(); 205 206 assertThat(mPreference.isVisible()).isFalse(); 207 } 208 209 @Test refreshUi_noSubscriptions_setsValue()210 public void refreshUi_noSubscriptions_setsValue() { 211 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 212 .thenReturn(Collections.emptyList()); 213 214 mPreferenceController.refreshUi(); 215 216 assertThat(mPreference.getValue()).isEqualTo( 217 String.valueOf(INVALID_SUBSCRIPTION_ID)); 218 } 219 220 @Test refreshUi_oneSubscription_hidesPreference()221 public void refreshUi_oneSubscription_hidesPreference() { 222 List<SubscriptionInfo> subscriptionInfoList = Collections.singletonList( 223 createSubInfo(SUBID_1, "sub1")); 224 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 225 .thenReturn(subscriptionInfoList); 226 227 mPreferenceController.refreshUi(); 228 229 assertThat(mPreference.isVisible()).isFalse(); 230 } 231 232 @Test refreshUi_oneSubscription_setsValue()233 public void refreshUi_oneSubscription_setsValue() { 234 List<SubscriptionInfo> subscriptionInfoList = Collections.singletonList( 235 createSubInfo(SUBID_1, "sub1")); 236 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 237 .thenReturn(subscriptionInfoList); 238 239 mPreferenceController.refreshUi(); 240 241 assertThat(mPreference.getValue()).isEqualTo(String.valueOf(SUBID_1)); 242 } 243 244 @Test refreshUi_multipleSubscriptions_showsPreference()245 public void refreshUi_multipleSubscriptions_showsPreference() { 246 List<SubscriptionInfo> subscriptionInfoList = Arrays.asList(createSubInfo(SUBID_1, "sub1"), 247 createSubInfo(SUBID_2, "sub2")); 248 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 249 .thenReturn(subscriptionInfoList); 250 251 mPreferenceController.refreshUi(); 252 253 assertThat(mPreference.isVisible()).isTrue(); 254 } 255 256 @Test refreshUi_multipleSubscriptions_populatesEntries()257 public void refreshUi_multipleSubscriptions_populatesEntries() { 258 String displayName1 = "sub1"; 259 String displayName2 = "sub2"; 260 List<SubscriptionInfo> subscriptionInfoList = Arrays.asList( 261 createSubInfo(SUBID_1, displayName1), createSubInfo(SUBID_2, displayName2)); 262 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 263 .thenReturn(subscriptionInfoList); 264 265 mPreferenceController.refreshUi(); 266 267 assertThat(Arrays.asList(mPreference.getEntries())).containsExactly(displayName1, 268 displayName2); 269 assertThat(Arrays.asList(mPreference.getEntryValues())).containsExactly( 270 String.valueOf(SUBID_1), 271 String.valueOf(SUBID_2)); 272 } 273 274 @Test refreshUi_defaultSelection_fourthPriority_system()275 public void refreshUi_defaultSelection_fourthPriority_system() { 276 List<SubscriptionInfo> subscriptionInfoList = Arrays.asList( 277 createSubInfo(SUBID_1, "sub1"), createSubInfo(SUBID_2, "sub2"), 278 createSubInfo(SUBID_3, "sub3"), createSubInfo(SUBID_4, "sub4")); 279 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 280 .thenReturn(subscriptionInfoList); 281 282 setDefaultSubscriptionId(SUBID_4); 283 mPreferenceController.refreshUi(); 284 285 assertThat(mPreference.getValue()).isEqualTo(String.valueOf(SUBID_4)); 286 } 287 288 @Test refreshUi_defaultSelection_thirdPriority_sms()289 public void refreshUi_defaultSelection_thirdPriority_sms() { 290 List<SubscriptionInfo> subscriptionInfoList = Arrays.asList(createSubInfo(SUBID_1, "sub1"), 291 createSubInfo(SUBID_2, "sub2"), createSubInfo(SUBID_3, "sub3"), 292 createSubInfo(SUBID_4, "sub4")); 293 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 294 .thenReturn(subscriptionInfoList); 295 296 setDefaultSubscriptionId(SUBID_4); 297 setDefaultSmsSubscriptionId(SUBID_3); 298 mPreferenceController.refreshUi(); 299 300 assertThat(mPreference.getValue()).isEqualTo(String.valueOf(SUBID_3)); 301 } 302 303 @Test refreshUi_defaultSelection_secondPriority_voice()304 public void refreshUi_defaultSelection_secondPriority_voice() { 305 List<SubscriptionInfo> subscriptionInfoList = Arrays.asList(createSubInfo(SUBID_1, "sub1"), 306 createSubInfo(SUBID_2, "sub2"), createSubInfo(SUBID_3, "sub3"), 307 createSubInfo(SUBID_4, "sub4")); 308 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 309 .thenReturn(subscriptionInfoList); 310 311 setDefaultSubscriptionId(SUBID_4); 312 setDefaultSmsSubscriptionId(SUBID_3); 313 setDefaultVoiceSubscriptionId(SUBID_2); 314 mPreferenceController.refreshUi(); 315 316 assertThat(mPreference.getValue()).isEqualTo(String.valueOf(SUBID_2)); 317 } 318 319 @Test refreshUi_defaultSelection_firstPriority_data()320 public void refreshUi_defaultSelection_firstPriority_data() { 321 List<SubscriptionInfo> subscriptionInfoList = Arrays.asList(createSubInfo(SUBID_1, "sub1"), 322 createSubInfo(SUBID_2, "sub2"), createSubInfo(SUBID_3, "sub3"), 323 createSubInfo(SUBID_4, "sub4")); 324 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 325 .thenReturn(subscriptionInfoList); 326 327 setDefaultSubscriptionId(SUBID_4); 328 setDefaultSmsSubscriptionId(SUBID_3); 329 setDefaultVoiceSubscriptionId(SUBID_2); 330 setDefaultDataSubscriptionId(SUBID_1); 331 mPreferenceController.refreshUi(); 332 333 assertThat(mPreference.getValue()).isEqualTo(String.valueOf(SUBID_1)); 334 } 335 336 @Test refreshUi_title_fourthPriority_subscriptionNetworkIds()337 public void refreshUi_title_fourthPriority_subscriptionNetworkIds() { 338 SubscriptionInfo subInfo = createSubInfo( 339 SUBID_1, 340 /* displayName= */ "", 341 /* carrierName= */ "", 342 /* number= */ ""); 343 // Multiple subscriptions so that preference is shown / title is set. 344 List<SubscriptionInfo> subscriptionInfoList = Arrays.asList(subInfo, 345 createSubInfo(SUBID_2, "sub2")); 346 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 347 .thenReturn(subscriptionInfoList); 348 setDefaultDataSubscriptionId(SUBID_1); 349 350 mPreferenceController.refreshUi(); 351 352 String title = mPreference.getTitle().toString(); 353 assertThat(title).contains(String.valueOf(subInfo.getMcc())); 354 assertThat(title).contains(String.valueOf(subInfo.getMnc())); 355 assertThat(title).contains(String.valueOf(subInfo.getSimSlotIndex())); 356 assertThat(title).contains(String.valueOf(subInfo.getSubscriptionId())); 357 } 358 359 @Test refreshUi_title_thirdPriority_subscriptionCarrierName()360 public void refreshUi_title_thirdPriority_subscriptionCarrierName() { 361 SubscriptionInfo subInfo = createSubInfo( 362 SUBID_1, 363 /* displayName= */ "", 364 "carrierName", 365 /* number= */ ""); 366 // Multiple subscriptions so that preference is shown / title is set. 367 // Multiple subscriptions so that preference is shown / title is set. 368 List<SubscriptionInfo> subscriptionInfoList = Arrays.asList(subInfo, 369 createSubInfo(SUBID_2, "sub2")); 370 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 371 .thenReturn(subscriptionInfoList); 372 setDefaultDataSubscriptionId(SUBID_1); 373 374 mPreferenceController.refreshUi(); 375 376 assertThat(mPreference.getTitle()).isEqualTo(subInfo.getCarrierName()); 377 } 378 379 @Test refreshUi_title_secondPriority_subscriptionNumber()380 public void refreshUi_title_secondPriority_subscriptionNumber() { 381 SubscriptionInfo subInfo = createSubInfo( 382 SUBID_1, 383 /* displayName= */ "", 384 "carrierName", 385 "number"); 386 // Multiple subscriptions so that preference is shown / title is set. 387 List<SubscriptionInfo> subscriptionInfoList = Arrays.asList(subInfo, 388 createSubInfo(SUBID_2, "sub2")); 389 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 390 .thenReturn(subscriptionInfoList); 391 setDefaultDataSubscriptionId(SUBID_1); 392 393 mPreferenceController.refreshUi(); 394 395 assertThat(mPreference.getTitle()).isEqualTo(subInfo.getNumber()); 396 } 397 398 @Test refreshUi_title_firstPriority_subscriptionDisplayName()399 public void refreshUi_title_firstPriority_subscriptionDisplayName() { 400 SubscriptionInfo subInfo = createSubInfo( 401 SUBID_1, 402 "displayName", 403 "carrierName", 404 "number"); 405 // Multiple subscriptions so that preference is shown / title is set. 406 List<SubscriptionInfo> subscriptionInfoList = Arrays.asList(subInfo, 407 createSubInfo(SUBID_2, "sub2")); 408 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 409 .thenReturn(subscriptionInfoList); 410 setDefaultDataSubscriptionId(SUBID_1); 411 412 mPreferenceController.refreshUi(); 413 414 assertThat(mPreference.getTitle()).isEqualTo(subInfo.getDisplayName()); 415 } 416 417 @Test handlePreferenceChanged_updatesTitle()418 public void handlePreferenceChanged_updatesTitle() { 419 List<SubscriptionInfo> subscriptionInfoList = Arrays.asList(createSubInfo(SUBID_1, "sub1"), 420 createSubInfo(SUBID_2, "sub2")); 421 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 422 .thenReturn(subscriptionInfoList); 423 setDefaultDataSubscriptionId(SUBID_1); 424 mPreferenceController.refreshUi(); 425 426 mPreference.callChangeListener(String.valueOf(SUBID_2)); 427 428 assertThat(mPreference.getTitle()).isEqualTo("sub2"); 429 } 430 431 @Test handlePreferenceChanged_returnsTrue()432 public void handlePreferenceChanged_returnsTrue() { 433 List<SubscriptionInfo> subscriptionInfoList = Arrays.asList(createSubInfo(SUBID_1, "sub1"), 434 createSubInfo(SUBID_2, "sub2")); 435 when(mMockSubscriptionManager.getActiveSubscriptionInfoList()) 436 .thenReturn(subscriptionInfoList); 437 setDefaultDataSubscriptionId(SUBID_1); 438 mPreferenceController.refreshUi(); 439 440 assertThat(mPreferenceController.handlePreferenceChanged(mPreference, 441 String.valueOf(SUBID_2))).isTrue(); 442 } 443 444 /** Reduce SubscriptionInfo constructor args to the ones we care about here. */ createSubInfo(int subId, String displayName)445 private SubscriptionInfo createSubInfo(int subId, String displayName) { 446 return createSubInfo(subId, displayName, "carrierName", "number"); 447 } 448 449 /** Reduce SubscriptionInfo constructor args to the ones we care about here. */ createSubInfo(int subId, String displayName, String carrierName, String number)450 private SubscriptionInfo createSubInfo(int subId, String displayName, String carrierName, 451 String number) { 452 // Hidden constructor so resort to mocking. 453 SubscriptionInfo subscriptionInfo = mock(SubscriptionInfo.class); 454 when(subscriptionInfo.getSubscriptionId()).thenReturn(subId); 455 when(subscriptionInfo.getDisplayName()).thenReturn(displayName); 456 when(subscriptionInfo.getCarrierName()).thenReturn(carrierName); 457 when(subscriptionInfo.getNumber()).thenReturn(number); 458 when(subscriptionInfo.getSimSlotIndex()).thenReturn(111); 459 when(subscriptionInfo.getMcc()).thenReturn(222); 460 when(subscriptionInfo.getMnc()).thenReturn(333); 461 return subscriptionInfo; 462 } 463 setDefaultSubscriptionId(int id)464 private void setDefaultSubscriptionId(int id) { 465 when(SubscriptionManager.getDefaultSubscriptionId()).thenReturn(id); 466 } 467 setDefaultSmsSubscriptionId(int id)468 private void setDefaultSmsSubscriptionId(int id) { 469 when(SubscriptionManager.getDefaultSmsSubscriptionId()).thenReturn(id); 470 } 471 setDefaultVoiceSubscriptionId(int id)472 private void setDefaultVoiceSubscriptionId(int id) { 473 when(SubscriptionManager.getDefaultVoiceSubscriptionId()).thenReturn(id); 474 } 475 setDefaultDataSubscriptionId(int id)476 private void setDefaultDataSubscriptionId(int id) { 477 when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(id); 478 } 479 } 480