1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. 4 * Not a Contribution. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package com.android.internal.telephony; 20 21 import static android.Manifest.permission.MODIFY_PHONE_STATE; 22 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; 23 import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING; 24 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.app.AppOpsManager; 28 import android.app.compat.CompatChanges; 29 import android.compat.annotation.UnsupportedAppUsage; 30 import android.content.Context; 31 import android.content.pm.PackageManager; 32 import android.net.Uri; 33 import android.os.Binder; 34 import android.os.Build; 35 import android.os.RemoteException; 36 import android.os.SystemProperties; 37 import android.os.TelephonyServiceManager.ServiceRegisterer; 38 import android.telephony.ImsiEncryptionInfo; 39 import android.telephony.PhoneNumberUtils; 40 import android.telephony.SubscriptionManager; 41 import android.telephony.TelephonyFrameworkInitializer; 42 import android.text.TextUtils; 43 import android.util.EventLog; 44 45 import com.android.internal.telephony.flags.FeatureFlags; 46 import com.android.internal.telephony.flags.FeatureFlagsImpl; 47 import com.android.internal.telephony.subscription.SubscriptionInfoInternal; 48 import com.android.internal.telephony.subscription.SubscriptionManagerService; 49 import com.android.internal.telephony.uicc.IsimRecords; 50 import com.android.internal.telephony.uicc.SIMRecords; 51 import com.android.internal.telephony.uicc.UiccCardApplication; 52 import com.android.internal.telephony.uicc.UiccPort; 53 import com.android.telephony.Rlog; 54 55 import java.util.ArrayList; 56 import java.util.Arrays; 57 import java.util.List; 58 import java.util.stream.Collectors; 59 60 public class PhoneSubInfoController extends IPhoneSubInfo.Stub { 61 private static final String TAG = "PhoneSubInfoController"; 62 private static final boolean DBG = true; 63 private static final boolean VDBG = false; // STOPSHIP if true 64 65 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 66 private final Context mContext; 67 private AppOpsManager mAppOps; 68 private FeatureFlags mFeatureFlags; 69 private PackageManager mPackageManager; 70 private final int mVendorApiLevel; 71 PhoneSubInfoController(Context context)72 public PhoneSubInfoController(Context context) { 73 this(context, new FeatureFlagsImpl()); 74 } 75 PhoneSubInfoController(Context context, FeatureFlags featureFlags)76 public PhoneSubInfoController(Context context, FeatureFlags featureFlags) { 77 ServiceRegisterer phoneSubServiceRegisterer = TelephonyFrameworkInitializer 78 .getTelephonyServiceManager() 79 .getPhoneSubServiceRegisterer(); 80 if (phoneSubServiceRegisterer.get() == null) { 81 phoneSubServiceRegisterer.register(this); 82 } 83 mAppOps = context.getSystemService(AppOpsManager.class); 84 mContext = context; 85 mPackageManager = context.getPackageManager(); 86 mFeatureFlags = featureFlags; 87 mVendorApiLevel = SystemProperties.getInt( 88 "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT); 89 } 90 91 @Deprecated getDeviceId(String callingPackage)92 public String getDeviceId(String callingPackage) { 93 return getDeviceIdWithFeature(callingPackage, null); 94 } 95 getDeviceIdWithFeature(String callingPackage, String callingFeatureId)96 public String getDeviceIdWithFeature(String callingPackage, String callingFeatureId) { 97 return getDeviceIdForPhone(SubscriptionManager.getPhoneId(getDefaultSubscription()), 98 callingPackage, callingFeatureId); 99 } 100 getDeviceIdForPhone(int phoneId, String callingPackage, String callingFeatureId)101 public String getDeviceIdForPhone(int phoneId, String callingPackage, 102 String callingFeatureId) { 103 enforceCallingPackageUidMatched(callingPackage); 104 return callPhoneMethodForPhoneIdWithReadDeviceIdentifiersCheck(phoneId, callingPackage, 105 callingFeatureId, "getDeviceId", (phone) -> phone.getDeviceId()); 106 } 107 getNaiForSubscriber(int subId, String callingPackage, String callingFeatureId)108 public String getNaiForSubscriber(int subId, String callingPackage, String callingFeatureId) { 109 return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage, 110 callingFeatureId, "getNai", (phone)-> { 111 enforceTelephonyFeatureWithException(callingPackage, 112 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, 113 "getNaiForSubscriber"); 114 115 return phone.getNai(); 116 }); 117 } 118 getImeiForSubscriber(int subId, String callingPackage, String callingFeatureId)119 public String getImeiForSubscriber(int subId, String callingPackage, 120 String callingFeatureId) { 121 return callPhoneMethodForSubIdWithReadDeviceIdentifiersCheck(subId, callingPackage, 122 callingFeatureId, "getImei", (phone) -> phone.getImei()); 123 } 124 getCarrierInfoForImsiEncryption(int subId, int keyType, String callingPackage)125 public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int subId, int keyType, 126 String callingPackage) { 127 return callPhoneMethodForSubIdWithPrivilegedCheck(subId, 128 "getCarrierInfoForImsiEncryption", 129 (phone)-> { 130 enforceTelephonyFeatureWithException(callingPackage, 131 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, 132 "getCarrierInfoForImsiEncryption"); 133 134 return phone.getCarrierInfoForImsiEncryption(keyType, true); 135 }); 136 } 137 138 public void setCarrierInfoForImsiEncryption(int subId, String callingPackage, 139 ImsiEncryptionInfo imsiEncryptionInfo) { 140 callPhoneMethodForSubIdWithModifyCheck(subId, callingPackage, 141 "setCarrierInfoForImsiEncryption", 142 (phone)-> { 143 phone.setCarrierInfoForImsiEncryption(imsiEncryptionInfo); 144 return null; 145 }); 146 } 147 148 /** 149 * Resets the Carrier Keys in the database. This involves 2 steps: 150 * 1. Delete the keys from the database. 151 * 2. Send an intent to download new Certificates. 152 * @param subId 153 * @param callingPackage 154 */ 155 public void resetCarrierKeysForImsiEncryption(int subId, String callingPackage) { 156 callPhoneMethodForSubIdWithModifyCheck(subId, callingPackage, 157 "resetCarrierKeysForImsiEncryption", 158 (phone)-> { 159 enforceTelephonyFeatureWithException(callingPackage, 160 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, 161 "resetCarrierKeysForImsiEncryption"); 162 163 phone.resetCarrierKeysForImsiEncryption(); 164 return null; 165 }); 166 } 167 168 public String getDeviceSvn(String callingPackage, String callingFeatureId) { 169 return getDeviceSvnUsingSubId(getDefaultSubscription(), callingPackage, callingFeatureId); 170 } 171 172 public String getDeviceSvnUsingSubId(int subId, String callingPackage, 173 String callingFeatureId) { 174 return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId, 175 "getDeviceSvn", (phone)-> phone.getDeviceSvn()); 176 } 177 178 @Deprecated 179 public String getSubscriberId(String callingPackage) { 180 return getSubscriberIdWithFeature(callingPackage, null); 181 } 182 183 public String getSubscriberIdWithFeature(String callingPackage, String callingFeatureId) { 184 return getSubscriberIdForSubscriber(getDefaultSubscription(), callingPackage, 185 callingFeatureId); 186 } 187 188 public String getSubscriberIdForSubscriber(int subId, String callingPackage, 189 String callingFeatureId) { 190 String message = "getSubscriberIdForSubscriber"; 191 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); 192 193 long identity = Binder.clearCallingIdentity(); 194 boolean isActive; 195 try { 196 isActive = SubscriptionManagerService.getInstance().isActiveSubId(subId, 197 callingPackage, callingFeatureId); 198 } finally { 199 Binder.restoreCallingIdentity(identity); 200 } 201 if (isActive) { 202 return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage, 203 callingFeatureId, message, (phone) -> { 204 enforceTelephonyFeatureWithException(callingPackage, 205 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, 206 "getSubscriberIdForSubscriber"); 207 208 return phone.getSubscriberId(); 209 }); 210 } else { 211 if (!TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers( 212 mContext, subId, callingPackage, callingFeatureId, message)) { 213 return null; 214 } 215 216 enforceTelephonyFeatureWithException(callingPackage, 217 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getSubscriberIdForSubscriber"); 218 219 identity = Binder.clearCallingIdentity(); 220 try { 221 SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance() 222 .getSubscriptionInfoInternal(subId); 223 if (subInfo != null && !TextUtils.isEmpty(subInfo.getImsi())) { 224 return subInfo.getImsi(); 225 } 226 return null; 227 } finally { 228 Binder.restoreCallingIdentity(identity); 229 } 230 } 231 } 232 233 @Deprecated 234 public String getIccSerialNumber(String callingPackage) { 235 return getIccSerialNumberWithFeature(callingPackage, null); 236 } 237 238 /** 239 * Retrieves the serial number of the ICC, if applicable. 240 */ 241 public String getIccSerialNumberWithFeature(String callingPackage, String callingFeatureId) { 242 return getIccSerialNumberForSubscriber(getDefaultSubscription(), callingPackage, 243 callingFeatureId); 244 } 245 246 public String getIccSerialNumberForSubscriber(int subId, String callingPackage, 247 String callingFeatureId) { 248 return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage, 249 callingFeatureId, "getIccSerialNumber", (phone) -> { 250 enforceTelephonyFeatureWithException(callingPackage, 251 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, 252 "getIccSerialNumberForSubscriber"); 253 254 return phone.getIccSerialNumber(); 255 }); 256 } 257 258 public String getLine1Number(String callingPackage, String callingFeatureId) { 259 return getLine1NumberForSubscriber(getDefaultSubscription(), callingPackage, 260 callingFeatureId); 261 } 262 263 // In R and beyond, READ_PHONE_NUMBERS includes READ_PHONE_NUMBERS and READ_SMS only. 264 // Prior to R, it also included READ_PHONE_STATE. Maintain that for compatibility. 265 public String getLine1NumberForSubscriber(int subId, String callingPackage, 266 String callingFeatureId) { 267 return callPhoneMethodForSubIdWithReadPhoneNumberCheck( 268 subId, callingPackage, callingFeatureId, "getLine1Number", 269 (phone)-> { 270 enforceTelephonyFeatureWithException(callingPackage, 271 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, 272 "getLine1NumberForSubscriber"); 273 274 return phone.getLine1Number(); 275 }); 276 } 277 278 public String getLine1AlphaTag(String callingPackage, String callingFeatureId) { 279 return getLine1AlphaTagForSubscriber(getDefaultSubscription(), callingPackage, 280 callingFeatureId); 281 } 282 283 public String getLine1AlphaTagForSubscriber(int subId, String callingPackage, 284 String callingFeatureId) { 285 return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId, 286 "getLine1AlphaTag", (phone)-> phone.getLine1AlphaTag()); 287 } 288 289 public String getMsisdn(String callingPackage, String callingFeatureId) { 290 return getMsisdnForSubscriber(getDefaultSubscription(), callingPackage, callingFeatureId); 291 } 292 293 // In R and beyond this will require READ_PHONE_NUMBERS. 294 // Prior to R it needed READ_PHONE_STATE. Maintain that for compatibility. 295 public String getMsisdnForSubscriber(int subId, String callingPackage, 296 String callingFeatureId) { 297 return callPhoneMethodForSubIdWithReadPhoneNumberCheck( 298 subId, callingPackage, callingFeatureId, "getMsisdn", (phone)-> phone.getMsisdn()); 299 } 300 301 public String getVoiceMailNumber(String callingPackage, String callingFeatureId) { 302 return getVoiceMailNumberForSubscriber(getDefaultSubscription(), callingPackage, 303 callingFeatureId); 304 } 305 306 public String getVoiceMailNumberForSubscriber(int subId, String callingPackage, 307 String callingFeatureId) { 308 return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId, 309 "getVoiceMailNumber", (phone)-> { 310 enforceTelephonyFeatureWithException(callingPackage, 311 PackageManager.FEATURE_TELEPHONY_CALLING, 312 "getVoiceMailNumberForSubscriber"); 313 314 String number = PhoneNumberUtils.extractNetworkPortion( 315 phone.getVoiceMailNumber()); 316 if (VDBG) log("VM: getVoiceMailNUmber: " + number); 317 return number; 318 }); 319 } 320 321 public String getVoiceMailAlphaTag(String callingPackage, String callingFeatureId) { 322 return getVoiceMailAlphaTagForSubscriber(getDefaultSubscription(), callingPackage, 323 callingFeatureId); 324 } 325 326 public String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage, 327 String callingFeatureId) { 328 return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId, 329 "getVoiceMailAlphaTag", (phone)-> { 330 enforceTelephonyFeatureWithException(callingPackage, 331 PackageManager.FEATURE_TELEPHONY_CALLING, 332 "getVoiceMailAlphaTagForSubscriber"); 333 334 return phone.getVoiceMailAlphaTag(); 335 }); 336 } 337 338 /** 339 * get Phone object based on subId. 340 **/ 341 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 342 private Phone getPhone(int subId) { 343 int phoneId = SubscriptionManager.getPhoneId(subId); 344 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 345 return null; 346 } 347 return PhoneFactory.getPhone(phoneId); 348 } 349 350 private void enforceCallingPackageUidMatched(String callingPackage) { 351 try { 352 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); 353 } catch (SecurityException se) { 354 EventLog.writeEvent(0x534e4554, "188677422", Binder.getCallingUid()); 355 throw se; 356 } 357 } 358 359 private boolean enforceIccSimChallengeResponsePermission(Context context, int subId, 360 String callingPackage, String callingFeatureId, String message) { 361 if (TelephonyPermissions.checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, 362 callingPackage, callingFeatureId, message)) { 363 return true; 364 } 365 if (VDBG) log("No USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER permission."); 366 enforcePrivilegedPermissionOrCarrierPrivilege(subId, message); 367 return true; 368 } 369 370 /** 371 * Make sure caller has either read privileged phone permission or carrier privilege. 372 * 373 * @throws SecurityException if the caller does not have the required permission/privilege 374 */ 375 private void enforcePrivilegedPermissionOrCarrierPrivilege(int subId, String message) { 376 // TODO(b/73660190): Migrate to 377 // TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivileges and delete 378 // this helper method. 379 int permissionResult = mContext.checkCallingOrSelfPermission( 380 READ_PRIVILEGED_PHONE_STATE); 381 if (permissionResult == PackageManager.PERMISSION_GRANTED) { 382 return; 383 } 384 if (VDBG) log("No read privileged phone permission, check carrier privilege next."); 385 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, subId, message); 386 } 387 388 /** 389 * Make sure caller has modify phone state permission. 390 */ 391 private void enforceModifyPermission() { 392 mContext.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, 393 "Requires MODIFY_PHONE_STATE"); 394 } 395 396 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 397 private int getDefaultSubscription() { 398 return PhoneFactory.getDefaultSubscription(); 399 } 400 401 /** 402 * get the Isim Impi based on subId 403 */ 404 public String getIsimImpi(int subId) { 405 return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimImpi", 406 (phone) -> { 407 IsimRecords isim = phone.getIsimRecords(); 408 if (isim != null) { 409 return isim.getIsimImpi(); 410 } else { 411 return null; 412 } 413 }); 414 } 415 416 /** 417 * Fetches the IMS private user identity (EF_IMPI) based on subscriptionId. 418 * 419 * @param subId subscriptionId 420 * @return IMPI (IMS private user identity) of type string. 421 * @throws IllegalArgumentException if the subscriptionId is not valid 422 * @throws IllegalStateException in case the ISIM hasn’t been loaded. 423 * @throws SecurityException if the caller does not have the required permission 424 */ 425 public String getImsPrivateUserIdentity(int subId, String callingPackage, 426 String callingFeatureId) { 427 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 428 throw new IllegalArgumentException("Invalid SubscriptionID = " + subId); 429 } 430 if (!TelephonyPermissions.checkCallingOrSelfUseIccAuthWithDeviceIdentifier(mContext, 431 callingPackage, callingFeatureId, "getImsPrivateUserIdentity")) { 432 throw (new SecurityException("No permissions to the caller")); 433 } 434 Phone phone = getPhone(subId); 435 assert phone != null; 436 IsimRecords isim = phone.getIsimRecords(); 437 if (isim != null) { 438 return isim.getIsimImpi(); 439 } else { 440 throw new IllegalStateException("ISIM is not loaded"); 441 } 442 } 443 444 /** 445 * get the Isim Domain based on subId 446 */ 447 public String getIsimDomain(int subId) { 448 return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimDomain", 449 (phone) -> { 450 enforceTelephonyFeatureWithException(getCurrentPackageName(), 451 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getIsimDomain"); 452 453 IsimRecords isim = phone.getIsimRecords(); 454 if (isim != null) { 455 return isim.getIsimDomain(); 456 } else { 457 return null; 458 } 459 }); 460 } 461 462 /** 463 * get the Isim Impu based on subId 464 */ 465 public String[] getIsimImpu(int subId) { 466 return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimImpu", 467 (phone) -> { 468 IsimRecords isim = phone.getIsimRecords(); 469 if (isim != null) { 470 return isim.getIsimImpu(); 471 } else { 472 return null; 473 } 474 }); 475 } 476 477 /** 478 * Fetches the ISIM public user identities (EF_IMPU) from UICC based on subId 479 * 480 * @param subId subscriptionId 481 * @param callingPackage package name of the caller 482 * @return List of public user identities of type android.net.Uri or empty list if 483 * EF_IMPU is not available. 484 * @throws IllegalArgumentException if the subscriptionId is not valid 485 * @throws IllegalStateException in case the ISIM hasn’t been loaded. 486 * @throws SecurityException if the caller does not have the required permission 487 */ 488 public List<Uri> getImsPublicUserIdentities(int subId, String callingPackage) { 489 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 490 throw new IllegalArgumentException("Invalid subscription: " + subId); 491 } 492 493 TelephonyPermissions 494 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege( 495 mContext, subId, "getImsPublicUserIdentities"); 496 enforceTelephonyFeatureWithException(callingPackage, 497 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getImsPublicUserIdentities"); 498 499 Phone phone = getPhone(subId); 500 assert phone != null; 501 IsimRecords isimRecords = phone.getIsimRecords(); 502 if (isimRecords != null) { 503 String[] impus = isimRecords.getIsimImpu(); 504 List<Uri> impuList = new ArrayList<>(); 505 for (String impu : impus) { 506 if (impu != null && impu.trim().length() > 0) { 507 impuList.add(Uri.parse(impu)); 508 } 509 } 510 return impuList; 511 } 512 throw new IllegalStateException("ISIM is not loaded"); 513 } 514 515 /** 516 * get the Isim Ist based on subId 517 */ 518 public String getIsimIst(int subId) throws RemoteException { 519 return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimIst", 520 (phone) -> { 521 enforceTelephonyFeatureWithException(getCurrentPackageName(), 522 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getIsimIst"); 523 524 IsimRecords isim = phone.getIsimRecords(); 525 if (isim != null) { 526 return isim.getIsimIst(); 527 } else { 528 return null; 529 } 530 }); 531 } 532 533 /** 534 * get the Isim Pcscf based on subId 535 */ 536 public String[] getIsimPcscf(int subId) throws RemoteException { 537 return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getIsimPcscf", 538 (phone) -> { 539 IsimRecords isim = phone.getIsimRecords(); 540 if (isim != null) { 541 return isim.getIsimPcscf(); 542 } else { 543 return null; 544 } 545 }); 546 } 547 548 /** 549 * Fetches the IMS Proxy Call Session Control Function(P-CSCF) based on the subscription. 550 * 551 * @param subId subscriptionId 552 * @param callingPackage package name of the caller 553 * @return List of IMS Proxy Call Session Control Function strings. 554 * @throws IllegalArgumentException if the subscriptionId is not valid 555 * @throws IllegalStateException in case the ISIM hasn’t been loaded. 556 * @throws SecurityException if the caller does not have the required permission 557 */ 558 public List<String> getImsPcscfAddresses(int subId, String callingPackage) { 559 if (!mFeatureFlags.supportIsimRecord()) { 560 return new ArrayList<>(); 561 } 562 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 563 throw new IllegalArgumentException("Invalid subscription: " + subId); 564 } 565 566 TelephonyPermissions 567 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege( 568 mContext, subId, "getImsPcscfAddresses"); 569 enforceTelephonyFeatureWithException(callingPackage, 570 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getImsPcscfAddresses"); 571 572 Phone phone = getPhone(subId); 573 assert phone != null; 574 IsimRecords isimRecords = phone.getIsimRecords(); 575 if (isimRecords != null) { 576 String[] pcscfs = isimRecords.getIsimPcscf(); 577 List<String> pcscfList = Arrays.stream(pcscfs) 578 .filter(u -> u != null) 579 .map(u -> u.trim()) 580 .filter(u -> u.length() > 0) 581 .collect(Collectors.toList()); 582 return pcscfList; 583 } 584 throw new IllegalStateException("ISIM is not loaded"); 585 } 586 587 /** 588 * Returns the USIM service table that fetched from EFUST elementary field that are loaded 589 * based on the appType. 590 */ 591 public String getSimServiceTable(int subId, int appType) throws RemoteException { 592 return callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getSimServiceTable", 593 (phone) -> { 594 enforceTelephonyFeatureWithException(getCurrentPackageName(), 595 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getSimServiceTable"); 596 597 UiccPort uiccPort = phone.getUiccPort(); 598 if (uiccPort == null || uiccPort.getUiccProfile() == null) { 599 loge("getSimServiceTable(): uiccPort or uiccProfile is null"); 600 return null; 601 } 602 UiccCardApplication uiccApp = uiccPort.getUiccProfile().getApplicationByType( 603 appType); 604 if (uiccApp == null) { 605 loge("getSimServiceTable(): no app with specified apptype=" 606 + appType); 607 return null; 608 } 609 return ((SIMRecords)uiccApp.getIccRecords()).getSimServiceTable(); 610 }); 611 } 612 613 @Override 614 public String getIccSimChallengeResponse(int subId, int appType, int authType, String data, 615 String callingPackage, String callingFeatureId) throws RemoteException { 616 CallPhoneMethodHelper<String> toExecute = (phone)-> { 617 enforceTelephonyFeatureWithException(callingPackage, 618 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getIccSimChallengeResponse"); 619 620 UiccPort uiccPort = phone.getUiccPort(); 621 if (uiccPort == null) { 622 loge("getIccSimChallengeResponse() uiccPort is null"); 623 return null; 624 } 625 626 UiccCardApplication uiccApp = uiccPort.getApplicationByType(appType); 627 if (uiccApp == null) { 628 loge("getIccSimChallengeResponse() no app with specified type -- " + appType); 629 return null; 630 } else { 631 loge("getIccSimChallengeResponse() found app " + uiccApp.getAid() 632 + " specified type -- " + appType); 633 } 634 635 if (authType != UiccCardApplication.AUTH_CONTEXT_EAP_SIM 636 && authType != UiccCardApplication.AUTH_CONTEXT_EAP_AKA 637 && authType != UiccCardApplication.AUTH_CONTEXT_GBA_BOOTSTRAP 638 && authType != UiccCardApplication.AUTHTYPE_GBA_NAF_KEY_EXTERNAL) { 639 loge("getIccSimChallengeResponse() unsupported authType: " + authType); 640 return null; 641 } 642 return uiccApp.getIccRecords().getIccSimChallengeResponse(authType, data); 643 }; 644 645 return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId, 646 "getIccSimChallengeResponse", toExecute, 647 this::enforceIccSimChallengeResponsePermission); 648 } 649 650 public String getGroupIdLevel1ForSubscriber(int subId, String callingPackage, 651 String callingFeatureId) { 652 return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage, callingFeatureId, 653 "getGroupIdLevel1", (phone)-> { 654 enforceTelephonyFeatureWithException(callingPackage, 655 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, 656 "getGroupIdLevel1ForSubscriber"); 657 658 return phone.getGroupIdLevel1(); 659 }); 660 } 661 662 /** 663 * Return GroupIdLevel2 for the subscriber 664 */ 665 public String getGroupIdLevel2ForSubscriber(int subId, String callingPackage, 666 String callingFeatureId) { 667 return callPhoneMethodForSubIdWithPrivilegedCheck(subId, 668 "getGroupIdLevel2", (phone)-> { 669 enforceTelephonyFeatureWithException(callingPackage, 670 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, 671 "getGroupIdLevel2ForSubscriber"); 672 return phone.getGroupIdLevel2(); 673 }); 674 } 675 676 /** Below are utility methods that abstracts the flow that many public methods use: 677 * 1. Check permission: pass, throw exception, or fails (returns false). 678 * 2. clearCallingIdentity. 679 * 3. Call a specified phone method and get return value. 680 * 4. restoreCallingIdentity and return. 681 */ 682 private interface CallPhoneMethodHelper<T> { 683 T callMethod(Phone phone); 684 } 685 686 private interface PermissionCheckHelper { 687 // Implemented to do whatever permission check it wants. 688 // If passes, it should return true. 689 // If permission is not granted, throws SecurityException. 690 // If permission is revoked by AppOps, return false. 691 boolean checkPermission(Context context, int subId, String callingPackage, 692 @Nullable String callingFeatureId, String message); 693 } 694 695 // Base utility method that others use. 696 private <T> T callPhoneMethodWithPermissionCheck(int subId, String callingPackage, 697 @Nullable String callingFeatureId, String message, 698 CallPhoneMethodHelper<T> callMethodHelper, 699 PermissionCheckHelper permissionCheckHelper) { 700 if (!permissionCheckHelper.checkPermission(mContext, subId, callingPackage, 701 callingFeatureId, message)) { 702 return null; 703 } 704 705 final long identity = Binder.clearCallingIdentity(); 706 try { 707 Phone phone = getPhone(subId); 708 if (phone != null) { 709 return callMethodHelper.callMethod(phone); 710 } else { 711 if (VDBG) loge(message + " phone is null for Subscription:" + subId); 712 return null; 713 } 714 } finally { 715 Binder.restoreCallingIdentity(identity); 716 } 717 } 718 719 private <T> T callPhoneMethodForSubIdWithReadCheck(int subId, String callingPackage, 720 @Nullable String callingFeatureId, String message, 721 CallPhoneMethodHelper<T> callMethodHelper) { 722 return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId, 723 message, callMethodHelper, 724 (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)-> 725 TelephonyPermissions.checkCallingOrSelfReadPhoneState( 726 aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)); 727 } 728 729 private <T> T callPhoneMethodForSubIdWithReadDeviceIdentifiersCheck(int subId, 730 String callingPackage, @Nullable String callingFeatureId, String message, 731 CallPhoneMethodHelper<T> callMethodHelper) { 732 return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId, 733 message, callMethodHelper, 734 (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)-> 735 TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers( 736 aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)); 737 } 738 739 private <T> T callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(int subId, 740 String callingPackage, @Nullable String callingFeatureId, String message, 741 CallPhoneMethodHelper<T> callMethodHelper) { 742 return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId, 743 message, callMethodHelper, 744 (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)-> 745 TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers( 746 aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)); 747 } 748 749 private <T> T callPhoneMethodForSubIdWithPrivilegedCheck( 750 int subId, String message, CallPhoneMethodHelper<T> callMethodHelper) { 751 return callPhoneMethodWithPermissionCheck(subId, null, null, message, callMethodHelper, 752 (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage) -> { 753 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, message); 754 return true; 755 }); 756 } 757 758 private <T> T callPhoneMethodForSubIdWithModifyCheck(int subId, String callingPackage, 759 String message, CallPhoneMethodHelper<T> callMethodHelper) { 760 return callPhoneMethodWithPermissionCheck(subId, null, null, message, callMethodHelper, 761 (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)-> { 762 enforceModifyPermission(); 763 return true; 764 }); 765 } 766 767 private <T> T callPhoneMethodForSubIdWithReadPhoneNumberCheck(int subId, String callingPackage, 768 @NonNull String callingFeatureId, String message, 769 CallPhoneMethodHelper<T> callMethodHelper) { 770 return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId, 771 message, callMethodHelper, 772 (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage) -> 773 TelephonyPermissions.checkCallingOrSelfReadPhoneNumber( 774 aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)); 775 } 776 777 private <T> T callPhoneMethodForPhoneIdWithReadDeviceIdentifiersCheck(int phoneId, 778 String callingPackage, @Nullable String callingFeatureId, String message, 779 CallPhoneMethodHelper<T> callMethodHelper) { 780 // Getting subId before doing permission check. 781 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 782 phoneId = 0; 783 } 784 final Phone phone = PhoneFactory.getPhone(phoneId); 785 if (phone == null) { 786 return null; 787 } 788 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext, 789 phone.getSubId(), callingPackage, callingFeatureId, message)) { 790 return null; 791 } 792 793 final long identity = Binder.clearCallingIdentity(); 794 try { 795 return callMethodHelper.callMethod(phone); 796 } finally { 797 Binder.restoreCallingIdentity(identity); 798 } 799 } 800 801 /** 802 * Returns SIP URI or tel URI of the Public Service Identity of the SM-SC fetched from 803 * EF_PSISMSC elementary field as defined in Section 4.5.9 (3GPP TS 31.102). 804 * @throws IllegalStateException in case if phone or UiccApplication is not available. 805 */ 806 public Uri getSmscIdentity(int subId, int appType) throws RemoteException { 807 Uri smscIdentityUri = callPhoneMethodForSubIdWithPrivilegedCheck(subId, "getSmscIdentity", 808 (phone) -> { 809 enforceTelephonyFeatureWithException(getCurrentPackageName(), 810 PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getSmscIdentity"); 811 812 try { 813 String smscIdentity = null; 814 UiccPort uiccPort = phone.getUiccPort(); 815 UiccCardApplication uiccApp = 816 uiccPort.getUiccProfile().getApplicationByType( 817 appType); 818 smscIdentity = (uiccApp != null) ? uiccApp.getIccRecords().getSmscIdentity() 819 : null; 820 if (TextUtils.isEmpty(smscIdentity)) { 821 return Uri.EMPTY; 822 } 823 return Uri.parse(smscIdentity); 824 } catch (NullPointerException ex) { 825 Rlog.e(TAG, "getSmscIdentity(): Exception = " + ex); 826 return null; 827 } 828 }); 829 if (smscIdentityUri == null) { 830 throw new IllegalStateException("Telephony service error"); 831 } 832 return smscIdentityUri; 833 } 834 835 /** 836 * Get the current calling package name. 837 * @return the current calling package name 838 */ 839 @Nullable 840 private String getCurrentPackageName() { 841 if (mFeatureFlags.hsumPackageManager()) { 842 PackageManager pm = mContext.createContextAsUser(Binder.getCallingUserHandle(), 0) 843 .getPackageManager(); 844 if (pm == null) return null; 845 String[] callingPackageNames = pm.getPackagesForUid(Binder.getCallingUid()); 846 return (callingPackageNames == null) ? null : callingPackageNames[0]; 847 } 848 if (mPackageManager == null) return null; 849 String[] callingPackageNames = mPackageManager.getPackagesForUid(Binder.getCallingUid()); 850 return (callingPackageNames == null) ? null : callingPackageNames[0]; 851 } 852 853 /** 854 * Make sure the device has required telephony feature 855 * 856 * @throws UnsupportedOperationException if the device does not have required telephony feature 857 */ 858 private void enforceTelephonyFeatureWithException(@Nullable String callingPackage, 859 @NonNull String telephonyFeature, @NonNull String methodName) { 860 if (callingPackage == null || mPackageManager == null) { 861 return; 862 } 863 864 if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage, 865 Binder.getCallingUserHandle()) 866 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) { 867 // Skip to check associated telephony feature, 868 // if compatibility change is not enabled for the current process or 869 // the SDK version of vendor partition is less than Android V. 870 return; 871 } 872 873 if (!mPackageManager.hasSystemFeature(telephonyFeature)) { 874 throw new UnsupportedOperationException( 875 methodName + " is unsupported without " + telephonyFeature); 876 } 877 } 878 879 private void log(String s) { 880 Rlog.d(TAG, s); 881 } 882 883 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 884 private void loge(String s) { 885 Rlog.e(TAG, s); 886 } 887 } 888