1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import android.content.Context; 20 import android.os.AsyncResult; 21 import android.os.Handler; 22 import android.os.Message; 23 import android.os.Registrant; 24 import android.os.RegistrantList; 25 26 import com.android.internal.telephony.gsm.UsimServiceTable; 27 import com.android.internal.telephony.ims.IsimRecords; 28 29 /** 30 * {@hide} 31 */ 32 public abstract class IccRecords extends Handler implements IccConstants { 33 34 protected static final boolean DBG = true; 35 // ***** Instance Variables 36 protected boolean mDestroyed = false; // set to true once this object needs to be disposed of 37 protected Context mContext; 38 protected CommandsInterface mCi; 39 protected IccFileHandler mFh; 40 protected IccCard mParentCard; 41 42 protected RegistrantList recordsLoadedRegistrants = new RegistrantList(); 43 protected RegistrantList mRecordsEventsRegistrants = new RegistrantList(); 44 protected RegistrantList mNewSmsRegistrants = new RegistrantList(); 45 protected RegistrantList mNetworkSelectionModeAutomaticRegistrants = new RegistrantList(); 46 47 protected int recordsToLoad; // number of pending load requests 48 49 protected AdnRecordCache adnCache; 50 51 // ***** Cached SIM State; cleared on channel close 52 53 protected boolean recordsRequested = false; // true if we've made requests for the sim records 54 55 public String iccid; 56 protected String msisdn = null; // My mobile number 57 protected String msisdnTag = null; 58 protected String voiceMailNum = null; 59 protected String voiceMailTag = null; 60 protected String newVoiceMailNum = null; 61 protected String newVoiceMailTag = null; 62 protected boolean isVoiceMailFixed = false; 63 protected int countVoiceMessages = 0; 64 65 protected int mncLength = UNINITIALIZED; 66 protected int mailboxIndex = 0; // 0 is no mailbox dailing number associated 67 68 protected String spn; 69 70 // ***** Constants 71 72 // Markers for mncLength 73 protected static final int UNINITIALIZED = -1; 74 protected static final int UNKNOWN = 0; 75 76 // Bitmasks for SPN display rules. 77 protected static final int SPN_RULE_SHOW_SPN = 0x01; 78 protected static final int SPN_RULE_SHOW_PLMN = 0x02; 79 80 // ***** Event Constants 81 protected static final int EVENT_SET_MSISDN_DONE = 30; 82 public static final int EVENT_MWI = 0; 83 public static final int EVENT_CFI = 1; 84 public static final int EVENT_SPN = 2; 85 86 public static final int EVENT_GET_ICC_RECORD_DONE = 100; 87 88 /** 89 * Generic ICC record loaded callback. Subclasses can call EF load methods on 90 * {@link IccFileHandler} passing a Message for onLoaded with the what field set to 91 * {@link #EVENT_GET_ICC_RECORD_DONE} and the obj field set to an instance 92 * of this interface. The {@link #handleMessage} method in this class will print a 93 * log message using {@link #getEfName()} and decrement {@link #recordsToLoad}. 94 * 95 * If the record load was successful, {@link #onRecordLoaded} will be called with the result. 96 * Otherwise, an error log message will be output by {@link #handleMessage} and 97 * {@link #onRecordLoaded} will not be called. 98 */ 99 public interface IccRecordLoaded { 100 String getEfName(); 101 void onRecordLoaded(AsyncResult ar); 102 } 103 104 // ***** Constructor 105 public IccRecords(IccCard card, Context c, CommandsInterface ci) { 106 mContext = c; 107 mCi = ci; 108 mFh = card.getIccFileHandler(); 109 mParentCard = card; 110 } 111 112 /** 113 * Call when the IccRecords object is no longer going to be used. 114 */ 115 public void dispose() { 116 mDestroyed = true; 117 mParentCard = null; 118 mFh = null; 119 mCi = null; 120 mContext = null; 121 } 122 123 protected abstract void onRadioOffOrNotAvailable(); 124 public abstract void onReady(); 125 126 //***** Public Methods 127 public AdnRecordCache getAdnCache() { 128 return adnCache; 129 } 130 131 public IccCard getIccCard() { 132 return mParentCard; 133 } 134 135 public void registerForRecordsLoaded(Handler h, int what, Object obj) { 136 if (mDestroyed) { 137 return; 138 } 139 140 Registrant r = new Registrant(h, what, obj); 141 recordsLoadedRegistrants.add(r); 142 143 if (recordsToLoad == 0 && recordsRequested == true) { 144 r.notifyRegistrant(new AsyncResult(null, null, null)); 145 } 146 } 147 public void unregisterForRecordsLoaded(Handler h) { 148 recordsLoadedRegistrants.remove(h); 149 } 150 151 public void registerForRecordsEvents(Handler h, int what, Object obj) { 152 Registrant r = new Registrant (h, what, obj); 153 mRecordsEventsRegistrants.add(r); 154 } 155 public void unregisterForRecordsEvents(Handler h) { 156 mRecordsEventsRegistrants.remove(h); 157 } 158 159 public void registerForNewSms(Handler h, int what, Object obj) { 160 Registrant r = new Registrant (h, what, obj); 161 mNewSmsRegistrants.add(r); 162 } 163 public void unregisterForNewSms(Handler h) { 164 mNewSmsRegistrants.remove(h); 165 } 166 167 public void registerForNetworkSelectionModeAutomatic( 168 Handler h, int what, Object obj) { 169 Registrant r = new Registrant (h, what, obj); 170 mNetworkSelectionModeAutomaticRegistrants.add(r); 171 } 172 public void unregisterForNetworkSelectionModeAutomatic(Handler h) { 173 mNetworkSelectionModeAutomaticRegistrants.remove(h); 174 } 175 176 /** 177 * Get the International Mobile Subscriber ID (IMSI) on a SIM 178 * for GSM, UMTS and like networks. Default is null if IMSI is 179 * not supported or unavailable. 180 * 181 * @return null if SIM is not yet ready or unavailable 182 */ 183 public String getIMSI() { 184 return null; 185 } 186 187 public String getMsisdnNumber() { 188 return msisdn; 189 } 190 191 /** 192 * Set subscriber number to SIM record 193 * 194 * The subscriber number is stored in EF_MSISDN (TS 51.011) 195 * 196 * When the operation is complete, onComplete will be sent to its handler 197 * 198 * @param alphaTag alpha-tagging of the dailing nubmer (up to 10 characters) 199 * @param number dailing nubmer (up to 20 digits) 200 * if the number starts with '+', then set to international TOA 201 * @param onComplete 202 * onComplete.obj will be an AsyncResult 203 * ((AsyncResult)onComplete.obj).exception == null on success 204 * ((AsyncResult)onComplete.obj).exception != null on fail 205 */ 206 public void setMsisdnNumber(String alphaTag, String number, 207 Message onComplete) { 208 209 msisdn = number; 210 msisdnTag = alphaTag; 211 212 if(DBG) log("Set MSISDN: " + msisdnTag +" " + msisdn); 213 214 215 AdnRecord adn = new AdnRecord(msisdnTag, msisdn); 216 217 new AdnRecordLoader(mFh).updateEF(adn, EF_MSISDN, EF_EXT1, 1, null, 218 obtainMessage(EVENT_SET_MSISDN_DONE, onComplete)); 219 } 220 221 public String getMsisdnAlphaTag() { 222 return msisdnTag; 223 } 224 225 public String getVoiceMailNumber() { 226 return voiceMailNum; 227 } 228 229 /** 230 * Return Service Provider Name stored in SIM (EF_SPN=0x6F46) or in RUIM (EF_RUIM_SPN=0x6F41) 231 * @return null if SIM is not yet ready or no RUIM entry 232 */ 233 public String getServiceProviderName() { 234 return spn; 235 } 236 237 /** 238 * Set voice mail number to SIM record 239 * 240 * The voice mail number can be stored either in EF_MBDN (TS 51.011) or 241 * EF_MAILBOX_CPHS (CPHS 4.2) 242 * 243 * If EF_MBDN is available, store the voice mail number to EF_MBDN 244 * 245 * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS 246 * 247 * So the voice mail number will be stored in both EFs if both are available 248 * 249 * Return error only if both EF_MBDN and EF_MAILBOX_CPHS fail. 250 * 251 * When the operation is complete, onComplete will be sent to its handler 252 * 253 * @param alphaTag alpha-tagging of the dailing nubmer (upto 10 characters) 254 * @param voiceNumber dailing nubmer (upto 20 digits) 255 * if the number is start with '+', then set to international TOA 256 * @param onComplete 257 * onComplete.obj will be an AsyncResult 258 * ((AsyncResult)onComplete.obj).exception == null on success 259 * ((AsyncResult)onComplete.obj).exception != null on fail 260 */ 261 public abstract void setVoiceMailNumber(String alphaTag, String voiceNumber, 262 Message onComplete); 263 264 public String getVoiceMailAlphaTag() { 265 return voiceMailTag; 266 } 267 268 /** 269 * Sets the SIM voice message waiting indicator records 270 * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported 271 * @param countWaiting The number of messages waiting, if known. Use 272 * -1 to indicate that an unknown number of 273 * messages are waiting 274 */ 275 public abstract void setVoiceMessageWaiting(int line, int countWaiting); 276 277 /** @return true if there are messages waiting, false otherwise. */ 278 public boolean getVoiceMessageWaiting() { 279 return countVoiceMessages != 0; 280 } 281 282 /** 283 * Returns number of voice messages waiting, if available 284 * If not available (eg, on an older CPHS SIM) -1 is returned if 285 * getVoiceMessageWaiting() is true 286 */ 287 public int getVoiceMessageCount() { 288 return countVoiceMessages; 289 } 290 291 /** 292 * Called by STK Service when REFRESH is received. 293 * @param fileChanged indicates whether any files changed 294 * @param fileList if non-null, a list of EF files that changed 295 */ 296 public abstract void onRefresh(boolean fileChanged, int[] fileList); 297 298 299 public boolean getRecordsLoaded() { 300 if (recordsToLoad == 0 && recordsRequested == true) { 301 return true; 302 } else { 303 return false; 304 } 305 } 306 307 //***** Overridden from Handler 308 @Override 309 public void handleMessage(Message msg) { 310 switch (msg.what) { 311 case EVENT_GET_ICC_RECORD_DONE: 312 try { 313 AsyncResult ar = (AsyncResult) msg.obj; 314 IccRecordLoaded recordLoaded = (IccRecordLoaded) ar.userObj; 315 if (DBG) log(recordLoaded.getEfName() + " LOADED"); 316 317 if (ar.exception != null) { 318 loge("Record Load Exception: " + ar.exception); 319 } else { 320 recordLoaded.onRecordLoaded(ar); 321 } 322 }catch (RuntimeException exc) { 323 // I don't want these exceptions to be fatal 324 loge("Exception parsing SIM record: " + exc); 325 } finally { 326 // Count up record load responses even if they are fails 327 onRecordLoaded(); 328 } 329 break; 330 331 default: 332 super.handleMessage(msg); 333 } 334 } 335 336 protected abstract void onRecordLoaded(); 337 338 protected abstract void onAllRecordsLoaded(); 339 340 /** 341 * Returns the SpnDisplayRule based on settings on the SIM and the 342 * specified plmn (currently-registered PLMN). See TS 22.101 Annex A 343 * and TS 51.011 10.3.11 for details. 344 * 345 * If the SPN is not found on the SIM, the rule is always PLMN_ONLY. 346 * Generally used for GSM/UMTS and the like SIMs. 347 */ 348 public abstract int getDisplayRule(String plmn); 349 350 /** 351 * Return true if "Restriction of menu options for manual PLMN selection" 352 * bit is set or EF_CSP data is unavailable, return false otherwise. 353 * Generally used for GSM/UMTS and the like SIMs. 354 */ 355 public boolean isCspPlmnEnabled() { 356 return false; 357 } 358 359 /** 360 * Returns the 5 or 6 digit MCC/MNC of the operator that 361 * provided the SIM card. Returns null of SIM is not yet ready 362 * or is not valid for the type of IccCard. Generally used for 363 * GSM/UMTS and the like SIMS 364 */ 365 public String getOperatorNumeric() { 366 return null; 367 } 368 369 /** 370 * Get the current Voice call forwarding flag for GSM/UMTS and the like SIMs 371 * 372 * @return true if enabled 373 */ 374 public boolean getVoiceCallForwardingFlag() { 375 return false; 376 } 377 378 /** 379 * Set the voice call forwarding flag for GSM/UMTS and the like SIMs 380 * 381 * @param line to enable/disable 382 * @param enable 383 */ 384 public void setVoiceCallForwardingFlag(int line, boolean enable) { 385 } 386 387 /** 388 * Indicates wether SIM is in provisioned state or not. 389 * Overridden only if SIM can be dynamically provisioned via OTA. 390 * 391 * @return true if provisioned 392 */ 393 public boolean isProvisioned () { 394 return true; 395 } 396 397 /** 398 * Write string to log file 399 * 400 * @param s is the string to write 401 */ 402 protected abstract void log(String s); 403 404 /** 405 * Write error string to log file. 406 * 407 * @param s is the string to write 408 */ 409 protected abstract void loge(String s); 410 411 /** 412 * Return an interface to retrieve the ISIM records for IMS, if available. 413 * @return the interface to retrieve the ISIM records, or null if not supported 414 */ 415 public IsimRecords getIsimRecords() { 416 return null; 417 } 418 419 public UsimServiceTable getUsimServiceTable() { 420 return null; 421 } 422 } 423