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