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