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