1 /* 2 * Copyright (C) 2016 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 android.carrierapi.cts; 18 19 import static android.carrierapi.cts.FcpTemplate.FILE_IDENTIFIER; 20 import static android.carrierapi.cts.IccUtils.bytesToHexString; 21 import static android.carrierapi.cts.IccUtils.hexStringToBytes; 22 import static android.telephony.IccOpenLogicalChannelResponse.INVALID_CHANNEL; 23 import static android.telephony.IccOpenLogicalChannelResponse.STATUS_NO_ERROR; 24 import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER; 25 import static android.telephony.TelephonyManager.DATA_ENABLED_REASON_THERMAL; 26 import static android.telephony.TelephonyManager.DATA_ENABLED_REASON_USER; 27 28 import static com.android.compatibility.common.util.UiccUtil.UiccCertificate.CTS_UICC_2021; 29 30 import static com.google.common.truth.Truth.assertThat; 31 import static com.google.common.truth.Truth.assertWithMessage; 32 33 import static org.junit.Assert.fail; 34 import static org.junit.Assume.assumeTrue; 35 36 import android.content.BroadcastReceiver; 37 import android.content.ContentProviderClient; 38 import android.content.ContentValues; 39 import android.content.Context; 40 import android.content.Intent; 41 import android.content.IntentFilter; 42 import android.database.Cursor; 43 import android.net.Uri; 44 import android.os.AsyncTask; 45 import android.os.Build; 46 import android.os.Handler; 47 import android.os.HandlerThread; 48 import android.os.ParcelUuid; 49 import android.os.PersistableBundle; 50 import android.platform.test.annotations.SystemUserOnly; 51 import android.provider.Telephony; 52 import android.provider.VoicemailContract; 53 import android.telephony.AccessNetworkConstants; 54 import android.telephony.AvailableNetworkInfo; 55 import android.telephony.CarrierConfigManager; 56 import android.telephony.IccOpenLogicalChannelResponse; 57 import android.telephony.PhoneStateListener; 58 import android.telephony.SignalStrengthUpdateRequest; 59 import android.telephony.SignalThresholdInfo; 60 import android.telephony.SubscriptionInfo; 61 import android.telephony.SubscriptionManager; 62 import android.telephony.TelephonyManager; 63 import android.telephony.data.NetworkSlicingConfig; 64 import android.util.Base64; 65 import android.util.Log; 66 67 import androidx.test.runner.AndroidJUnit4; 68 69 import com.android.compatibility.common.util.PollingCheck; 70 import com.android.compatibility.common.util.ShellIdentityUtils; 71 import com.android.compatibility.common.util.UiccUtil; 72 73 import com.google.common.collect.Range; 74 75 import org.junit.After; 76 import org.junit.Before; 77 import org.junit.Test; 78 import org.junit.runner.RunWith; 79 80 import java.util.ArrayList; 81 import java.util.Arrays; 82 import java.util.Collections; 83 import java.util.HashSet; 84 import java.util.List; 85 import java.util.Set; 86 import java.util.concurrent.CompletableFuture; 87 import java.util.concurrent.CountDownLatch; 88 import java.util.concurrent.TimeUnit; 89 import java.util.concurrent.atomic.AtomicReference; 90 import java.util.function.Consumer; 91 import java.util.stream.Collectors; 92 93 import javax.annotation.Nonnull; 94 95 /** 96 * Unit tests for various carrier-related APIs. 97 * 98 * <p>Test using `atest CtsCarrierApiTestCases:CarrierApiTest` or `make cts -j64 && cts-tradefed run 99 * cts -m CtsCarrierApiTestCases --test android.carrierapi.cts.CarrierApiTest` 100 */ 101 // TODO(b/130187425): Split CarrierApiTest apart to have separate test classes for functionality 102 @RunWith(AndroidJUnit4.class) 103 public class CarrierApiTest extends BaseCarrierApiTest { 104 private static final String TAG = "CarrierApiTest"; 105 106 private TelephonyManager mTelephonyManager; 107 private CarrierConfigManager mCarrierConfigManager; 108 private SubscriptionManager mSubscriptionManager; 109 private ContentProviderClient mVoicemailProvider; 110 private ContentProviderClient mStatusProvider; 111 private Uri mVoicemailContentUri; 112 private Uri mStatusContentUri; 113 private String selfPackageName; 114 private HandlerThread mListenerThread; 115 116 // The minimum allocatable logical channel number, per TS 102 221 Section 11.1.17.1 117 private static final int MIN_LOGICAL_CHANNEL = 1; 118 // The maximum allocatable logical channel number in the standard range, per TS 102 221 Section 119 // 11.1.17.1 120 private static final int MAX_LOGICAL_CHANNEL = 3; 121 // Class bytes. The logical channel used should be included for bits b2b1. TS 102 221 Table 11.5 122 private static final int CLA_GET_RESPONSE = 0x00; 123 private static final int CLA_MANAGE_CHANNEL = 0x00; 124 private static final int CLA_READ_BINARY = 0x00; 125 private static final int CLA_SELECT = 0x00; 126 private static final int CLA_STATUS = 0x80; 127 private static final String CLA_STATUS_STRING = "80"; 128 // APDU Instruction Bytes. TS 102 221 Section 10.1.2 129 private static final int COMMAND_GET_RESPONSE = 0xC0; 130 private static final int COMMAND_MANAGE_CHANNEL = 0x70; 131 private static final int COMMAND_READ_BINARY = 0xB0; 132 private static final int COMMAND_SELECT = 0xA4; 133 private static final int COMMAND_STATUS = 0xF2; 134 private static final String COMMAND_STATUS_STRING = "F2"; 135 // Status words. TS 102 221 Section 10.2.1 136 private static final byte[] STATUS_NORMAL = {(byte) 0x90, (byte) 0x00}; 137 private static final String STATUS_NORMAL_STRING = "9000"; 138 private static final String STATUS_BYTES_REMAINING = "61"; 139 private static final String STATUS_WARNING_A = "62"; 140 private static final String STATUS_WARNING_B = "63"; 141 private static final String STATUS_FILE_NOT_FOUND = "6a82"; 142 private static final String STATUS_INCORRECT_PARAMETERS = "6a86"; 143 private static final String STATUS_WRONG_PARAMETERS = "6b00"; 144 private static final Set<String> INVALID_PARAMETERS_STATUSES = 145 new HashSet<>(Arrays.asList(STATUS_INCORRECT_PARAMETERS, STATUS_WRONG_PARAMETERS)); 146 private static final String STATUS_WRONG_CLASS = "6e00"; 147 // File ID for the EF ICCID. TS 102 221 148 private static final String ICCID_FILE_ID = "2FE2"; 149 // File ID for the master file. TS 102 221 150 private static final String MF_FILE_ID = "3F00"; 151 private static final int MF_FILE_ID_HEX = 0x3F00; 152 // File ID for the MF Access Rule Reference. TS 102 221 153 private static final String MF_ARR_FILE_ID = "2F06"; 154 private static final String ALPHA_TAG_A = "tagA"; 155 private static final String ALPHA_TAG_B = "tagB"; 156 private static final String NUMBER_A = "1234567890"; 157 private static final String NUMBER_B = "0987654321"; 158 private static final String TESTING_PLMN = "12345"; 159 160 private static final String EAP_SIM_AKA_RAND = "11111111111111111111111111111111"; 161 162 // Derived from TS 134 108#8.1.2. Based on EAP_SIM_AKA_RAND and assumed K value of 163 // 000102030405060708090A0B0C0D0E0F, per TS 134 108#8.2 164 private static final String EAP_AKA_AUTN = "12351417161900001130131215141716"; 165 166 // EAP-AKA Response Format: [DB][Length][RES][Length][CK][Length][IK] 167 private static final int EAP_AKA_RESPONSE_LENGTH = 1 + 1 + 16 + 1 + 16 + 1 + 16; 168 169 // Derived from TS 134 108#8.1.2. Based on EAP_SIM_AKA_RAND and assumed K value of 170 // 000102030405060708090A0B0C0D0E0F, per TS 134 108#8.2. 171 // Format: [DB][Length][RES][Length][CK][Length][IK] 172 private static final String EXPECTED_EAP_AKA_RESULT = 173 "DB10111013121514171619181B1A1D1C1F1E" 174 + "101013121514171619181B1A1D1C1F1E11" 175 + "1013121514171619181B1A1D1C1F1E1110"; 176 177 // Derived from TS 134 108#8.1.2 and TS 133 102#6.8.1.2. Based on EAP_SIM_AKA_RAND and assumed K 178 // value of 000102030405060708090A0B0C0D0E0F, per TS 134 108#8.2. 179 // Format: [Length][SRES][Length][Kc] 180 private static final String EXPECTED_EAP_SIM_RESULT = "0400000000080000000000000000"; 181 182 private static final int DSDS_PHONE_COUNT = 2; 183 184 @Before setUp()185 public void setUp() throws Exception { 186 Context context = getContext(); 187 mTelephonyManager = context.getSystemService(TelephonyManager.class); 188 mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); 189 mSubscriptionManager = context.getSystemService(SubscriptionManager.class); 190 selfPackageName = context.getPackageName(); 191 mVoicemailContentUri = VoicemailContract.Voicemails.buildSourceUri(selfPackageName); 192 mVoicemailProvider = 193 context.getContentResolver().acquireContentProviderClient(mVoicemailContentUri); 194 mStatusContentUri = VoicemailContract.Status.buildSourceUri(selfPackageName); 195 mStatusProvider = 196 context.getContentResolver().acquireContentProviderClient(mStatusContentUri); 197 mListenerThread = new HandlerThread("CarrierApiTest"); 198 mListenerThread.start(); 199 } 200 201 @After tearDown()202 public void tearDown() throws Exception { 203 if (!werePreconditionsSatisfied()) return; 204 205 mListenerThread.quit(); 206 try { 207 mStatusProvider.delete(mStatusContentUri, null, null); 208 mVoicemailProvider.delete(mVoicemailContentUri, null, null); 209 } catch (Exception e) { 210 Log.w(TAG, "Failed to clean up voicemail tables in tearDown", e); 211 } 212 } 213 214 @Test testSimCardPresent()215 public void testSimCardPresent() { 216 assertWithMessage("This test requires a SIM card") 217 .that(mTelephonyManager.getSimState()) 218 .isNotEqualTo(TelephonyManager.SIM_STATE_ABSENT); 219 } 220 221 @Test testHasCarrierPrivileges()222 public void testHasCarrierPrivileges() { 223 assertWithMessage(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE) 224 .that(mTelephonyManager.hasCarrierPrivileges()) 225 .isTrue(); 226 } 227 assertUpdateAvailableNetworkSuccess(int value)228 private static void assertUpdateAvailableNetworkSuccess(int value) { 229 assertThat(value).isEqualTo(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS); 230 } 231 assertUpdateAvailableNetworkNoOpportunisticSubAvailable(int value)232 private static void assertUpdateAvailableNetworkNoOpportunisticSubAvailable(int value) { 233 assertThat(value) 234 .isEqualTo( 235 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE); 236 } 237 assertSetOpportunisticSubSuccess(int value)238 private static void assertSetOpportunisticSubSuccess(int value) { 239 assertThat(value).isEqualTo(TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS); 240 } 241 getFirstActivateCarrierPrivilegedSubscriptionId()242 private int getFirstActivateCarrierPrivilegedSubscriptionId() { 243 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 244 List<SubscriptionInfo> subscriptionInfos = 245 mSubscriptionManager.getActiveSubscriptionInfoList(); 246 if (subscriptionInfos != null) { 247 for (SubscriptionInfo info : subscriptionInfos) { 248 TelephonyManager telephonyManager = 249 mTelephonyManager.createForSubscriptionId(info.getSubscriptionId()); 250 if (telephonyManager.hasCarrierPrivileges()) { 251 subId = info.getSubscriptionId(); 252 return subId; 253 } 254 } 255 } 256 return subId; 257 } 258 259 @Test testUpdateAvailableNetworksWithCarrierPrivilege()260 public void testUpdateAvailableNetworksWithCarrierPrivilege() { 261 int subIdWithCarrierPrivilege = getFirstActivateCarrierPrivilegedSubscriptionId(); 262 int activeSubscriptionInfoCount = 263 ShellIdentityUtils.invokeMethodWithShellPermissions( 264 mSubscriptionManager, (tm) -> tm.getActiveSubscriptionInfoCount()); 265 if (mTelephonyManager.getPhoneCount() == 1) { 266 return; 267 } 268 269 /* TODO: b/145993690 */ 270 if (mTelephonyManager.getPhoneCount() == 2 && activeSubscriptionInfoCount != 2) { 271 /* This test requires two SIM cards */ 272 return; 273 } 274 if (subIdWithCarrierPrivilege == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 275 /* This test requires SIM with carrier privilege */ 276 return; 277 } 278 279 List<SubscriptionInfo> subscriptionInfoList = 280 mSubscriptionManager.getOpportunisticSubscriptions(); 281 List<String> mccMncs = new ArrayList<String>(); 282 List<Integer> bands = new ArrayList<Integer>(); 283 List<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<AvailableNetworkInfo>(); 284 Consumer<Integer> callbackSuccess = CarrierApiTest::assertUpdateAvailableNetworkSuccess; 285 Consumer<Integer> callbackNoOpportunisticSubAvailable = 286 CarrierApiTest::assertUpdateAvailableNetworkNoOpportunisticSubAvailable; 287 Consumer<Integer> setOpCallbackSuccess = CarrierApiTest::assertSetOpportunisticSubSuccess; 288 if (subscriptionInfoList == null 289 || subscriptionInfoList.size() == 0 290 || !mSubscriptionManager.isActiveSubscriptionId( 291 subscriptionInfoList.get(0).getSubscriptionId())) { 292 try { 293 AvailableNetworkInfo availableNetworkInfo = 294 new AvailableNetworkInfo( 295 subIdWithCarrierPrivilege, 296 AvailableNetworkInfo.PRIORITY_HIGH, 297 mccMncs, 298 bands); 299 availableNetworkInfos.add(availableNetworkInfo); 300 // Call updateAvailableNetworks without opportunistic subscription. 301 // callbackNoOpportunisticSubAvailable is expected to be triggered 302 // and the return value will be checked against 303 // UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE 304 mTelephonyManager.updateAvailableNetworks( 305 availableNetworkInfos, 306 AsyncTask.SERIAL_EXECUTOR, 307 callbackNoOpportunisticSubAvailable); 308 } finally { 309 // clear all the operations at the end of test. 310 availableNetworkInfos.clear(); 311 mTelephonyManager.updateAvailableNetworks( 312 availableNetworkInfos, 313 AsyncTask.SERIAL_EXECUTOR, 314 callbackNoOpportunisticSubAvailable); 315 } 316 } else { 317 // This is case of DSDS phone, one active opportunistic subscription and one 318 // active primary subscription. 319 int resultSubId; 320 try { 321 AvailableNetworkInfo availableNetworkInfo = 322 new AvailableNetworkInfo( 323 subscriptionInfoList.get(0).getSubscriptionId(), 324 AvailableNetworkInfo.PRIORITY_HIGH, 325 mccMncs, 326 bands); 327 availableNetworkInfos.add(availableNetworkInfo); 328 mTelephonyManager.updateAvailableNetworks( 329 availableNetworkInfos, AsyncTask.SERIAL_EXECUTOR, callbackSuccess); 330 // wait for the data change to take effect 331 waitForMs(500); 332 // Call setPreferredData and reconfirm with getPreferred data 333 // that the same is updated. 334 int preferSubId = subscriptionInfoList.get(0).getSubscriptionId(); 335 mTelephonyManager.setPreferredOpportunisticDataSubscription( 336 preferSubId, false, AsyncTask.SERIAL_EXECUTOR, setOpCallbackSuccess); 337 // wait for the data change to take effect 338 waitForMs(500); 339 resultSubId = mTelephonyManager.getPreferredOpportunisticDataSubscription(); 340 assertThat(resultSubId).isEqualTo(preferSubId); 341 } finally { 342 // clear all the operations at the end of test. 343 availableNetworkInfos.clear(); 344 mTelephonyManager.updateAvailableNetworks( 345 availableNetworkInfos, AsyncTask.SERIAL_EXECUTOR, callbackSuccess); 346 waitForMs(500); 347 mTelephonyManager.setPreferredOpportunisticDataSubscription( 348 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 349 false, 350 AsyncTask.SERIAL_EXECUTOR, 351 callbackSuccess); 352 waitForMs(500); 353 resultSubId = mTelephonyManager.getPreferredOpportunisticDataSubscription(); 354 assertThat(resultSubId).isEqualTo(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 355 } 356 } 357 } 358 waitForMs(long ms)359 public static void waitForMs(long ms) { 360 try { 361 Thread.sleep(ms); 362 } catch (InterruptedException e) { 363 Log.d(TAG, "InterruptedException while waiting: " + e); 364 } 365 } 366 367 @Test testGetIccAuthentication()368 public void testGetIccAuthentication() { 369 // EAP-SIM rand is 16 bytes. 370 String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM="; 371 String base64Challenge2 = "EMNxjsFrPCpm+KcgCmQGnwQ="; 372 373 try { 374 assertWithMessage("getIccAuthentication should return null for empty data.") 375 .that( 376 mTelephonyManager.getIccAuthentication( 377 TelephonyManager.APPTYPE_USIM, 378 TelephonyManager.AUTHTYPE_EAP_AKA, 379 "")) 380 .isNull(); 381 String response = 382 mTelephonyManager.getIccAuthentication( 383 TelephonyManager.APPTYPE_USIM, 384 TelephonyManager.AUTHTYPE_EAP_SIM, 385 base64Challenge); 386 assertWithMessage("Response to EAP-SIM Challenge must not be Null.") 387 .that(response) 388 .isNotNull(); 389 // response is base64 encoded. After decoding, the value should be: 390 // 1 length byte + SRES(4 bytes) + 1 length byte + Kc(8 bytes) 391 byte[] result = android.util.Base64.decode(response, android.util.Base64.DEFAULT); 392 assertThat(result).hasLength(14); 393 String response2 = 394 mTelephonyManager.getIccAuthentication( 395 TelephonyManager.APPTYPE_USIM, 396 TelephonyManager.AUTHTYPE_EAP_SIM, 397 base64Challenge2); 398 assertWithMessage("Two responses must be different") 399 .that(response) 400 .isNotEqualTo(response2); 401 } catch (SecurityException e) { 402 fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE); 403 } 404 } 405 406 @Test 407 @SystemUserOnly(reason = "b/177921545, broadcast sent only to primary user") testSendDialerSpecialCode()408 public void testSendDialerSpecialCode() { 409 IntentReceiver intentReceiver = new IntentReceiver(); 410 final IntentFilter intentFilter = new IntentFilter(); 411 intentFilter.addAction(Telephony.Sms.Intents.SECRET_CODE_ACTION); 412 intentFilter.addDataScheme("android_secret_code"); 413 414 Context context = getContext(); 415 context.registerReceiver(intentReceiver, intentFilter); 416 try { 417 mTelephonyManager.sendDialerSpecialCode("4636"); 418 assertWithMessage( 419 "Did not receive expected Intent: " 420 + Telephony.Sms.Intents.SECRET_CODE_ACTION) 421 .that(intentReceiver.waitForReceive()) 422 .isTrue(); 423 } catch (SecurityException e) { 424 fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE); 425 } catch (InterruptedException e) { 426 Log.d(TAG, "Broadcast receiver wait was interrupted."); 427 } finally { 428 context.unregisterReceiver(intentReceiver); 429 } 430 } 431 432 @Test testSubscriptionInfoListing()433 public void testSubscriptionInfoListing() { 434 try { 435 assertThat(mSubscriptionManager.getActiveSubscriptionInfoCount()).isGreaterThan(0); 436 List<SubscriptionInfo> subInfoList = 437 mSubscriptionManager.getActiveSubscriptionInfoList(); 438 assertWithMessage("getActiveSubscriptionInfoList() returned null") 439 .that(subInfoList) 440 .isNotNull(); 441 assertWithMessage("getActiveSubscriptionInfoList() returned an empty list") 442 .that(subInfoList) 443 .isNotEmpty(); 444 for (SubscriptionInfo info : subInfoList) { 445 TelephonyManager tm = 446 mTelephonyManager.createForSubscriptionId(info.getSubscriptionId()); 447 assertWithMessage( 448 "getActiveSubscriptionInfoList() returned an inaccessible" 449 + " subscription") 450 .that(tm.hasCarrierPrivileges()) 451 .isTrue(); 452 453 // Check other APIs to make sure they are accessible and return consistent info. 454 SubscriptionInfo infoForSlot = 455 mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex( 456 info.getSimSlotIndex()); 457 assertWithMessage("getActiveSubscriptionInfoForSimSlotIndex() returned null") 458 .that(infoForSlot) 459 .isNotNull(); 460 assertWithMessage( 461 "getActiveSubscriptionInfoForSimSlotIndex() returned inconsistent" 462 + " info") 463 .that(infoForSlot.getSubscriptionId()) 464 .isEqualTo(info.getSubscriptionId()); 465 466 SubscriptionInfo infoForSubId = 467 mSubscriptionManager.getActiveSubscriptionInfo(info.getSubscriptionId()); 468 assertWithMessage("getActiveSubscriptionInfo() returned null") 469 .that(infoForSubId) 470 .isNotNull(); 471 assertWithMessage("getActiveSubscriptionInfo() returned inconsistent info") 472 .that(infoForSubId.getSubscriptionId()) 473 .isEqualTo(info.getSubscriptionId()); 474 } 475 } catch (SecurityException e) { 476 fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE); 477 } 478 } 479 480 @Test testCarrierConfigIsAccessible()481 public void testCarrierConfigIsAccessible() { 482 try { 483 PersistableBundle bundle = mCarrierConfigManager.getConfig(); 484 assertWithMessage("CarrierConfigManager#getConfig() returned null") 485 .that(bundle) 486 .isNotNull(); 487 assertWithMessage("CarrierConfigManager#getConfig() returned empty bundle") 488 .that(bundle.isEmpty()) 489 .isFalse(); 490 491 int subId = SubscriptionManager.getDefaultSubscriptionId(); 492 bundle = mCarrierConfigManager.getConfigForSubId(subId); 493 assertWithMessage("CarrierConfigManager#getConfigForSubId() returned null") 494 .that(bundle) 495 .isNotNull(); 496 assertWithMessage("CarrierConfigManager#getConfigForSubId() returned empty bundle") 497 .that(bundle.isEmpty()) 498 .isFalse(); 499 } catch (SecurityException e) { 500 fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE); 501 } 502 } 503 504 @Test testTelephonyApisAreAccessible()505 public void testTelephonyApisAreAccessible() { 506 // The following methods may return any value depending on the state of the device. Simply 507 // call them to make sure they do not throw any exceptions. Methods that return a device 508 // identifier will be accessible to apps with carrier privileges in Q, but this may change 509 // in a future release. 510 try { 511 mTelephonyManager.getDeviceId(); 512 mTelephonyManager.getImei(); 513 mTelephonyManager.getMeid(); 514 mTelephonyManager.getDeviceSoftwareVersion(); 515 mTelephonyManager.getNai(); 516 mTelephonyManager.getDataNetworkType(); 517 mTelephonyManager.getVoiceNetworkType(); 518 mTelephonyManager.getSimSerialNumber(); 519 mTelephonyManager.getSubscriberId(); 520 mTelephonyManager.getGroupIdLevel1(); 521 mTelephonyManager.getLine1Number(); 522 mTelephonyManager.getVoiceMailNumber(); 523 mTelephonyManager.getVisualVoicemailPackageName(); 524 mTelephonyManager.getVoiceMailAlphaTag(); 525 mTelephonyManager.getForbiddenPlmns(); 526 mTelephonyManager.getServiceState(); 527 mTelephonyManager.getManualNetworkSelectionPlmn(); 528 mTelephonyManager.setForbiddenPlmns(new ArrayList<String>()); 529 // TODO(b/235490259): test all slots once TM#isModemEnabledForSlot allows 530 mTelephonyManager.isModemEnabledForSlot( 531 SubscriptionManager.getSlotIndex(mTelephonyManager.getSubscriptionId())); 532 } catch (SecurityException e) { 533 fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE); 534 } 535 } 536 537 @Test testVoicemailTableIsAccessible()538 public void testVoicemailTableIsAccessible() throws Exception { 539 ContentValues value = new ContentValues(); 540 value.put(VoicemailContract.Voicemails.NUMBER, "0123456789"); 541 value.put(VoicemailContract.Voicemails.SOURCE_PACKAGE, selfPackageName); 542 try { 543 Uri uri = mVoicemailProvider.insert(mVoicemailContentUri, value); 544 assertThat(uri).isNotNull(); 545 Cursor cursor = 546 mVoicemailProvider.query( 547 uri, 548 new String[] { 549 VoicemailContract.Voicemails.NUMBER, 550 VoicemailContract.Voicemails.SOURCE_PACKAGE 551 }, 552 null, 553 null, 554 null); 555 assertThat(cursor).isNotNull(); 556 assertThat(cursor.moveToFirst()).isTrue(); 557 assertThat(cursor.getString(0)).isEqualTo("0123456789"); 558 assertThat(cursor.getString(1)).isEqualTo(selfPackageName); 559 assertThat(cursor.moveToNext()).isFalse(); 560 } catch (SecurityException e) { 561 fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE); 562 } 563 } 564 565 @Test testVoicemailStatusTableIsAccessible()566 public void testVoicemailStatusTableIsAccessible() throws Exception { 567 ContentValues value = new ContentValues(); 568 value.put( 569 VoicemailContract.Status.CONFIGURATION_STATE, 570 VoicemailContract.Status.CONFIGURATION_STATE_OK); 571 value.put(VoicemailContract.Status.SOURCE_PACKAGE, selfPackageName); 572 try { 573 Uri uri = mStatusProvider.insert(mStatusContentUri, value); 574 assertThat(uri).isNotNull(); 575 Cursor cursor = 576 mVoicemailProvider.query( 577 uri, 578 new String[] { 579 VoicemailContract.Status.CONFIGURATION_STATE, 580 VoicemailContract.Status.SOURCE_PACKAGE 581 }, 582 null, 583 null, 584 null); 585 assertThat(cursor).isNotNull(); 586 assertThat(cursor.moveToFirst()).isTrue(); 587 assertThat(cursor.getInt(0)).isEqualTo(VoicemailContract.Status.CONFIGURATION_STATE_OK); 588 assertThat(cursor.getString(1)).isEqualTo(selfPackageName); 589 assertThat(cursor.moveToNext()).isFalse(); 590 } catch (SecurityException e) { 591 fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE); 592 } 593 } 594 595 static final int READ_PHONE_STATE_LISTENERS = 596 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR 597 | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR 598 | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST; 599 600 static final int READ_PRECISE_PHONE_STATE_LISTENERS = 601 PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE 602 | PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES 603 | PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES 604 | PhoneStateListener.LISTEN_REGISTRATION_FAILURE 605 | PhoneStateListener.LISTEN_BARRING_INFO; 606 607 static final int CARRIER_PRIVILEGE_LISTENERS = 608 READ_PHONE_STATE_LISTENERS | READ_PRECISE_PHONE_STATE_LISTENERS; 609 610 @Test testGetManualNetworkSelectionPlmnPersisted()611 public void testGetManualNetworkSelectionPlmnPersisted() throws Exception { 612 if (mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_GSM) return; 613 614 try { 615 mTelephonyManager.setNetworkSelectionModeManual( 616 TESTING_PLMN /* operatorNumeric */, true /* persistSelection */); 617 String plmn = mTelephonyManager.getManualNetworkSelectionPlmn(); 618 assertThat(plmn).isEqualTo(TESTING_PLMN); 619 } finally { 620 mTelephonyManager.setNetworkSelectionModeAutomatic(); 621 } 622 } 623 624 @Test testPhoneStateListener()625 public void testPhoneStateListener() throws Exception { 626 PhoneStateListener psl = new PhoneStateListener((Runnable r) -> {}); 627 try { 628 mTelephonyManager.listen(psl, CARRIER_PRIVILEGE_LISTENERS); 629 } finally { 630 mTelephonyManager.listen(psl, PhoneStateListener.LISTEN_NONE); 631 } 632 } 633 634 @Test testIsManualNetworkSelectionAllowed()635 public void testIsManualNetworkSelectionAllowed() throws Exception { 636 if (mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_GSM) return; 637 638 try { 639 assertThat(mTelephonyManager.isManualNetworkSelectionAllowed()).isTrue(); 640 } catch (SecurityException e) { 641 fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE); 642 } 643 } 644 645 @Test testGetNetworkSelectionMode()646 public void testGetNetworkSelectionMode() throws Exception { 647 try { 648 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( 649 mTelephonyManager, (tm) -> tm.setNetworkSelectionModeAutomatic()); 650 int networkMode = mTelephonyManager.getNetworkSelectionMode(); 651 assertThat(networkMode).isEqualTo(TelephonyManager.NETWORK_SELECTION_MODE_AUTO); 652 } catch (SecurityException e) { 653 fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE); 654 } 655 } 656 657 @Test testSubscriptionInfoChangeListener()658 public void testSubscriptionInfoChangeListener() throws Exception { 659 final AtomicReference<SecurityException> error = new AtomicReference<>(); 660 final CountDownLatch latch = new CountDownLatch(1); 661 new Handler(mListenerThread.getLooper()) 662 .post( 663 () -> { 664 SubscriptionManager.OnSubscriptionsChangedListener listener = 665 new SubscriptionManager.OnSubscriptionsChangedListener(); 666 try { 667 mSubscriptionManager.addOnSubscriptionsChangedListener(listener); 668 } catch (SecurityException e) { 669 error.set(e); 670 } finally { 671 mSubscriptionManager.removeOnSubscriptionsChangedListener(listener); 672 latch.countDown(); 673 } 674 }); 675 assertWithMessage("Test timed out").that(latch.await(30L, TimeUnit.SECONDS)).isTrue(); 676 if (error.get() != null) { 677 fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE); 678 } 679 } 680 681 /** 682 * Test that it's possible to open logical channels to the ICC. This mirrors the Manage Channel 683 * command described in TS 102 221 Section 11.1.17. 684 */ 685 @Test testIccOpenLogicalChannel()686 public void testIccOpenLogicalChannel() { 687 // The AID here doesn't matter - we just need to open a valid connection. In this case, the 688 // specified AID ("") opens a channel and selects the MF. 689 IccOpenLogicalChannelResponse response = mTelephonyManager.iccOpenLogicalChannel(""); 690 final int logicalChannel = response.getChannel(); 691 try { 692 verifyValidIccOpenLogicalChannelResponse(response); 693 } finally { 694 mTelephonyManager.iccCloseLogicalChannel(logicalChannel); 695 } 696 } 697 698 @Test testIccOpenLogicalChannelWithValidP2()699 public void testIccOpenLogicalChannelWithValidP2() { 700 // {@link TelephonyManager#iccOpenLogicalChannel} sends a Manage Channel (open) APDU 701 // followed by a Select APDU with the given AID and p2 values. See Open Mobile API 702 // Specification v3.2 Section 6.2.7.h and TS 102 221 for details. 703 int p2 = 0x0C; // '0C' for no data returned (TS 102 221 Section 11.1.1.2) 704 IccOpenLogicalChannelResponse response = mTelephonyManager.iccOpenLogicalChannel("", p2); 705 final int logicalChannel = response.getChannel(); 706 try { 707 verifyValidIccOpenLogicalChannelResponse(response); 708 } finally { 709 mTelephonyManager.iccCloseLogicalChannel(logicalChannel); 710 } 711 } 712 713 @Test testIccOpenLogicalChannelWithInvalidP2()714 public void testIccOpenLogicalChannelWithInvalidP2() { 715 // Valid p2 values are defined in TS 102 221 Table 11.2. Per Table 11.2, 0xF0 should be 716 // invalid. Any p2 values that produce non '9000'/'62xx'/'63xx' status words are treated as 717 // an error and the channel is not opened. Due to compatibility issues with older devices, 718 // this check is only enabled for new devices launching on Q+. 719 if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.Q) { 720 int p2 = 0xF0; 721 IccOpenLogicalChannelResponse response = 722 mTelephonyManager.iccOpenLogicalChannel("", p2); 723 final int logicalChannel = response.getChannel(); 724 assertThat(logicalChannel).isEqualTo(INVALID_CHANNEL); 725 assertThat(response.getStatus()).isNotEqualTo(STATUS_NO_ERROR); 726 } 727 } 728 729 /** 730 * Test that it's possible to close logical channels to the ICC. This follows the Manage Channel 731 * command described in TS 102 221 Section 11.1.17. 732 */ 733 @Test testIccCloseLogicalChannel()734 public void testIccCloseLogicalChannel() { 735 // The directory here doesn't matter - we just need to open a valid connection that can 736 // later be closed. In this case, the specified AID ("") opens a channel and selects the MF. 737 IccOpenLogicalChannelResponse response = mTelephonyManager.iccOpenLogicalChannel(""); 738 739 // Check that the select command succeeded. This ensures that the logical channel is indeed 740 // open. 741 assertThat(response.getSelectResponse()).isEqualTo(STATUS_NORMAL); 742 assertThat(mTelephonyManager.iccCloseLogicalChannel(response.getChannel())).isTrue(); 743 744 // Close opened channel twice. 745 try { 746 boolean result = mTelephonyManager.iccCloseLogicalChannel(response.getChannel()); 747 assertThat(result).isFalse(); 748 } catch (IllegalArgumentException ex) { 749 //IllegalArgumentException is expected sometimes because of different behaviour of modem 750 } 751 752 // Channel 0 is guaranteed to be always available and cannot be closed, per TS 102 221 753 // Section 11.1.17 754 try { 755 mTelephonyManager.iccCloseLogicalChannel(0); 756 fail("Expected IllegalArgumentException"); 757 } catch (IllegalArgumentException ex) { 758 // IllegalArgumentException is expected 759 } 760 } 761 762 /** 763 * This test ensures that valid APDU instructions can be sent and processed by the ICC. To do 764 * so, APDUs are sent to: - get the status of the MF - select the Access Rule Reference (ARR) 765 * for the MF - get the FCP template response for the select 766 */ 767 @Test testIccTransmitApduLogicalChannel()768 public void testIccTransmitApduLogicalChannel() { 769 // An open LC is required for transmitting APDU commands. This opens an LC to the MF. 770 IccOpenLogicalChannelResponse iccOpenLogicalChannelResponse = 771 mTelephonyManager.iccOpenLogicalChannel(""); 772 773 // Get the status of the current directory. This should match the MF. TS 102 221 Section 774 // 11.1.2 775 final int logicalChannel = iccOpenLogicalChannelResponse.getChannel(); 776 777 try { 778 int cla = CLA_STATUS; 779 int p1 = 0; // no indication of application status 780 int p2 = 0; // same response parameters as the SELECT in the iccOpenLogicalChannel() 781 // above 782 int p3 = 0; // length of 'data' payload 783 String data = ""; 784 String response = 785 mTelephonyManager.iccTransmitApduLogicalChannel( 786 logicalChannel, cla, COMMAND_STATUS, p1, p2, p3, data); 787 FcpTemplate fcpTemplate = FcpTemplate.parseFcpTemplate(response); 788 // Check that the FCP Template's file ID matches the MF 789 assertThat(containsFileId(fcpTemplate, MF_FILE_ID)).isTrue(); 790 assertThat(fcpTemplate.getStatus()).isEqualTo(STATUS_NORMAL_STRING); 791 792 // Select the Access Rule Reference for the MF. Similar to the MF, this will exist 793 // across all SIM cards. TS 102 221 Section 11.1.1 794 cla = CLA_SELECT; 795 p1 = 0; // select EF by FID 796 p2 = 0x04; // requesting FCP template 797 p3 = 2; // data (FID to be selected) is 2 bytes 798 data = MF_ARR_FILE_ID; 799 response = 800 mTelephonyManager.iccTransmitApduLogicalChannel( 801 logicalChannel, cla, COMMAND_SELECT, p1, p2, p3, data); 802 803 // Devices launching with Q or later must immediately return the FCP template from the 804 // previous SELECT command. Some devices that launched before Q return TPDUs (instead of 805 // APDUs) - these devices must issue a subsequent GET RESPONSE command to get the FCP 806 // template. 807 if (Build.VERSION.DEVICE_INITIAL_SDK_INT < Build.VERSION_CODES.Q) { 808 // Conditionally need to send GET RESPONSE apdu based on response from 809 // TelephonyManager 810 if (response.startsWith(STATUS_BYTES_REMAINING)) { 811 // Read the FCP template from the ICC. TS 102 221 Section 12.1.1 812 cla = CLA_GET_RESPONSE; 813 p1 = 0; 814 p2 = 0; 815 p3 = 0; 816 data = ""; 817 response = 818 mTelephonyManager.iccTransmitApduLogicalChannel( 819 logicalChannel, cla, COMMAND_GET_RESPONSE, p1, p2, p3, data); 820 } 821 } 822 823 fcpTemplate = FcpTemplate.parseFcpTemplate(response); 824 // Check that the FCP Template's file ID matches the selected ARR 825 assertThat(containsFileId(fcpTemplate, MF_ARR_FILE_ID)).isTrue(); 826 assertThat(fcpTemplate.getStatus()).isEqualTo(STATUS_NORMAL_STRING); 827 } finally { 828 mTelephonyManager.iccCloseLogicalChannel(logicalChannel); 829 } 830 } 831 832 /** 833 * Tests several invalid APDU instructions over a logical channel and makes sure appropriate 834 * errors are returned from the UICC. 835 */ 836 @Test testIccTransmitApduLogicalChannelWithInvalidInputs()837 public void testIccTransmitApduLogicalChannelWithInvalidInputs() { 838 // An open LC is required for transmitting apdu commands. This opens an LC to the MF. 839 IccOpenLogicalChannelResponse iccOpenLogicalChannelResponse = 840 mTelephonyManager.iccOpenLogicalChannel(""); 841 final int logicalChannel = iccOpenLogicalChannelResponse.getChannel(); 842 843 try { 844 // Make some invalid APDU commands and make sure they fail as expected. 845 // Use an invalid p1 value for Status apdu 846 int cla = CLA_STATUS | logicalChannel; 847 int p1 = 0xFF; // only '00', '01', and '02' are allowed 848 int p2 = 0; // same response parameters as the SELECT in the iccOpenLogicalChannel() 849 // above 850 int p3 = 0; // length of 'data' payload 851 String data = ""; 852 String response = 853 mTelephonyManager.iccTransmitApduLogicalChannel( 854 logicalChannel, cla, COMMAND_STATUS, p1, p2, p3, data); 855 assertThat(INVALID_PARAMETERS_STATUSES.contains(response)).isTrue(); 856 857 // Select a file that doesn't exist 858 cla = CLA_SELECT; 859 p1 = 0x00; // select by file ID 860 p2 = 0x0C; // no data returned 861 p3 = 0x02; // length of 'data' payload 862 data = "FFFF"; // invalid file ID 863 response = 864 mTelephonyManager.iccTransmitApduLogicalChannel( 865 logicalChannel, cla, COMMAND_SELECT, p1, p2, p3, data); 866 assertThat(response).isEqualTo(STATUS_FILE_NOT_FOUND); 867 868 // Manage channel with incorrect p1 parameter 869 cla = CLA_MANAGE_CHANNEL | logicalChannel; 870 p1 = 0x83; // Only '80' or '00' allowed for Manage Channel p1 871 p2 = logicalChannel; // channel to be closed 872 p3 = 0; // length of 'data' payload 873 data = ""; 874 response = 875 mTelephonyManager.iccTransmitApduLogicalChannel( 876 logicalChannel, cla, COMMAND_MANAGE_CHANNEL, p1, p2, p3, data); 877 assertThat(isErrorResponse(response)).isTrue(); 878 879 // Use an incorrect class byte for Status apdu 880 cla = 0xFF; 881 p1 = 0; // no indication of application status 882 p2 = 0; // same response parameters as the SELECT in the iccOpenLogicalChannel() above 883 p3 = 0; // length of 'data' payload 884 data = ""; 885 response = 886 mTelephonyManager.iccTransmitApduLogicalChannel( 887 logicalChannel, cla, COMMAND_STATUS, p1, p2, p3, data); 888 assertThat(response).isEqualTo(STATUS_WRONG_CLASS); 889 890 // Provide a data field that is longer than described for Select apdu 891 cla = CLA_SELECT | logicalChannel; 892 p1 = 0; // select by file ID 893 p2 = 0x0C; // no data returned 894 p3 = 0x04; // data passed is actually 2 bytes long 895 data = "3F00"; // valid ID 896 response = 897 mTelephonyManager.iccTransmitApduLogicalChannel( 898 logicalChannel, cla, COMMAND_SELECT, p1, p2, p3, data); 899 assertThat(isErrorResponse(response)).isTrue(); 900 901 // Use an invalid instruction 902 cla = 0; 903 p1 = 0; 904 p2 = 0; 905 p3 = 0; 906 data = ""; 907 int invalidInstruction = 0xFF; // see TS 102 221 Table 10.5 for valid instructions 908 response = 909 mTelephonyManager.iccTransmitApduLogicalChannel( 910 logicalChannel, cla, invalidInstruction, p1, p2, p3, data); 911 assertThat(isErrorResponse(response)).isTrue(); 912 } finally { 913 mTelephonyManager.iccCloseLogicalChannel(logicalChannel); 914 } 915 } 916 917 /** 918 * This test ensures that files can be read off the UICC. This helps to test the SIM booting 919 * process, as it process involves several file-reads. The ICCID is one of the first files read. 920 */ 921 @Test testApduFileRead()922 public void testApduFileRead() { 923 // Open a logical channel and select the MF. 924 IccOpenLogicalChannelResponse iccOpenLogicalChannel = 925 mTelephonyManager.iccOpenLogicalChannel(""); 926 final int logicalChannel = iccOpenLogicalChannel.getChannel(); 927 928 try { 929 // Select the ICCID. TS 102 221 Section 13.2 930 int p1 = 0; // select by file ID 931 int p2 = 0x0C; // no data returned 932 int p3 = 2; // length of 'data' payload 933 String response = 934 mTelephonyManager.iccTransmitApduLogicalChannel( 935 logicalChannel, CLA_SELECT, COMMAND_SELECT, p1, p2, p3, ICCID_FILE_ID); 936 assertThat(response).isEqualTo(STATUS_NORMAL_STRING); 937 938 // Read the contents of the ICCID. 939 p1 = 0; // 0-byte offset 940 p2 = 0; // 0-byte offset 941 p3 = 0; // length of 'data' payload 942 response = 943 mTelephonyManager.iccTransmitApduLogicalChannel( 944 logicalChannel, CLA_READ_BINARY, COMMAND_READ_BINARY, p1, p2, p3, ""); 945 assertThat(response).endsWith(STATUS_NORMAL_STRING); 946 } finally { 947 mTelephonyManager.iccCloseLogicalChannel(logicalChannel); 948 } 949 } 950 951 /** This test sends several valid APDU commands over the basic channel (channel 0). */ 952 @Test testIccTransmitApduBasicChannel()953 public void testIccTransmitApduBasicChannel() { 954 // select the MF 955 int cla = CLA_SELECT; 956 int p1 = 0; // select EF by FID 957 int p2 = 0x0C; // requesting FCP template 958 int p3 = 2; // length of 'data' payload 959 String data = MF_FILE_ID; 960 String response = 961 mTelephonyManager.iccTransmitApduBasicChannel( 962 cla, COMMAND_SELECT, p1, p2, p3, data); 963 assertThat(response).isEqualTo(STATUS_NORMAL_STRING); 964 965 // get the Status of the current file/directory 966 cla = CLA_STATUS; 967 p1 = 0; // no indication of application status 968 p2 = 0; // same response parameters as the SELECT in the iccOpenLogicalChannel() above 969 p3 = 0; // length of 'data' payload 970 data = ""; 971 response = 972 mTelephonyManager.iccTransmitApduBasicChannel( 973 cla, COMMAND_STATUS, p1, p2, p3, data); 974 FcpTemplate fcpTemplate = FcpTemplate.parseFcpTemplate(response); 975 assertThat(containsFileId(fcpTemplate, MF_FILE_ID)).isTrue(); 976 977 // Manually open a logical channel 978 cla = CLA_MANAGE_CHANNEL; 979 p1 = 0; // open a logical channel 980 p2 = 0; // '00' for open command 981 p3 = 0; // length of data payload 982 data = ""; 983 response = 984 mTelephonyManager.iccTransmitApduBasicChannel( 985 cla, COMMAND_MANAGE_CHANNEL, p1, p2, p3, data); 986 // response is in the format | 1 byte: channel number | 2 bytes: status word | 987 String responseStatus = response.substring(2); 988 assertThat(responseStatus).isEqualTo(STATUS_NORMAL_STRING); 989 990 // Close the open channel 991 byte[] responseBytes = hexStringToBytes(response); 992 int channel = responseBytes[0]; 993 cla = CLA_MANAGE_CHANNEL; 994 p1 = 0x80; // close a logical channel 995 p2 = channel; // the channel to be closed 996 p3 = 0; // length of data payload 997 data = ""; 998 response = 999 mTelephonyManager.iccTransmitApduBasicChannel( 1000 cla, COMMAND_MANAGE_CHANNEL, p1, p2, p3, data); 1001 assertThat(response).isEqualTo(STATUS_NORMAL_STRING); 1002 } 1003 1004 /** 1005 * This test verifies that {@link TelephonyManager#setLine1NumberForDisplay(String, String)} 1006 * correctly sets the Line 1 alpha tag and number when called, and the phone number 1007 * of {@link SubscriptionManager#PHONE_NUMBER_SOURCE_CARRIER}. 1008 */ 1009 @Test testLine1NumberForDisplay()1010 public void testLine1NumberForDisplay() { 1011 int subId = SubscriptionManager.getDefaultSubscriptionId(); 1012 // Cache original alpha tag and number values. 1013 String originalAlphaTag = mTelephonyManager.getLine1AlphaTag(); 1014 String originalNumber = mTelephonyManager.getLine1Number(); 1015 1016 try { 1017 // clear any potentially overridden values and cache defaults 1018 mTelephonyManager.setLine1NumberForDisplay(null, null); 1019 String defaultAlphaTag = mTelephonyManager.getLine1AlphaTag(); 1020 String defaultNumber = mTelephonyManager.getLine1Number(); 1021 1022 assertThat(mTelephonyManager.setLine1NumberForDisplay(ALPHA_TAG_A, NUMBER_A)).isTrue(); 1023 assertThat(mTelephonyManager.getLine1AlphaTag()).isEqualTo(ALPHA_TAG_A); 1024 assertThat(mTelephonyManager.getLine1Number()).isEqualTo(NUMBER_A); 1025 assertThat(mSubscriptionManager.getPhoneNumber(subId, PHONE_NUMBER_SOURCE_CARRIER)) 1026 .isEqualTo(NUMBER_A); 1027 1028 assertThat(mTelephonyManager.setLine1NumberForDisplay(ALPHA_TAG_B, NUMBER_B)).isTrue(); 1029 assertThat(mTelephonyManager.getLine1AlphaTag()).isEqualTo(ALPHA_TAG_B); 1030 assertThat(mTelephonyManager.getLine1Number()).isEqualTo(NUMBER_B); 1031 assertThat(mSubscriptionManager.getPhoneNumber(subId, PHONE_NUMBER_SOURCE_CARRIER)) 1032 .isEqualTo(NUMBER_B); 1033 1034 // null is used to clear the Line 1 alpha tag and number values. 1035 assertThat(mTelephonyManager.setLine1NumberForDisplay(null, null)).isTrue(); 1036 assertThat(mTelephonyManager.getLine1AlphaTag()).isEqualTo(defaultAlphaTag); 1037 assertThat(mTelephonyManager.getLine1Number()).isEqualTo(defaultNumber); 1038 assertThat(mSubscriptionManager.getPhoneNumber(subId, PHONE_NUMBER_SOURCE_CARRIER)) 1039 .isEqualTo(""); 1040 } finally { 1041 // Reset original alpha tag and number values. 1042 mTelephonyManager.setLine1NumberForDisplay(originalAlphaTag, originalNumber); 1043 } 1044 } 1045 1046 /** 1047 * This test verifies that {@link TelephonyManager#setVoiceMailNumber(String, String)} correctly 1048 * sets the VoiceMail alpha tag and number when called. 1049 */ 1050 @Test testVoiceMailNumber()1051 public void testVoiceMailNumber() { 1052 // Cache original alpha tag and number values. 1053 String originalAlphaTag = mTelephonyManager.getVoiceMailAlphaTag(); 1054 String originalNumber = mTelephonyManager.getVoiceMailNumber(); 1055 1056 try { 1057 assertThat(mTelephonyManager.setVoiceMailNumber(ALPHA_TAG_A, NUMBER_A)).isTrue(); 1058 assertThat(mTelephonyManager.getVoiceMailAlphaTag()).isEqualTo(ALPHA_TAG_A); 1059 assertThat(mTelephonyManager.getVoiceMailNumber()).isEqualTo(NUMBER_A); 1060 1061 assertThat(mTelephonyManager.setVoiceMailNumber(ALPHA_TAG_B, NUMBER_B)).isTrue(); 1062 assertThat(mTelephonyManager.getVoiceMailAlphaTag()).isEqualTo(ALPHA_TAG_B); 1063 assertThat(mTelephonyManager.getVoiceMailNumber()).isEqualTo(NUMBER_B); 1064 } finally { 1065 // Reset original alpha tag and number values. 1066 mTelephonyManager.setVoiceMailNumber(originalAlphaTag, originalNumber); 1067 } 1068 } 1069 1070 /** 1071 * This test verifies that {@link SubscriptionManager#createSubscriptionGroup(List)} correctly 1072 * create a group with the given subscription id. 1073 * 1074 * <p>This also verifies that {@link SubscriptionManager#removeSubscriptionsFromGroup(List, 1075 * ParcelUuid)} correctly remove the given subscription group. 1076 */ 1077 @Test testCreateAndRemoveSubscriptionGroup()1078 public void testCreateAndRemoveSubscriptionGroup() { 1079 // Set subscription group with current sub Id. 1080 int subId = SubscriptionManager.getDefaultSubscriptionId(); 1081 List<Integer> subGroup = Arrays.asList(subId); 1082 ParcelUuid uuid = mSubscriptionManager.createSubscriptionGroup(subGroup); 1083 1084 // Getting subscriptions in group. 1085 List<SubscriptionInfo> infoList = mSubscriptionManager.getSubscriptionsInGroup(uuid); 1086 1087 try { 1088 assertThat(infoList).hasSize(1); 1089 assertThat(infoList.get(0).getGroupUuid()).isEqualTo(uuid); 1090 assertThat(infoList.get(0).getSubscriptionId()).isEqualTo(subId); 1091 } finally { 1092 // Verify that the given subGroup has been removed. 1093 mSubscriptionManager.removeSubscriptionsFromGroup(subGroup, uuid); 1094 infoList = mSubscriptionManager.getSubscriptionsInGroup(uuid); 1095 assertThat(infoList).isEmpty(); 1096 } 1097 } 1098 1099 @Test testAddSubscriptionToExistingGroupForMultipleSims()1100 public void testAddSubscriptionToExistingGroupForMultipleSims() { 1101 if (mTelephonyManager.getPhoneCount() < DSDS_PHONE_COUNT 1102 || mSubscriptionManager.getActiveSubscriptionInfoList().size() < DSDS_PHONE_COUNT) { 1103 // This test requires at least two active subscriptions. 1104 return; 1105 } 1106 1107 // Set subscription group with current sub Id. 1108 int subId = SubscriptionManager.getDefaultSubscriptionId(); 1109 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return; 1110 ParcelUuid uuid = ShellIdentityUtils.invokeMethodWithShellPermissions(mSubscriptionManager, 1111 (sm) -> sm.createSubscriptionGroup(Arrays.asList(subId))); 1112 1113 try { 1114 // Get all active subscriptions. 1115 List<SubscriptionInfo> activeSubInfos = 1116 ShellIdentityUtils.invokeMethodWithShellPermissions(mSubscriptionManager, 1117 (sm) -> sm.getActiveSubscriptionInfoList()); 1118 1119 List<Integer> activeSubGroup = getSubscriptionIdList(activeSubInfos); 1120 activeSubGroup.removeIf(id -> id == subId); 1121 1122 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSubscriptionManager, 1123 (sm) -> sm.addSubscriptionsIntoGroup(activeSubGroup, uuid)); 1124 1125 List<Integer> infoList = ShellIdentityUtils.invokeMethodWithShellPermissions( 1126 mSubscriptionManager, 1127 (sm) -> getSubscriptionIdList(sm.getSubscriptionsInGroup(uuid))); 1128 1129 activeSubGroup.add(subId); 1130 assertThat(infoList).containsExactlyElementsIn(activeSubGroup); 1131 } finally { 1132 removeSubscriptionsFromGroup(uuid); 1133 } 1134 } 1135 1136 /** 1137 * This test verifies that {@link SubscriptionManager#addSubscriptionsIntoGroup(List, 1138 * ParcelUuid)}} correctly add some additional subscriptions to the existing group. 1139 * 1140 * <p>This test required the device has more than one subscription. 1141 */ 1142 @Test testAddSubscriptionToExistingGroupForEsim()1143 public void testAddSubscriptionToExistingGroupForEsim() { 1144 // Set subscription group with current sub Id. 1145 int subId = SubscriptionManager.getDefaultSubscriptionId(); 1146 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return; 1147 ParcelUuid uuid = mSubscriptionManager.createSubscriptionGroup(Arrays.asList(subId)); 1148 1149 try { 1150 // Get all accessible eSim subscription. 1151 List<SubscriptionInfo> accessibleSubInfos = 1152 mSubscriptionManager.getAccessibleSubscriptionInfoList(); 1153 if (accessibleSubInfos != null && accessibleSubInfos.size() > 1) { 1154 List<Integer> accessibleSubGroup = getSubscriptionIdList(accessibleSubInfos); 1155 accessibleSubGroup.removeIf(id -> id == subId); 1156 1157 mSubscriptionManager.addSubscriptionsIntoGroup(accessibleSubGroup, uuid); 1158 1159 List<Integer> infoList = 1160 getSubscriptionIdList(mSubscriptionManager.getSubscriptionsInGroup(uuid)); 1161 accessibleSubGroup.add(subId); 1162 assertThat(infoList).containsExactlyElementsIn(accessibleSubGroup); 1163 } 1164 } finally { 1165 removeSubscriptionsFromGroup(uuid); 1166 } 1167 } 1168 1169 /** 1170 * This test verifies that {@link SubscriptionManager#setOpportunistic(boolean, int)} correctly 1171 * set the opportunistic property of the given subscription. 1172 */ 1173 @Test testOpportunistic()1174 public void testOpportunistic() { 1175 int subId = SubscriptionManager.getDefaultSubscriptionId(); 1176 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return; 1177 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId); 1178 boolean oldOpportunistic = info.isOpportunistic(); 1179 boolean newOpportunistic = !oldOpportunistic; 1180 1181 try { 1182 // Mark the given subscription as opportunistic subscription. 1183 assertThat(mSubscriptionManager.setOpportunistic(newOpportunistic, subId)).isTrue(); 1184 1185 // Verify that the given subscription is opportunistic subscription. 1186 info = mSubscriptionManager.getActiveSubscriptionInfo(subId); 1187 assertThat(info.isOpportunistic()).isEqualTo(newOpportunistic); 1188 } finally { 1189 // Set back to original opportunistic property. 1190 mSubscriptionManager.setOpportunistic(oldOpportunistic, subId); 1191 info = mSubscriptionManager.getActiveSubscriptionInfo(subId); 1192 assertThat(info.isOpportunistic()).isEqualTo(oldOpportunistic); 1193 1194 // As opportunistic subscription can not be the default data/voice/sms subscription, 1195 // when the test case set the active subscription as opportunistic, the default 1196 // subscription may set to INVALID_SUBSCRIPTION_ID. Although at the end, the test case 1197 // tries to recover it, it may take time to fully take effect and fail the following 1198 // test case. Add a polling check of carrier privilege on default subscription here to 1199 // make sure default subscription has recovered before ending the case. 1200 PollingCheck.waitFor(5000, () -> getContext().getSystemService(TelephonyManager.class) 1201 .hasCarrierPrivileges(), 1202 "Timeout when waiting to gain carrier privileges again."); 1203 } 1204 } 1205 1206 /** 1207 * This test verifies that {@link TelephonyManager#iccExchangeSimIO(int, int, int, int, int, 1208 * String)} correctly transmits iccIO commands to the UICC card. First, the MF is selected via a 1209 * SELECT apdu via the basic channel, then a STATUS AT-command is sent. 1210 */ 1211 @Test testIccExchangeSimIO()1212 public void testIccExchangeSimIO() { 1213 // select the MF first. This makes sure the next STATUS AT-command returns a FCP template 1214 // for the right file. 1215 int cla = CLA_SELECT; 1216 int p1 = 0; // select EF by FID 1217 int p2 = 0x0C; // requesting FCP template 1218 int p3 = 2; // length of 'data' payload 1219 String data = MF_FILE_ID; 1220 String response = 1221 mTelephonyManager.iccTransmitApduBasicChannel( 1222 cla, COMMAND_SELECT, p1, p2, p3, data); 1223 assertThat(response).isEqualTo(STATUS_NORMAL_STRING); 1224 1225 // The iccExchangeSimIO command implements the +CRSM command defined in TS 27.007 section 1226 // 8.18. A STATUS command is sent and the returned value will be an FCP template. 1227 byte[] result = 1228 mTelephonyManager.iccExchangeSimIO( 1229 0, // fileId: not required for STATUS 1230 COMMAND_STATUS, // command: STATUS 1231 0, // p1: not required for STATUS 1232 0, // p2: not required for STATUS 1233 0, // p3: not required for STATUS 1234 ""); // filePath: not required for STATUS 1235 String resultString = bytesToHexString(result); 1236 FcpTemplate fcpTemplate = FcpTemplate.parseFcpTemplate(resultString); 1237 assertThat(containsFileId(fcpTemplate, MF_FILE_ID)).isTrue(); 1238 assertWithMessage("iccExchangeSimIO returned non-normal Status byte: %s", resultString) 1239 .that(fcpTemplate.getStatus()) 1240 .isEqualTo(STATUS_NORMAL_STRING); 1241 } 1242 1243 /** 1244 * This test checks that a STATUS apdu can be sent as an encapsulated envelope to the UICC via 1245 * {@link TelephonyManager#sendEnvelopeWithStatus(String)}. 1246 */ 1247 @Test testSendEnvelopeWithStatus()1248 public void testSendEnvelopeWithStatus() { 1249 // STATUS apdu as hex String 1250 String envelope = 1251 CLA_STATUS_STRING 1252 + COMMAND_STATUS_STRING 1253 + "00" // p1: no indication of application status 1254 + "00"; // p2: identical parameters to 1255 String response = mTelephonyManager.sendEnvelopeWithStatus(envelope); 1256 1257 // TODO(b/137963715): add more specific assertions on response from TelMan#sendEnvelope 1258 assertWithMessage("sendEnvelopeWithStatus is null for envelope=%s", envelope) 1259 .that(response) 1260 .isNotNull(); 1261 } 1262 1263 /** 1264 * This test checks that applications with carrier privilege can set/clear signal strength 1265 * update request via {@link 1266 * TelephonyManager#setSignalStrengthUpdateRequest(SignalStrengthUpdateRequest)} and {@link 1267 * TelephonyManager#clearSignalStrengthUpdateRequest} without {@link 1268 * android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}. 1269 */ 1270 @Test testSetClearSignalStrengthUpdateRequest()1271 public void testSetClearSignalStrengthUpdateRequest() { 1272 final SignalStrengthUpdateRequest request = 1273 new SignalStrengthUpdateRequest.Builder() 1274 .setSignalThresholdInfos( 1275 List.of( 1276 new SignalThresholdInfo.Builder() 1277 .setRadioAccessNetworkType( 1278 AccessNetworkConstants.AccessNetworkType 1279 .GERAN) 1280 .setSignalMeasurementType( 1281 SignalThresholdInfo 1282 .SIGNAL_MEASUREMENT_TYPE_RSSI) 1283 .setThresholds(new int[] {-113, -103, -97, -51}) 1284 .build())) 1285 .setReportingRequestedWhileIdle(true) 1286 .build(); 1287 try { 1288 mTelephonyManager.setSignalStrengthUpdateRequest(request); 1289 } finally { 1290 mTelephonyManager.clearSignalStrengthUpdateRequest(request); 1291 } 1292 } 1293 verifyValidIccOpenLogicalChannelResponse(IccOpenLogicalChannelResponse response)1294 private void verifyValidIccOpenLogicalChannelResponse(IccOpenLogicalChannelResponse response) { 1295 // The assigned channel should be between the min and max allowed channel numbers 1296 int channel = response.getChannel(); 1297 assertThat(channel).isIn(Range.closed(MIN_LOGICAL_CHANNEL, MAX_LOGICAL_CHANNEL)); 1298 assertThat(response.getStatus()).isEqualTo(STATUS_NO_ERROR); 1299 assertThat(response.getSelectResponse()).isEqualTo(STATUS_NORMAL); 1300 } 1301 removeSubscriptionsFromGroup(ParcelUuid uuid)1302 private void removeSubscriptionsFromGroup(ParcelUuid uuid) { 1303 List<SubscriptionInfo> infoList = ShellIdentityUtils.invokeMethodWithShellPermissions( 1304 mSubscriptionManager, 1305 (sm) -> (sm.getSubscriptionsInGroup(uuid))); 1306 if (!infoList.isEmpty()) { 1307 List<Integer> subscriptionIdList = getSubscriptionIdList(infoList); 1308 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSubscriptionManager, 1309 (sm) -> sm.removeSubscriptionsFromGroup(subscriptionIdList, uuid)); 1310 } 1311 infoList = ShellIdentityUtils.invokeMethodWithShellPermissions( 1312 mSubscriptionManager, 1313 (sm) -> (sm.getSubscriptionsInGroup(uuid))); 1314 assertThat(infoList).isEmpty(); 1315 } 1316 getSubscriptionIdList(List<SubscriptionInfo> subInfoList)1317 private List<Integer> getSubscriptionIdList(List<SubscriptionInfo> subInfoList) { 1318 if (subInfoList == null || subInfoList.isEmpty()) return Collections.EMPTY_LIST; 1319 return subInfoList.stream() 1320 .map(info -> info.getSubscriptionId()) 1321 .collect(Collectors.toList()); 1322 } 1323 1324 /** 1325 * Checks whether the a {@code fcpTemplate} contains the given {@code fileId}. 1326 * 1327 * @param fcpTemplate The FCP Template to be checked. 1328 * @param fileId The file ID that is being searched for 1329 * @return true iff fcpTemplate contains fileId. 1330 */ containsFileId(FcpTemplate fcpTemplate, String fileId)1331 private boolean containsFileId(FcpTemplate fcpTemplate, String fileId) { 1332 return fcpTemplate.getTlvs().stream() 1333 .anyMatch(tlv -> tlv.getTag() == FILE_IDENTIFIER && tlv.getValue().equals(fileId)); 1334 } 1335 1336 /** 1337 * Returns true iff {@code response} indicates an error with the previous APDU. 1338 * 1339 * @param response The APDU response to be checked. 1340 * @return true iff the given response indicates an error occurred 1341 */ isErrorResponse(@onnull String response)1342 private boolean isErrorResponse(@Nonnull String response) { 1343 return !(STATUS_NORMAL_STRING.equals(response) 1344 || response.startsWith(STATUS_WARNING_A) 1345 || response.startsWith(STATUS_WARNING_B) 1346 || response.startsWith(STATUS_BYTES_REMAINING)); 1347 } 1348 1349 private static class IntentReceiver extends BroadcastReceiver { 1350 private final CountDownLatch mReceiveLatch = new CountDownLatch(1); 1351 1352 @Override onReceive(Context context, Intent intent)1353 public void onReceive(Context context, Intent intent) { 1354 mReceiveLatch.countDown(); 1355 } 1356 waitForReceive()1357 public boolean waitForReceive() throws InterruptedException { 1358 return mReceiveLatch.await(30, TimeUnit.SECONDS); 1359 } 1360 } 1361 1362 @Test testEapSimAuthentication()1363 public void testEapSimAuthentication() { 1364 assumeTrue( 1365 "testEapSimAuthentication requires a 2021 CTS UICC or newer", 1366 UiccUtil.uiccHasCertificate(CTS_UICC_2021)); 1367 // K: '000102030405060708090A0B0C0D0E0F', defined by TS 134 108#8.2 1368 // n: 128 (Bits to use for RES value) 1369 // Format: [Length][RAND] 1370 String challenge = "10" + EAP_SIM_AKA_RAND; 1371 String base64Challenge = Base64.encodeToString(hexStringToBytes(challenge), Base64.NO_WRAP); 1372 String base64Response = 1373 mTelephonyManager.getIccAuthentication( 1374 TelephonyManager.APPTYPE_USIM, 1375 TelephonyManager.AUTHTYPE_EAP_SIM, 1376 base64Challenge); 1377 byte[] response = Base64.decode(base64Response, Base64.DEFAULT); 1378 assertWithMessage("Results for AUTHTYPE_EAP_SIM failed") 1379 .that(response) 1380 .isEqualTo(hexStringToBytes(EXPECTED_EAP_SIM_RESULT)); 1381 } 1382 1383 @Test testEapAkaAuthentication()1384 public void testEapAkaAuthentication() { 1385 assumeTrue( 1386 "testEapAkaAuthentication requires a 2021 CTS UICC or newer", 1387 UiccUtil.uiccHasCertificate(CTS_UICC_2021)); 1388 // K: '000102030405060708090A0B0C0D0E0F', defined by TS 134 108#8.2 1389 // n: 128 (Bits to use for RES value) 1390 // Format: [Length][Rand][Length][Autn] 1391 String challenge = "10" + EAP_SIM_AKA_RAND + "10" + EAP_AKA_AUTN; 1392 String base64Challenge = Base64.encodeToString(hexStringToBytes(challenge), Base64.NO_WRAP); 1393 String base64Response = 1394 mTelephonyManager.getIccAuthentication( 1395 TelephonyManager.APPTYPE_USIM, 1396 TelephonyManager.AUTHTYPE_EAP_AKA, 1397 base64Challenge); 1398 1399 assertWithMessage("UICC returned null for EAP-AKA auth").that(base64Response).isNotNull(); 1400 byte[] response = Base64.decode(base64Response, Base64.NO_WRAP); 1401 1402 // response may be formatted as: [DB][Length][RES][Length][CK][Length][IK][Length][Kc] 1403 byte[] akaResponse = Arrays.copyOfRange(response, 0, EAP_AKA_RESPONSE_LENGTH); 1404 assertWithMessage("Results for AUTHTYPE_EAP_AKA failed") 1405 .that(akaResponse) 1406 .isEqualTo(hexStringToBytes(EXPECTED_EAP_AKA_RESULT)); 1407 } 1408 1409 /** 1410 * This test checks that applications with carrier privilege can set/get data enable 1411 * state. 1412 */ 1413 @Test testDataEnableRequest()1414 public void testDataEnableRequest() { 1415 for (int i = DATA_ENABLED_REASON_USER; i <= DATA_ENABLED_REASON_THERMAL; i++) { 1416 mTelephonyManager.isDataEnabledForReason(i); 1417 } 1418 boolean isDataEnabled = mTelephonyManager.isDataEnabledForReason( 1419 TelephonyManager.DATA_ENABLED_REASON_CARRIER); 1420 mTelephonyManager.setDataEnabledForReason( 1421 TelephonyManager.DATA_ENABLED_REASON_CARRIER, !isDataEnabled); 1422 mTelephonyManager.setDataEnabledForReason( 1423 TelephonyManager.DATA_ENABLED_REASON_CARRIER, isDataEnabled); 1424 } 1425 1426 /** 1427 * This test checks that applications with carrier privileges can get network slicing 1428 * configuration. 1429 */ 1430 @Test testGetNetworkSlicingConfiguration()1431 public void testGetNetworkSlicingConfiguration() { 1432 CompletableFuture<NetworkSlicingConfig> resultFuture = new CompletableFuture<>(); 1433 mTelephonyManager.getNetworkSlicingConfiguration( 1434 AsyncTask.SERIAL_EXECUTOR, resultFuture::complete); 1435 } 1436 } 1437