Home | History | Annotate | Download | only in uicc
      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.uicc;
     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.CommandsInterface;
     27 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
     28 
     29 import java.io.FileDescriptor;
     30 import java.io.PrintWriter;
     31 import java.util.concurrent.atomic.AtomicBoolean;
     32 
     33 /**
     34  * {@hide}
     35  */
     36 public abstract class IccRecords extends Handler implements IccConstants {
     37     protected static final boolean DBG = true;
     38 
     39     // ***** Instance Variables
     40     protected AtomicBoolean mDestroyed = new AtomicBoolean(false);
     41     protected Context mContext;
     42     protected CommandsInterface mCi;
     43     protected IccFileHandler mFh;
     44     protected UiccCardApplication mParentApp;
     45 
     46     protected RegistrantList mRecordsLoadedRegistrants = new RegistrantList();
     47     protected RegistrantList mImsiReadyRegistrants = new RegistrantList();
     48     protected RegistrantList mRecordsEventsRegistrants = new RegistrantList();
     49     protected RegistrantList mNewSmsRegistrants = new RegistrantList();
     50     protected RegistrantList mNetworkSelectionModeAutomaticRegistrants = new RegistrantList();
     51 
     52     protected int mRecordsToLoad;  // number of pending load requests
     53 
     54     protected AdnRecordCache mAdnCache;
     55 
     56     // ***** Cached SIM State; cleared on channel close
     57 
     58     protected boolean mRecordsRequested = false; // true if we've made requests for the sim records
     59 
     60     protected String mIccId;
     61     protected String mMsisdn = null;  // My mobile number
     62     protected String mMsisdnTag = null;
     63     protected String mVoiceMailNum = null;
     64     protected String mVoiceMailTag = null;
     65     protected String mNewVoiceMailNum = null;
     66     protected String mNewVoiceMailTag = null;
     67     protected boolean mIsVoiceMailFixed = false;
     68     protected int mCountVoiceMessages = 0;
     69     protected String mImsi;
     70     private IccIoResult auth_rsp;
     71 
     72     protected int mMncLength = UNINITIALIZED;
     73     protected int mMailboxIndex = 0; // 0 is no mailbox dailing number associated
     74 
     75     private String mSpn;
     76 
     77     protected String mGid1;
     78 
     79     private final Object mLock = new Object();
     80 
     81     // ***** Constants
     82 
     83     // Markers for mncLength
     84     protected static final int UNINITIALIZED = -1;
     85     protected static final int UNKNOWN = 0;
     86 
     87     // Bitmasks for SPN display rules.
     88     public static final int SPN_RULE_SHOW_SPN  = 0x01;
     89     public static final int SPN_RULE_SHOW_PLMN = 0x02;
     90 
     91     // ***** Event Constants
     92     protected static final int EVENT_SET_MSISDN_DONE = 30;
     93     public static final int EVENT_MWI = 0; // Message Waiting indication
     94     public static final int EVENT_CFI = 1; // Call Forwarding indication
     95     public static final int EVENT_SPN = 2; // Service Provider Name
     96 
     97     public static final int EVENT_GET_ICC_RECORD_DONE = 100;
     98     protected static final int EVENT_APP_READY = 1;
     99     private static final int EVENT_AKA_AUTHENTICATE_DONE          = 90;
    100 
    101     @Override
    102     public String toString() {
    103         return "mDestroyed=" + mDestroyed
    104                 + " mContext=" + mContext
    105                 + " mCi=" + mCi
    106                 + " mFh=" + mFh
    107                 + " mParentApp=" + mParentApp
    108                 + " recordsLoadedRegistrants=" + mRecordsLoadedRegistrants
    109                 + " mImsiReadyRegistrants=" + mImsiReadyRegistrants
    110                 + " mRecordsEventsRegistrants=" + mRecordsEventsRegistrants
    111                 + " mNewSmsRegistrants=" + mNewSmsRegistrants
    112                 + " mNetworkSelectionModeAutomaticRegistrants="
    113                         + mNetworkSelectionModeAutomaticRegistrants
    114                 + " recordsToLoad=" + mRecordsToLoad
    115                 + " adnCache=" + mAdnCache
    116                 + " recordsRequested=" + mRecordsRequested
    117                 + " iccid=" + mIccId
    118                 + " msisdn=" + mMsisdn
    119                 + " msisdnTag=" + mMsisdnTag
    120                 + " voiceMailNum=" + mVoiceMailNum
    121                 + " voiceMailTag=" + mVoiceMailTag
    122                 + " newVoiceMailNum=" + mNewVoiceMailNum
    123                 + " newVoiceMailTag=" + mNewVoiceMailTag
    124                 + " isVoiceMailFixed=" + mIsVoiceMailFixed
    125                 + " countVoiceMessages=" + mCountVoiceMessages
    126                 + " mImsi=" + mImsi
    127                 + " mncLength=" + mMncLength
    128                 + " mailboxIndex=" + mMailboxIndex
    129                 + " spn=" + mSpn;
    130 
    131     }
    132 
    133     /**
    134      * Generic ICC record loaded callback. Subclasses can call EF load methods on
    135      * {@link IccFileHandler} passing a Message for onLoaded with the what field set to
    136      * {@link #EVENT_GET_ICC_RECORD_DONE} and the obj field set to an instance
    137      * of this interface. The {@link #handleMessage} method in this class will print a
    138      * log message using {@link #getEfName()} and decrement {@link #mRecordsToLoad}.
    139      *
    140      * If the record load was successful, {@link #onRecordLoaded} will be called with the result.
    141      * Otherwise, an error log message will be output by {@link #handleMessage} and
    142      * {@link #onRecordLoaded} will not be called.
    143      */
    144     public interface IccRecordLoaded {
    145         String getEfName();
    146         void onRecordLoaded(AsyncResult ar);
    147     }
    148 
    149     // ***** Constructor
    150     public IccRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
    151         mContext = c;
    152         mCi = ci;
    153         mFh = app.getIccFileHandler();
    154         mParentApp = app;
    155     }
    156 
    157     /**
    158      * Call when the IccRecords object is no longer going to be used.
    159      */
    160     public void dispose() {
    161         mDestroyed.set(true);
    162         mParentApp = null;
    163         mFh = null;
    164         mCi = null;
    165         mContext = null;
    166     }
    167 
    168     public abstract void onReady();
    169 
    170     //***** Public Methods
    171     public AdnRecordCache getAdnCache() {
    172         return mAdnCache;
    173     }
    174 
    175     public String getIccId() {
    176         return mIccId;
    177     }
    178 
    179     public void registerForRecordsLoaded(Handler h, int what, Object obj) {
    180         if (mDestroyed.get()) {
    181             return;
    182         }
    183 
    184         Registrant r = new Registrant(h, what, obj);
    185         mRecordsLoadedRegistrants.add(r);
    186 
    187         if (mRecordsToLoad == 0 && mRecordsRequested == true) {
    188             r.notifyRegistrant(new AsyncResult(null, null, null));
    189         }
    190     }
    191     public void unregisterForRecordsLoaded(Handler h) {
    192         mRecordsLoadedRegistrants.remove(h);
    193     }
    194 
    195     public void registerForImsiReady(Handler h, int what, Object obj) {
    196         if (mDestroyed.get()) {
    197             return;
    198         }
    199 
    200         Registrant r = new Registrant(h, what, obj);
    201         mImsiReadyRegistrants.add(r);
    202 
    203         if (mImsi != null) {
    204             r.notifyRegistrant(new AsyncResult(null, null, null));
    205         }
    206     }
    207     public void unregisterForImsiReady(Handler h) {
    208         mImsiReadyRegistrants.remove(h);
    209     }
    210 
    211     public void registerForRecordsEvents(Handler h, int what, Object obj) {
    212         Registrant r = new Registrant (h, what, obj);
    213         mRecordsEventsRegistrants.add(r);
    214 
    215         /* Notify registrant of all the possible events. This is to make sure registrant is
    216         notified even if event occurred in the past. */
    217         r.notifyResult(EVENT_MWI);
    218         r.notifyResult(EVENT_CFI);
    219     }
    220     public void unregisterForRecordsEvents(Handler h) {
    221         mRecordsEventsRegistrants.remove(h);
    222     }
    223 
    224     public void registerForNewSms(Handler h, int what, Object obj) {
    225         Registrant r = new Registrant (h, what, obj);
    226         mNewSmsRegistrants.add(r);
    227     }
    228     public void unregisterForNewSms(Handler h) {
    229         mNewSmsRegistrants.remove(h);
    230     }
    231 
    232     public void registerForNetworkSelectionModeAutomatic(
    233             Handler h, int what, Object obj) {
    234         Registrant r = new Registrant (h, what, obj);
    235         mNetworkSelectionModeAutomaticRegistrants.add(r);
    236     }
    237     public void unregisterForNetworkSelectionModeAutomatic(Handler h) {
    238         mNetworkSelectionModeAutomaticRegistrants.remove(h);
    239     }
    240 
    241     /**
    242      * Get the International Mobile Subscriber ID (IMSI) on a SIM
    243      * for GSM, UMTS and like networks. Default is null if IMSI is
    244      * not supported or unavailable.
    245      *
    246      * @return null if SIM is not yet ready or unavailable
    247      */
    248     public String getIMSI() {
    249         return null;
    250     }
    251 
    252     /**
    253      * Imsi could be set by ServiceStateTrackers in case of cdma
    254      * @param imsi
    255      */
    256     public void setImsi(String imsi) {
    257         mImsi = imsi;
    258         mImsiReadyRegistrants.notifyRegistrants();
    259     }
    260 
    261     public String getMsisdnNumber() {
    262         return mMsisdn;
    263     }
    264 
    265     /**
    266      * Get the Group Identifier Level 1 (GID1) on a SIM for GSM.
    267      * @return null if SIM is not yet ready
    268      */
    269     public String getGid1() {
    270         return null;
    271     }
    272 
    273     /**
    274      * Set subscriber number to SIM record
    275      *
    276      * The subscriber number is stored in EF_MSISDN (TS 51.011)
    277      *
    278      * When the operation is complete, onComplete will be sent to its handler
    279      *
    280      * @param alphaTag alpha-tagging of the dailing nubmer (up to 10 characters)
    281      * @param number dailing nubmer (up to 20 digits)
    282      *        if the number starts with '+', then set to international TOA
    283      * @param onComplete
    284      *        onComplete.obj will be an AsyncResult
    285      *        ((AsyncResult)onComplete.obj).exception == null on success
    286      *        ((AsyncResult)onComplete.obj).exception != null on fail
    287      */
    288     public void setMsisdnNumber(String alphaTag, String number,
    289             Message onComplete) {
    290 
    291         mMsisdn = number;
    292         mMsisdnTag = alphaTag;
    293 
    294         if (DBG) log("Set MSISDN: " + mMsisdnTag +" " + mMsisdn);
    295 
    296 
    297         AdnRecord adn = new AdnRecord(mMsisdnTag, mMsisdn);
    298 
    299         new AdnRecordLoader(mFh).updateEF(adn, EF_MSISDN, EF_EXT1, 1, null,
    300                 obtainMessage(EVENT_SET_MSISDN_DONE, onComplete));
    301     }
    302 
    303     public String getMsisdnAlphaTag() {
    304         return mMsisdnTag;
    305     }
    306 
    307     public String getVoiceMailNumber() {
    308         return mVoiceMailNum;
    309     }
    310 
    311     /**
    312      * Return Service Provider Name stored in SIM (EF_SPN=0x6F46) or in RUIM (EF_RUIM_SPN=0x6F41).
    313      *
    314      * @return null if SIM is not yet ready or no RUIM entry
    315      */
    316     public String getServiceProviderName() {
    317         String providerName = mSpn;
    318 
    319         // Check for null pointers, mParentApp can be null after dispose,
    320         // which did occur after removing a SIM.
    321         UiccCardApplication parentApp = mParentApp;
    322         if (parentApp != null) {
    323             UiccCard card = parentApp.getUiccCard();
    324             if (card != null) {
    325                 String brandOverride = card.getOperatorBrandOverride();
    326                 if (brandOverride != null) {
    327                     log("getServiceProviderName: override");
    328                     providerName = brandOverride;
    329                 } else {
    330                     log("getServiceProviderName: no brandOverride");
    331                 }
    332             } else {
    333                 log("getServiceProviderName: card is null");
    334             }
    335         } else {
    336             log("getServiceProviderName: mParentApp is null");
    337         }
    338         log("getServiceProviderName: providerName=" + providerName);
    339         return providerName;
    340     }
    341 
    342     protected void setServiceProviderName(String spn) {
    343         mSpn = spn;
    344     }
    345 
    346     /**
    347      * Set voice mail number to SIM record
    348      *
    349      * The voice mail number can be stored either in EF_MBDN (TS 51.011) or
    350      * EF_MAILBOX_CPHS (CPHS 4.2)
    351      *
    352      * If EF_MBDN is available, store the voice mail number to EF_MBDN
    353      *
    354      * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS
    355      *
    356      * So the voice mail number will be stored in both EFs if both are available
    357      *
    358      * Return error only if both EF_MBDN and EF_MAILBOX_CPHS fail.
    359      *
    360      * When the operation is complete, onComplete will be sent to its handler
    361      *
    362      * @param alphaTag alpha-tagging of the dailing nubmer (upto 10 characters)
    363      * @param voiceNumber dailing nubmer (upto 20 digits)
    364      *        if the number is start with '+', then set to international TOA
    365      * @param onComplete
    366      *        onComplete.obj will be an AsyncResult
    367      *        ((AsyncResult)onComplete.obj).exception == null on success
    368      *        ((AsyncResult)onComplete.obj).exception != null on fail
    369      */
    370     public abstract void setVoiceMailNumber(String alphaTag, String voiceNumber,
    371             Message onComplete);
    372 
    373     public String getVoiceMailAlphaTag() {
    374         return mVoiceMailTag;
    375     }
    376 
    377     /**
    378      * Sets the SIM voice message waiting indicator records
    379      * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
    380      * @param countWaiting The number of messages waiting, if known. Use
    381      *                     -1 to indicate that an unknown number of
    382      *                      messages are waiting
    383      */
    384     public abstract void setVoiceMessageWaiting(int line, int countWaiting);
    385 
    386     /** @return  true if there are messages waiting, false otherwise. */
    387     public boolean getVoiceMessageWaiting() {
    388         return mCountVoiceMessages != 0;
    389     }
    390 
    391     /**
    392      * Returns number of voice messages waiting, if available
    393      * If not available (eg, on an older CPHS SIM) -1 is returned if
    394      * getVoiceMessageWaiting() is true
    395      */
    396     public int getVoiceMessageCount() {
    397         return mCountVoiceMessages;
    398     }
    399 
    400     /**
    401      * Called by STK Service when REFRESH is received.
    402      * @param fileChanged indicates whether any files changed
    403      * @param fileList if non-null, a list of EF files that changed
    404      */
    405     public abstract void onRefresh(boolean fileChanged, int[] fileList);
    406 
    407     /**
    408      * Called by subclasses (SimRecords and RuimRecords) whenever
    409      * IccRefreshResponse.REFRESH_RESULT_INIT event received
    410      */
    411     protected void onIccRefreshInit() {
    412         mAdnCache.reset();
    413         UiccCardApplication parentApp = mParentApp;
    414         if ((parentApp != null) &&
    415                 (parentApp.getState() == AppState.APPSTATE_READY)) {
    416             // This will cause files to be reread
    417             sendMessage(obtainMessage(EVENT_APP_READY));
    418         }
    419     }
    420 
    421     public boolean getRecordsLoaded() {
    422         if (mRecordsToLoad == 0 && mRecordsRequested == true) {
    423             return true;
    424         } else {
    425             return false;
    426         }
    427     }
    428 
    429     //***** Overridden from Handler
    430     @Override
    431     public void handleMessage(Message msg) {
    432         AsyncResult ar;
    433 
    434         switch (msg.what) {
    435             case EVENT_GET_ICC_RECORD_DONE:
    436                 try {
    437                     ar = (AsyncResult) msg.obj;
    438                     IccRecordLoaded recordLoaded = (IccRecordLoaded) ar.userObj;
    439                     if (DBG) log(recordLoaded.getEfName() + " LOADED");
    440 
    441                     if (ar.exception != null) {
    442                         loge("Record Load Exception: " + ar.exception);
    443                     } else {
    444                         recordLoaded.onRecordLoaded(ar);
    445                     }
    446                 }catch (RuntimeException exc) {
    447                     // I don't want these exceptions to be fatal
    448                     loge("Exception parsing SIM record: " + exc);
    449                 } finally {
    450                     // Count up record load responses even if they are fails
    451                     onRecordLoaded();
    452                 }
    453                 break;
    454 
    455             case EVENT_AKA_AUTHENTICATE_DONE:
    456                 ar = (AsyncResult)msg.obj;
    457                 auth_rsp = null;
    458                 if (DBG) log("EVENT_AKA_AUTHENTICATE_DONE");
    459                 if (ar.exception != null) {
    460                     loge("Exception ICC SIM AKA: " + ar.exception);
    461                 } else {
    462                     try {
    463                         auth_rsp = (IccIoResult)ar.result;
    464                         if (DBG) log("ICC SIM AKA: auth_rsp = " + auth_rsp);
    465                     } catch (Exception e) {
    466                         loge("Failed to parse ICC SIM AKA contents: " + e);
    467                     }
    468                 }
    469                 synchronized (mLock) {
    470                     mLock.notifyAll();
    471                 }
    472 
    473                 break;
    474 
    475             default:
    476                 super.handleMessage(msg);
    477         }
    478     }
    479 
    480     protected abstract void onRecordLoaded();
    481 
    482     protected abstract void onAllRecordsLoaded();
    483 
    484     /**
    485      * Returns the SpnDisplayRule based on settings on the SIM and the
    486      * specified plmn (currently-registered PLMN).  See TS 22.101 Annex A
    487      * and TS 51.011 10.3.11 for details.
    488      *
    489      * If the SPN is not found on the SIM, the rule is always PLMN_ONLY.
    490      * Generally used for GSM/UMTS and the like SIMs.
    491      */
    492     public abstract int getDisplayRule(String plmn);
    493 
    494     /**
    495      * Return true if "Restriction of menu options for manual PLMN selection"
    496      * bit is set or EF_CSP data is unavailable, return false otherwise.
    497      * Generally used for GSM/UMTS and the like SIMs.
    498      */
    499     public boolean isCspPlmnEnabled() {
    500         return false;
    501     }
    502 
    503     /**
    504      * Returns the 5 or 6 digit MCC/MNC of the operator that
    505      * provided the SIM card. Returns null of SIM is not yet ready
    506      * or is not valid for the type of IccCard. Generally used for
    507      * GSM/UMTS and the like SIMS
    508      */
    509     public String getOperatorNumeric() {
    510         return null;
    511     }
    512 
    513     /**
    514      * Get the current Voice call forwarding flag for GSM/UMTS and the like SIMs
    515      *
    516      * @return true if enabled
    517      */
    518     public boolean getVoiceCallForwardingFlag() {
    519         return false;
    520     }
    521 
    522     /**
    523      * Set the voice call forwarding flag for GSM/UMTS and the like SIMs
    524      *
    525      * @param line to enable/disable
    526      * @param enable
    527      * @param number to which CFU is enabled
    528      */
    529     public void setVoiceCallForwardingFlag(int line, boolean enable, String number) {
    530     }
    531 
    532     /**
    533      * Indicates wether SIM is in provisioned state or not.
    534      * Overridden only if SIM can be dynamically provisioned via OTA.
    535      *
    536      * @return true if provisioned
    537      */
    538     public boolean isProvisioned () {
    539         return true;
    540     }
    541 
    542     /**
    543      * Write string to log file
    544      *
    545      * @param s is the string to write
    546      */
    547     protected abstract void log(String s);
    548 
    549     /**
    550      * Write error string to log file.
    551      *
    552      * @param s is the string to write
    553      */
    554     protected abstract void loge(String s);
    555 
    556     /**
    557      * Return an interface to retrieve the ISIM records for IMS, if available.
    558      * @return the interface to retrieve the ISIM records, or null if not supported
    559      */
    560     public IsimRecords getIsimRecords() {
    561         return null;
    562     }
    563 
    564     public UsimServiceTable getUsimServiceTable() {
    565         return null;
    566     }
    567 
    568     /**
    569      * Returns the response of the SIM application on the UICC to authentication
    570      * challenge/response algorithm. The data string and challenge response are
    571      * Base64 encoded Strings.
    572      * Can support EAP-SIM, EAP-AKA with results encoded per 3GPP TS 31.102.
    573      *
    574      * @param authContext parameter P2 that specifies the authentication context per 3GPP TS 31.102 (Section 7.1.2)
    575      * @param data authentication challenge data
    576      * @return challenge response
    577      */
    578     public String getIccSimChallengeResponse(int authContext, String data) {
    579         if (DBG) log("getIccSimChallengeResponse:");
    580 
    581         try {
    582             synchronized(mLock) {
    583                 CommandsInterface ci = mCi;
    584                 UiccCardApplication parentApp = mParentApp;
    585                 if (ci != null && parentApp != null) {
    586                     ci.requestIccSimAuthentication(authContext, data,
    587                             parentApp.getAid(),
    588                             obtainMessage(EVENT_AKA_AUTHENTICATE_DONE));
    589                     try {
    590                         mLock.wait();
    591                     } catch (InterruptedException e) {
    592                         loge("getIccSimChallengeResponse: Fail, interrupted"
    593                                 + " while trying to request Icc Sim Auth");
    594                         return null;
    595                     }
    596                 } else {
    597                     loge( "getIccSimChallengeResponse: "
    598                             + "Fail, ci or parentApp is null");
    599                     return null;
    600                 }
    601             }
    602         } catch(Exception e) {
    603             loge( "getIccSimChallengeResponse: "
    604                     + "Fail while trying to request Icc Sim Auth");
    605             return null;
    606         }
    607 
    608         if (DBG) log("getIccSimChallengeResponse: return auth_rsp");
    609 
    610         return android.util.Base64.encodeToString(auth_rsp.payload, android.util.Base64.NO_WRAP);
    611     }
    612 
    613     protected boolean requirePowerOffOnSimRefreshReset() {
    614         return mContext.getResources().getBoolean(
    615             com.android.internal.R.bool.config_requireRadioPowerOffOnSimRefreshReset);
    616     }
    617 
    618     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    619         pw.println("IccRecords: " + this);
    620         pw.println(" mDestroyed=" + mDestroyed);
    621         pw.println(" mCi=" + mCi);
    622         pw.println(" mFh=" + mFh);
    623         pw.println(" mParentApp=" + mParentApp);
    624         pw.println(" recordsLoadedRegistrants: size=" + mRecordsLoadedRegistrants.size());
    625         for (int i = 0; i < mRecordsLoadedRegistrants.size(); i++) {
    626             pw.println("  recordsLoadedRegistrants[" + i + "]="
    627                     + ((Registrant)mRecordsLoadedRegistrants.get(i)).getHandler());
    628         }
    629         pw.println(" mImsiReadyRegistrants: size=" + mImsiReadyRegistrants.size());
    630         for (int i = 0; i < mImsiReadyRegistrants.size(); i++) {
    631             pw.println("  mImsiReadyRegistrants[" + i + "]="
    632                     + ((Registrant)mImsiReadyRegistrants.get(i)).getHandler());
    633         }
    634         pw.println(" mRecordsEventsRegistrants: size=" + mRecordsEventsRegistrants.size());
    635         for (int i = 0; i < mRecordsEventsRegistrants.size(); i++) {
    636             pw.println("  mRecordsEventsRegistrants[" + i + "]="
    637                     + ((Registrant)mRecordsEventsRegistrants.get(i)).getHandler());
    638         }
    639         pw.println(" mNewSmsRegistrants: size=" + mNewSmsRegistrants.size());
    640         for (int i = 0; i < mNewSmsRegistrants.size(); i++) {
    641             pw.println("  mNewSmsRegistrants[" + i + "]="
    642                     + ((Registrant)mNewSmsRegistrants.get(i)).getHandler());
    643         }
    644         pw.println(" mNetworkSelectionModeAutomaticRegistrants: size="
    645                 + mNetworkSelectionModeAutomaticRegistrants.size());
    646         for (int i = 0; i < mNetworkSelectionModeAutomaticRegistrants.size(); i++) {
    647             pw.println("  mNetworkSelectionModeAutomaticRegistrants[" + i + "]="
    648                     + ((Registrant)mNetworkSelectionModeAutomaticRegistrants.get(i)).getHandler());
    649         }
    650         pw.println(" mRecordsRequested=" + mRecordsRequested);
    651         pw.println(" mRecordsToLoad=" + mRecordsToLoad);
    652         pw.println(" mRdnCache=" + mAdnCache);
    653         pw.println(" iccid=" + mIccId);
    654         pw.println(" mMsisdn=" + mMsisdn);
    655         pw.println(" mMsisdnTag=" + mMsisdnTag);
    656         pw.println(" mVoiceMailNum=" + mVoiceMailNum);
    657         pw.println(" mVoiceMailTag=" + mVoiceMailTag);
    658         pw.println(" mNewVoiceMailNum=" + mNewVoiceMailNum);
    659         pw.println(" mNewVoiceMailTag=" + mNewVoiceMailTag);
    660         pw.println(" mIsVoiceMailFixed=" + mIsVoiceMailFixed);
    661         pw.println(" mCountVoiceMessages=" + mCountVoiceMessages);
    662         pw.println(" mImsi=" + mImsi);
    663         pw.println(" mMncLength=" + mMncLength);
    664         pw.println(" mMailboxIndex=" + mMailboxIndex);
    665         pw.println(" mSpn=" + mSpn);
    666         pw.flush();
    667     }
    668 }
    669