1 /* 2 * Copyright (C) 2007 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 package com.android.internal.telephony; 17 18 import java.io.FileDescriptor; 19 import java.io.PrintWriter; 20 21 import android.content.Context; 22 import android.content.pm.PackageManager; 23 import android.os.Binder; 24 import android.os.RemoteException; 25 import android.telephony.PhoneNumberUtils; 26 import android.telephony.Rlog; 27 28 import com.android.internal.telephony.uicc.IsimRecords; 29 import com.android.internal.telephony.uicc.UiccCard; 30 import com.android.internal.telephony.uicc.UiccCardApplication; 31 32 public class PhoneSubInfo { 33 static final String LOG_TAG = "PhoneSubInfo"; 34 private static final boolean DBG = true; 35 private static final boolean VDBG = false; // STOPSHIP if true 36 37 private Phone mPhone; 38 private Context mContext; 39 private static final String READ_PHONE_STATE = 40 android.Manifest.permission.READ_PHONE_STATE; 41 // TODO: change getCompleteVoiceMailNumber() to require READ_PRIVILEGED_PHONE_STATE 42 private static final String CALL_PRIVILEGED = 43 android.Manifest.permission.CALL_PRIVILEGED; 44 private static final String READ_PRIVILEGED_PHONE_STATE = 45 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; 46 47 public PhoneSubInfo(Phone phone) { 48 mPhone = phone; 49 mContext = phone.getContext(); 50 } 51 52 public void dispose() { 53 } 54 55 @Override 56 protected void finalize() { 57 try { 58 super.finalize(); 59 } catch (Throwable throwable) { 60 loge("Error while finalizing:", throwable); 61 } 62 if (DBG) log("PhoneSubInfo finalized"); 63 } 64 65 /** 66 * Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones. 67 */ 68 public String getDeviceId() { 69 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); 70 return mPhone.getDeviceId(); 71 } 72 73 /** 74 * Retrieves the IMEI. 75 */ 76 public String getImei() { 77 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); 78 return mPhone.getImei(); 79 } 80 81 /** 82 * Retrieves the software version number for the device, e.g., IMEI/SV 83 * for GSM phones. 84 */ 85 public String getDeviceSvn() { 86 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); 87 return mPhone.getDeviceSvn(); 88 } 89 90 /** 91 * Retrieves the unique subscriber ID, e.g., IMSI for GSM phones. 92 */ 93 public String getSubscriberId() { 94 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); 95 return mPhone.getSubscriberId(); 96 } 97 98 /** 99 * Retrieves the Group Identifier Level1 for GSM phones. 100 */ 101 public String getGroupIdLevel1() { 102 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); 103 return mPhone.getGroupIdLevel1(); 104 } 105 106 /** 107 * Retrieves the serial number of the ICC, if applicable. 108 */ 109 public String getIccSerialNumber() { 110 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); 111 return mPhone.getIccSerialNumber(); 112 } 113 114 /** 115 * Retrieves the phone number string for line 1. 116 */ 117 public String getLine1Number() { 118 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); 119 return mPhone.getLine1Number(); 120 } 121 122 /** 123 * Retrieves the alpha identifier for line 1. 124 */ 125 public String getLine1AlphaTag() { 126 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); 127 return mPhone.getLine1AlphaTag(); 128 } 129 130 /** 131 * Retrieves the MSISDN string. 132 */ 133 public String getMsisdn() { 134 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); 135 return mPhone.getMsisdn(); 136 } 137 138 /** 139 * Retrieves the voice mail number. 140 */ 141 public String getVoiceMailNumber() { 142 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); 143 String number = PhoneNumberUtils.extractNetworkPortion(mPhone.getVoiceMailNumber()); 144 if (VDBG) log("VM: PhoneSubInfo.getVoiceMailNUmber: " + number); 145 return number; 146 } 147 148 /** 149 * Retrieves the complete voice mail number. 150 * 151 * @hide 152 */ 153 public String getCompleteVoiceMailNumber() { 154 mContext.enforceCallingOrSelfPermission(CALL_PRIVILEGED, 155 "Requires CALL_PRIVILEGED"); 156 String number = mPhone.getVoiceMailNumber(); 157 if (VDBG) log("VM: PhoneSubInfo.getCompleteVoiceMailNUmber: " + number); 158 return number; 159 } 160 161 /** 162 * Retrieves the alpha identifier associated with the voice mail number. 163 */ 164 public String getVoiceMailAlphaTag() { 165 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); 166 return mPhone.getVoiceMailAlphaTag(); 167 } 168 169 /** 170 * Returns the IMS private user identity (IMPI) that was loaded from the ISIM. 171 * @return the IMPI, or null if not present or not loaded 172 */ 173 public String getIsimImpi() { 174 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, 175 "Requires READ_PRIVILEGED_PHONE_STATE"); 176 IsimRecords isim = mPhone.getIsimRecords(); 177 if (isim != null) { 178 return isim.getIsimImpi(); 179 } else { 180 return null; 181 } 182 } 183 184 /** 185 * Returns the IMS home network domain name that was loaded from the ISIM. 186 * @return the IMS domain name, or null if not present or not loaded 187 */ 188 public String getIsimDomain() { 189 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, 190 "Requires READ_PRIVILEGED_PHONE_STATE"); 191 IsimRecords isim = mPhone.getIsimRecords(); 192 if (isim != null) { 193 return isim.getIsimDomain(); 194 } else { 195 return null; 196 } 197 } 198 199 /** 200 * Returns the IMS public user identities (IMPU) that were loaded from the ISIM. 201 * @return an array of IMPU strings, with one IMPU per string, or null if 202 * not present or not loaded 203 */ 204 public String[] getIsimImpu() { 205 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, 206 "Requires READ_PRIVILEGED_PHONE_STATE"); 207 IsimRecords isim = mPhone.getIsimRecords(); 208 if (isim != null) { 209 return isim.getIsimImpu(); 210 } else { 211 return null; 212 } 213 } 214 215 /** 216 * Returns the IMS Service Table (IST) that was loaded from the ISIM. 217 * @return IMS Service Table or null if not present or not loaded 218 */ 219 public String getIsimIst(){ 220 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, 221 "Requires READ_PRIVILEGED_PHONE_STATE"); 222 IsimRecords isim = mPhone.getIsimRecords(); 223 if (isim != null) { 224 return isim.getIsimIst(); 225 } else { 226 return null; 227 } 228 } 229 230 /** 231 * Returns the IMS Proxy Call Session Control Function(PCSCF) that were loaded from the ISIM. 232 * @return an array of PCSCF strings with one PCSCF per string, or null if 233 * not present or not loaded 234 */ 235 public String[] getIsimPcscf() { 236 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, 237 "Requires READ_PRIVILEGED_PHONE_STATE"); 238 IsimRecords isim = mPhone.getIsimRecords(); 239 if (isim != null) { 240 return isim.getIsimPcscf(); 241 } else { 242 return null; 243 } 244 } 245 246 /** 247 * Returns the response of ISIM Authetification through RIL. 248 * Returns null if the Authentification hasn't been successed or isn't present iphonesubinfo. 249 * @return the response of ISIM Authetification, or null if not available 250 */ 251 public String getIsimChallengeResponse(String nonce){ 252 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, 253 "Requires READ_PRIVILEGED_PHONE_STATE"); 254 IsimRecords isim = mPhone.getIsimRecords(); 255 if (isim != null) { 256 return isim.getIsimChallengeResponse(nonce); 257 } else { 258 return null; 259 } 260 } 261 262 /** 263 * Returns the response of the SIM application on the UICC to authentication 264 * challenge/response algorithm. The data string and challenge response are 265 * Base64 encoded Strings. 266 * Can support EAP-SIM, EAP-AKA with results encoded per 3GPP TS 31.102. 267 * 268 * @param appType ICC application family (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx) 269 * @param data authentication challenge data 270 * @return challenge response 271 */ 272 public String getIccSimChallengeResponse(long subId, int appType, String data) { 273 // FIXME: use subId!! 274 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, 275 "Requires READ_PRIVILEGED_PHONE_STATE"); 276 277 UiccCard uiccCard = mPhone.getUiccCard(); 278 if (uiccCard == null) { 279 Rlog.e(LOG_TAG, "getIccSimChallengeResponse() UiccCard is null"); 280 return null; 281 } 282 283 UiccCardApplication uiccApp = uiccCard.getApplicationByType(appType); 284 if (uiccApp == null) { 285 Rlog.e(LOG_TAG, "getIccSimChallengeResponse() no app with specified type -- " + 286 appType); 287 return null; 288 } else { 289 Rlog.e(LOG_TAG, "getIccSimChallengeResponse() found app " + uiccApp.getAid() 290 + "specified type -- " + appType); 291 } 292 293 int authContext = uiccApp.getAuthContext(); 294 295 if (data.length() < 32) { 296 /* must use EAP_SIM context */ 297 Rlog.e(LOG_TAG, "data is too small to use EAP_AKA, using EAP_SIM instead"); 298 authContext = UiccCardApplication.AUTH_CONTEXT_EAP_SIM; 299 } 300 301 if(authContext == UiccCardApplication.AUTH_CONTEXT_UNDEFINED) { 302 Rlog.e(LOG_TAG, "getIccSimChallengeResponse() authContext undefined for app type " + 303 appType); 304 return null; 305 } 306 307 return uiccApp.getIccRecords().getIccSimChallengeResponse(authContext, data); 308 } 309 310 private void log(String s) { 311 Rlog.d(LOG_TAG, s); 312 } 313 314 private void loge(String s, Throwable e) { 315 Rlog.e(LOG_TAG, s, e); 316 } 317 318 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 319 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 320 != PackageManager.PERMISSION_GRANTED) { 321 pw.println("Permission Denial: can't dump PhoneSubInfo from from pid=" 322 + Binder.getCallingPid() 323 + ", uid=" + Binder.getCallingUid()); 324 return; 325 } 326 327 pw.println("Phone Subscriber Info:"); 328 pw.println(" Phone Type = " + mPhone.getPhoneName()); 329 pw.println(" Device ID = " + mPhone.getDeviceId()); 330 } 331 } 332