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.CALL_PRIVILEGED; 22 import static android.Manifest.permission.MODIFY_PHONE_STATE; 23 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; 24 25 import android.app.AppOpsManager; 26 import android.content.Context; 27 import android.content.pm.PackageManager; 28 import android.os.RemoteException; 29 import android.os.ServiceManager; 30 import android.telephony.ImsiEncryptionInfo; 31 import android.telephony.PhoneNumberUtils; 32 import android.telephony.Rlog; 33 import android.telephony.SubscriptionManager; 34 35 import com.android.internal.telephony.uicc.IsimRecords; 36 import com.android.internal.telephony.uicc.UiccCard; 37 import com.android.internal.telephony.uicc.UiccCardApplication; 38 39 public class PhoneSubInfoController extends IPhoneSubInfo.Stub { 40 private static final String TAG = "PhoneSubInfoController"; 41 private static final boolean DBG = true; 42 private static final boolean VDBG = false; // STOPSHIP if true 43 44 private final Phone[] mPhone; 45 private final Context mContext; 46 private final AppOpsManager mAppOps; 47 48 public PhoneSubInfoController(Context context, Phone[] phone) { 49 mPhone = phone; 50 if (ServiceManager.getService("iphonesubinfo") == null) { 51 ServiceManager.addService("iphonesubinfo", this); 52 } 53 mContext = context; 54 mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 55 } 56 57 public String getDeviceId(String callingPackage) { 58 return getDeviceIdForPhone(SubscriptionManager.getPhoneId(getDefaultSubscription()), 59 callingPackage); 60 } 61 62 public String getDeviceIdForPhone(int phoneId, String callingPackage) { 63 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 64 phoneId = 0; 65 } 66 final Phone phone = mPhone[phoneId]; 67 if (phone != null) { 68 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 69 mContext, phone.getSubId(), callingPackage, "getDeviceId")) { 70 return null; 71 } 72 return phone.getDeviceId(); 73 } else { 74 loge("getDeviceIdForPhone phone " + phoneId + " is null"); 75 return null; 76 } 77 } 78 79 public String getNaiForSubscriber(int subId, String callingPackage) { 80 Phone phone = getPhone(subId); 81 if (phone != null) { 82 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 83 mContext, subId, callingPackage, "getNai")) { 84 return null; 85 } 86 return phone.getNai(); 87 } else { 88 loge("getNai phone is null for Subscription:" + subId); 89 return null; 90 } 91 } 92 93 public String getImeiForSubscriber(int subId, String callingPackage) { 94 Phone phone = getPhone(subId); 95 if (phone != null) { 96 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 97 mContext, subId, callingPackage, "getImei")) { 98 return null; 99 } 100 return phone.getImei(); 101 } else { 102 loge("getDeviceId phone is null for Subscription:" + subId); 103 return null; 104 } 105 } 106 107 public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int subId, int keyType, 108 String callingPackage) { 109 Phone phone = getPhone(subId); 110 if (phone != null) { 111 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 112 mContext, subId, callingPackage, 113 "getCarrierInfoForImsiEncryption")) { 114 return null; 115 } 116 return phone.getCarrierInfoForImsiEncryption(keyType); 117 } else { 118 loge("getCarrierInfoForImsiEncryption phone is null for Subscription:" + subId); 119 return null; 120 } 121 } 122 123 public void setCarrierInfoForImsiEncryption(int subId, String callingPackage, 124 ImsiEncryptionInfo imsiEncryptionInfo) { 125 Phone phone = getPhone(subId); 126 if (phone != null) { 127 enforceModifyPermission(); 128 phone.setCarrierInfoForImsiEncryption(imsiEncryptionInfo); 129 } else { 130 loge("setCarrierInfoForImsiEncryption phone is null for Subscription:" + subId); 131 return; 132 } 133 } 134 135 /** 136 * Resets the Carrier Keys in the database. This involves 2 steps: 137 * 1. Delete the keys from the database. 138 * 2. Send an intent to download new Certificates. 139 * @param subId 140 * @param callingPackage 141 */ 142 public void resetCarrierKeysForImsiEncryption(int subId, String callingPackage) { 143 Phone phone = getPhone(subId); 144 if (phone != null) { 145 enforceModifyPermission(); 146 phone.resetCarrierKeysForImsiEncryption(); 147 return; 148 } else { 149 loge("resetCarrierKeysForImsiEncryption phone is null for Subscription:" + subId); 150 return; 151 } 152 } 153 154 155 public String getDeviceSvn(String callingPackage) { 156 return getDeviceSvnUsingSubId(getDefaultSubscription(), callingPackage); 157 } 158 159 public String getDeviceSvnUsingSubId(int subId, String callingPackage) { 160 Phone phone = getPhone(subId); 161 if (phone != null) { 162 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 163 mContext, subId, callingPackage, "getDeviceSvn")) { 164 return null; 165 } 166 return phone.getDeviceSvn(); 167 } else { 168 loge("getDeviceSvn phone is null"); 169 return null; 170 } 171 } 172 173 public String getSubscriberId(String callingPackage) { 174 return getSubscriberIdForSubscriber(getDefaultSubscription(), callingPackage); 175 } 176 177 public String getSubscriberIdForSubscriber(int subId, String callingPackage) { 178 Phone phone = getPhone(subId); 179 if (phone != null) { 180 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 181 mContext, subId, callingPackage, "getSubscriberId")) { 182 return null; 183 } 184 return phone.getSubscriberId(); 185 } else { 186 loge("getSubscriberId phone is null for Subscription:" + subId); 187 return null; 188 } 189 } 190 191 /** 192 * Retrieves the serial number of the ICC, if applicable. 193 */ 194 public String getIccSerialNumber(String callingPackage) { 195 return getIccSerialNumberForSubscriber(getDefaultSubscription(), callingPackage); 196 } 197 198 public String getIccSerialNumberForSubscriber(int subId, String callingPackage) { 199 Phone phone = getPhone(subId); 200 if (phone != null) { 201 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 202 mContext, subId, callingPackage, "getIccSerialNumber")) { 203 return null; 204 } 205 return phone.getIccSerialNumber(); 206 } else { 207 loge("getIccSerialNumber phone is null for Subscription:" + subId); 208 return null; 209 } 210 } 211 212 public String getLine1Number(String callingPackage) { 213 return getLine1NumberForSubscriber(getDefaultSubscription(), callingPackage); 214 } 215 216 public String getLine1NumberForSubscriber(int subId, String callingPackage) { 217 Phone phone = getPhone(subId); 218 if (phone != null) { 219 // This is open to apps with WRITE_SMS. 220 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneNumber( 221 mContext, subId, callingPackage, "getLine1Number")) { 222 return null; 223 } 224 return phone.getLine1Number(); 225 } else { 226 loge("getLine1Number phone is null for Subscription:" + subId); 227 return null; 228 } 229 } 230 231 public String getLine1AlphaTag(String callingPackage) { 232 return getLine1AlphaTagForSubscriber(getDefaultSubscription(), callingPackage); 233 } 234 235 public String getLine1AlphaTagForSubscriber(int subId, String callingPackage) { 236 Phone phone = getPhone(subId); 237 if (phone != null) { 238 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 239 mContext, subId, callingPackage, "getLine1AlphaTag")) { 240 return null; 241 } 242 return phone.getLine1AlphaTag(); 243 } else { 244 loge("getLine1AlphaTag phone is null for Subscription:" + subId); 245 return null; 246 } 247 } 248 249 public String getMsisdn(String callingPackage) { 250 return getMsisdnForSubscriber(getDefaultSubscription(), callingPackage); 251 } 252 253 public String getMsisdnForSubscriber(int subId, String callingPackage) { 254 Phone phone = getPhone(subId); 255 if (phone != null) { 256 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 257 mContext, subId, callingPackage, "getMsisdn")) { 258 return null; 259 } 260 return phone.getMsisdn(); 261 } else { 262 loge("getMsisdn phone is null for Subscription:" + subId); 263 return null; 264 } 265 } 266 267 public String getVoiceMailNumber(String callingPackage) { 268 return getVoiceMailNumberForSubscriber(getDefaultSubscription(), callingPackage); 269 } 270 271 public String getVoiceMailNumberForSubscriber(int subId, String callingPackage) { 272 Phone phone = getPhone(subId); 273 if (phone != null) { 274 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 275 mContext, subId, callingPackage, "getVoiceMailNumber")) { 276 return null; 277 } 278 String number = PhoneNumberUtils.extractNetworkPortion(phone.getVoiceMailNumber()); 279 if (VDBG) log("VM: getVoiceMailNUmber: " + number); 280 return number; 281 } else { 282 loge("getVoiceMailNumber phone is null for Subscription:" + subId); 283 return null; 284 } 285 } 286 287 // TODO: change getCompleteVoiceMailNumber() to require READ_PRIVILEGED_PHONE_STATE 288 public String getCompleteVoiceMailNumber() { 289 return getCompleteVoiceMailNumberForSubscriber(getDefaultSubscription()); 290 } 291 292 public String getCompleteVoiceMailNumberForSubscriber(int subId) { 293 Phone phone = getPhone(subId); 294 if (phone != null) { 295 mContext.enforceCallingOrSelfPermission(CALL_PRIVILEGED, "Requires CALL_PRIVILEGED"); 296 String number = phone.getVoiceMailNumber(); 297 if (VDBG) log("VM: getCompleteVoiceMailNUmber: " + number); 298 return number; 299 } else { 300 loge("getCompleteVoiceMailNumber phone is null for Subscription:" + subId); 301 return null; 302 } 303 } 304 305 public String getVoiceMailAlphaTag(String callingPackage) { 306 return getVoiceMailAlphaTagForSubscriber(getDefaultSubscription(), callingPackage); 307 } 308 309 public String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage) { 310 Phone phone = getPhone(subId); 311 if (phone != null) { 312 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 313 mContext, subId, callingPackage, "getVoiceMailAlphaTag")) { 314 return null; 315 } 316 return phone.getVoiceMailAlphaTag(); 317 } else { 318 loge("getVoiceMailAlphaTag phone is null for Subscription:" + subId); 319 return null; 320 } 321 } 322 323 /** 324 * get Phone object based on subId. 325 **/ 326 private Phone getPhone(int subId) { 327 int phoneId = SubscriptionManager.getPhoneId(subId); 328 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 329 phoneId = 0; 330 } 331 return mPhone[phoneId]; 332 } 333 334 /** 335 * Make sure caller has either read privileged phone permission or carrier privilege. 336 * 337 * @throws SecurityException if the caller does not have the required permission/privilege 338 */ 339 private void enforcePrivilegedPermissionOrCarrierPrivilege(int subId, String message) { 340 int permissionResult = mContext.checkCallingOrSelfPermission( 341 READ_PRIVILEGED_PHONE_STATE); 342 if (permissionResult == PackageManager.PERMISSION_GRANTED) { 343 return; 344 } 345 if (VDBG) log("No read privileged phone permission, check carrier privilege next."); 346 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(subId, message); 347 } 348 349 /** 350 * Make sure caller has modify phone state permission. 351 */ 352 private void enforceModifyPermission() { 353 mContext.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, 354 "Requires MODIFY_PHONE_STATE"); 355 } 356 357 private int getDefaultSubscription() { 358 return PhoneFactory.getDefaultSubscription(); 359 } 360 361 362 /** 363 * get the Isim Impi based on subId 364 */ 365 public String getIsimImpi(int subId) { 366 Phone phone = getPhone(subId); 367 if (phone != null) { 368 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, 369 "Requires READ_PRIVILEGED_PHONE_STATE"); 370 IsimRecords isim = phone.getIsimRecords(); 371 if (isim != null) { 372 return isim.getIsimImpi(); 373 } else { 374 return null; 375 } 376 } else { 377 loge("getIsimImpi phone is null for Subscription:" + subId); 378 return null; 379 } 380 } 381 382 /** 383 * get the Isim Domain based on subId 384 */ 385 public String getIsimDomain(int subId) { 386 Phone phone = getPhone(subId); 387 if (phone != null) { 388 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, 389 "Requires READ_PRIVILEGED_PHONE_STATE"); 390 IsimRecords isim = phone.getIsimRecords(); 391 if (isim != null) { 392 return isim.getIsimDomain(); 393 } else { 394 return null; 395 } 396 } else { 397 loge("getIsimDomain phone is null for Subscription:" + subId); 398 return null; 399 } 400 } 401 402 /** 403 * get the Isim Impu based on subId 404 */ 405 public String[] getIsimImpu(int subId) { 406 Phone phone = getPhone(subId); 407 if (phone != null) { 408 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, 409 "Requires READ_PRIVILEGED_PHONE_STATE"); 410 IsimRecords isim = phone.getIsimRecords(); 411 if (isim != null) { 412 return isim.getIsimImpu(); 413 } else { 414 return null; 415 } 416 } else { 417 loge("getIsimImpu phone is null for Subscription:" + subId); 418 return null; 419 } 420 } 421 422 /** 423 * get the Isim Ist based on subId 424 */ 425 public String getIsimIst(int subId) throws RemoteException { 426 Phone phone = getPhone(subId); 427 if (phone != null) { 428 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, 429 "Requires READ_PRIVILEGED_PHONE_STATE"); 430 IsimRecords isim = phone.getIsimRecords(); 431 if (isim != null) { 432 return isim.getIsimIst(); 433 } else { 434 return null; 435 } 436 } else { 437 loge("getIsimIst phone is null for Subscription:" + subId); 438 return null; 439 } 440 } 441 442 /** 443 * get the Isim Pcscf based on subId 444 */ 445 public String[] getIsimPcscf(int subId) throws RemoteException { 446 Phone phone = getPhone(subId); 447 if (phone != null) { 448 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, 449 "Requires READ_PRIVILEGED_PHONE_STATE"); 450 IsimRecords isim = phone.getIsimRecords(); 451 if (isim != null) { 452 return isim.getIsimPcscf(); 453 } else { 454 return null; 455 } 456 } else { 457 loge("getIsimPcscf phone is null for Subscription:" + subId); 458 return null; 459 } 460 } 461 462 public String getIccSimChallengeResponse(int subId, int appType, int authType, String data) 463 throws RemoteException { 464 // TODO(b/73660190): Migrate to 465 // TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivileges and delete 466 // this helper method. 467 enforcePrivilegedPermissionOrCarrierPrivilege(subId, "getIccSimChallengeResponse"); 468 Phone phone = getPhone(subId); 469 UiccCard uiccCard = phone.getUiccCard(); 470 if (uiccCard == null) { 471 loge("getIccSimChallengeResponse() UiccCard is null"); 472 return null; 473 } 474 475 UiccCardApplication uiccApp = uiccCard.getApplicationByType(appType); 476 if (uiccApp == null) { 477 loge("getIccSimChallengeResponse() no app with specified type -- " + 478 appType); 479 return null; 480 } else { 481 loge("getIccSimChallengeResponse() found app " + uiccApp.getAid() 482 + " specified type -- " + appType); 483 } 484 485 if(authType != UiccCardApplication.AUTH_CONTEXT_EAP_SIM && 486 authType != UiccCardApplication.AUTH_CONTEXT_EAP_AKA) { 487 loge("getIccSimChallengeResponse() unsupported authType: " + authType); 488 return null; 489 } 490 491 return uiccApp.getIccRecords().getIccSimChallengeResponse(authType, data); 492 } 493 494 public String getGroupIdLevel1ForSubscriber(int subId, String callingPackage) { 495 Phone phone = getPhone(subId); 496 if (phone != null) { 497 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( 498 mContext, subId, callingPackage, "getGroupIdLevel1")) { 499 return null; 500 } 501 return phone.getGroupIdLevel1(); 502 } else { 503 loge("getGroupIdLevel1 phone is null for Subscription:" + subId); 504 return null; 505 } 506 } 507 508 private void log(String s) { 509 Rlog.d(TAG, s); 510 } 511 512 private void loge(String s) { 513 Rlog.e(TAG, s); 514 } 515 } 516