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