CDMAPhone.java revision c6d6b687af385d2a4e5f5210a9111d7b1acc233c
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.cdma;
18
19import android.app.ActivityManagerNative;
20import android.content.Context;
21import android.content.ContentValues;
22import android.content.Intent;
23import android.content.res.Configuration;
24import android.content.SharedPreferences;
25import android.database.SQLException;
26import android.net.Uri;
27import android.os.AsyncResult;
28import android.os.Handler;
29import android.os.Looper;
30import android.os.Message;
31import android.os.Registrant;
32import android.os.RegistrantList;
33import android.os.RemoteException;
34import android.os.SystemProperties;
35import android.preference.PreferenceManager;
36import android.provider.Settings;
37import android.provider.Telephony;
38import android.telephony.CellLocation;
39import android.telephony.PhoneNumberUtils;
40import android.telephony.ServiceState;
41import android.telephony.SignalStrength;
42import android.text.TextUtils;
43import android.util.Log;
44
45import com.android.internal.telephony.Call;
46import com.android.internal.telephony.CallStateException;
47import com.android.internal.telephony.CommandException;
48import com.android.internal.telephony.CommandsInterface;
49import com.android.internal.telephony.Connection;
50import com.android.internal.telephony.DataConnection;
51// TODO(Moto): need to move MccTable from telephony.gsm to telephony
52// since there is no difference between CDMA and GSM for MccTable and
53// CDMA uses gsm's MccTable is not good.
54import com.android.internal.telephony.gsm.MccTable;
55import com.android.internal.telephony.IccCard;
56import com.android.internal.telephony.IccException;
57import com.android.internal.telephony.IccFileHandler;
58import com.android.internal.telephony.IccPhoneBookInterfaceManager;
59import com.android.internal.telephony.IccSmsInterfaceManager;
60import com.android.internal.telephony.MmiCode;
61import com.android.internal.telephony.Phone;
62import com.android.internal.telephony.PhoneBase;
63import com.android.internal.telephony.PhoneNotifier;
64import com.android.internal.telephony.PhoneProxy;
65import com.android.internal.telephony.PhoneSubInfo;
66import com.android.internal.telephony.RILConstants;
67import com.android.internal.telephony.TelephonyIntents;
68import com.android.internal.telephony.TelephonyProperties;
69
70import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
71import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
72import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
73
74import java.util.List;
75import java.util.Timer;
76import java.util.TimerTask;
77
78import java.util.regex.Matcher;
79import java.util.regex.Pattern;
80
81/**
82 * {@hide}
83 */
84public class CDMAPhone extends PhoneBase {
85    static final String LOG_TAG = "CDMA";
86    private static final boolean DBG = true;
87
88    // Default Emergency Callback Mode exit timer
89    private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000;
90    static final String VM_COUNT_CDMA = "vm_count_key_cdma";
91    private static final String VM_NUMBER_CDMA = "vm_number_key_cdma";
92    private String mVmNumber = null;
93
94    //***** Instance Variables
95    CdmaCallTracker mCT;
96    CdmaSMSDispatcher mSMS;
97    CdmaServiceStateTracker mSST;
98    CdmaDataConnectionTracker mDataConnection;
99    RuimFileHandler mRuimFileHandler;
100    RuimRecords mRuimRecords;
101    RuimCard mRuimCard;
102    MyHandler h;
103    RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager;
104    RuimSmsInterfaceManager mRuimSmsInterfaceManager;
105    PhoneSubInfo mSubInfo;
106    EriManager mEriManager;
107
108    // mNvLoadedRegistrants are informed after the EVENT_NV_READY
109    private RegistrantList mNvLoadedRegistrants = new RegistrantList();
110
111    // mEriFileLoadedRegistrants are informed after the ERI text has been loaded
112    private RegistrantList mEriFileLoadedRegistrants = new RegistrantList();
113
114    // mECMExitRespRegistrant is informed after the phone has been exited
115    //the emergency callback mode
116    //keep track of if phone is in emergency callback mode
117    private boolean mIsPhoneInECMState;
118    private Registrant mECMExitRespRegistrant;
119    private String mEsn;
120    private String mMeid;
121    // string to define how the carrier specifies its own ota sp number
122    private String mCarrierOtaSpNumSchema;
123
124    // A runnable which is used to automatically exit from ECM after a period of time.
125    private Runnable mExitEcmRunnable = new Runnable() {
126        public void run() {
127            exitEmergencyCallbackMode();
128        }
129    };
130
131    Registrant mPostDialHandler;
132
133
134    //***** Constructors
135    public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
136        this(context,ci,notifier, false);
137    }
138
139    public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
140            boolean unitTestMode) {
141        super(notifier, context, unitTestMode);
142
143        h = new MyHandler();
144        mCM = ci;
145
146        mCM.setPhoneType(RILConstants.CDMA_PHONE);
147        mCT = new CdmaCallTracker(this);
148        mSST = new CdmaServiceStateTracker (this);
149        mSMS = new CdmaSMSDispatcher(this);
150        mIccFileHandler = new RuimFileHandler(this);
151        mRuimRecords = new RuimRecords(this);
152        mDataConnection = new CdmaDataConnectionTracker (this);
153        mRuimCard = new RuimCard(this);
154        mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
155        mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this);
156        mSubInfo = new PhoneSubInfo(this);
157        mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
158
159        mCM.registerForAvailable(h, EVENT_RADIO_AVAILABLE, null);
160        mRuimRecords.registerForRecordsLoaded(h, EVENT_RUIM_RECORDS_LOADED, null);
161        mCM.registerForOffOrNotAvailable(h, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
162        mCM.registerForOn(h, EVENT_RADIO_ON, null);
163        mCM.setOnSuppServiceNotification(h, EVENT_SSN, null);
164        mCM.setOnCallRing(h, EVENT_CALL_RING, null);
165        mSST.registerForNetworkAttach(h, EVENT_REGISTERED_TO_NETWORK, null);
166        mCM.registerForNVReady(h, EVENT_NV_READY, null);
167        mCM.setEmergencyCallbackMode(h, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
168
169
170        //Change the system setting
171        SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE,
172                new Integer(RILConstants.CDMA_PHONE).toString());
173
174        // This is needed to handle phone process crashes
175        String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
176        mIsPhoneInECMState = inEcm.equals("true");
177
178        // get the string that specifies the carrier OTA Sp number
179        mCarrierOtaSpNumSchema = SystemProperties.get(
180                TelephonyProperties.PROPERTY_OTASP_NUM_SCHEMA,"");
181
182        // Sets operator alpha property by retrieving from build-time system property
183        String operatorAlpha = SystemProperties.get("ro.cdma.home.operator.alpha");
184        setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, operatorAlpha);
185
186        // Sets operator numeric property by retrieving from build-time system property
187        String operatorNumeric = SystemProperties.get("ro.cdma.home.operator.numeric");
188        setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operatorNumeric);
189
190        // Sets iso country property by retrieving from build-time system property
191        setIsoCountryProperty(operatorNumeric);
192
193        // Sets current entry in the telephony carrier table
194        updateCurrentCarrierInProvider(operatorNumeric);
195
196        // Updates MCC MNC device configuration information
197        updateMccMncConfiguration(operatorNumeric);
198
199        // Notify voicemails.
200        notifier.notifyMessageWaitingChanged(this);
201    }
202
203    public void dispose() {
204        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
205
206            //Unregister from all former registered events
207            mRuimRecords.unregisterForRecordsLoaded(h); //EVENT_RUIM_RECORDS_LOADED
208            mCM.unregisterForAvailable(h); //EVENT_RADIO_AVAILABLE
209            mCM.unregisterForOffOrNotAvailable(h); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
210            mCM.unregisterForOn(h); //EVENT_RADIO_ON
211            mCM.unregisterForNVReady(h); //EVENT_NV_READY
212            mSST.unregisterForNetworkAttach(h); //EVENT_REGISTERED_TO_NETWORK
213            mCM.unSetOnSuppServiceNotification(h);
214            mCM.unSetOnCallRing(h);
215
216
217            //Force all referenced classes to unregister their former registered events
218            mCT.dispose();
219            mDataConnection.dispose();
220            mSST.dispose();
221            mSMS.dispose();
222            mIccFileHandler.dispose(); // instance of RuimFileHandler
223            mRuimRecords.dispose();
224            mRuimCard.dispose();
225            mRuimPhoneBookInterfaceManager.dispose();
226            mRuimSmsInterfaceManager.dispose();
227            mSubInfo.dispose();
228            mEriManager.dispose();
229        }
230    }
231
232    public void removeReferences() {
233            this.mRuimPhoneBookInterfaceManager = null;
234            this.mRuimSmsInterfaceManager = null;
235            this.mSMS = null;
236            this.mSubInfo = null;
237            this.mRuimRecords = null;
238            this.mIccFileHandler = null;
239            this.mRuimCard = null;
240            this.mDataConnection = null;
241            this.mCT = null;
242            this.mSST = null;
243            this.mEriManager = null;
244    }
245
246    protected void finalize() {
247        if(DBG) Log.d(LOG_TAG, "CDMAPhone finalized");
248    }
249
250
251    //***** Overridden from Phone
252    public ServiceState getServiceState() {
253        return mSST.ss;
254    }
255
256    public Phone.State
257    getState() {
258        return mCT.state;
259    }
260
261    public String
262    getPhoneName() {
263        return "CDMA";
264    }
265
266    public boolean canTransfer() {
267        Log.e(LOG_TAG, "canTransfer: not possible in CDMA");
268        return false;
269    }
270
271    public CdmaCall
272    getRingingCall() {
273        return mCT.ringingCall;
274    }
275
276    public void setMute(boolean muted) {
277        mCT.setMute(muted);
278    }
279
280    public boolean getMute() {
281        return mCT.getMute();
282    }
283
284    public void conference() throws CallStateException {
285        // three way calls in CDMA will be handled by feature codes
286        Log.e(LOG_TAG, "conference: not possible in CDMA");
287    }
288
289    public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
290        this.mCM.setPreferredVoicePrivacy(enable, onComplete);
291    }
292
293    public void getEnhancedVoicePrivacy(Message onComplete) {
294        this.mCM.getPreferredVoicePrivacy(onComplete);
295    }
296
297    public void clearDisconnected() {
298        mCT.clearDisconnected();
299    }
300
301    public DataActivityState getDataActivityState() {
302        DataActivityState ret = DataActivityState.NONE;
303
304        if (mSST.getCurrentCdmaDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
305
306            switch (mDataConnection.getActivity()) {
307                case DATAIN:
308                    ret = DataActivityState.DATAIN;
309                break;
310
311                case DATAOUT:
312                    ret = DataActivityState.DATAOUT;
313                break;
314
315                case DATAINANDOUT:
316                    ret = DataActivityState.DATAINANDOUT;
317                break;
318
319                case DORMANT:
320                    ret = DataActivityState.DORMANT;
321                break;
322            }
323        }
324        return ret;
325    }
326
327    /*package*/ void
328    notifySignalStrength() {
329        mNotifier.notifySignalStrength(this);
330    }
331
332    public Connection
333    dial (String dialString) throws CallStateException {
334        // Need to make sure dialString gets parsed properly
335        String newDialString = PhoneNumberUtils.stripSeparators(dialString);
336
337        if (!mCT.foregroundCall.isIdle()) {
338            FeatureCode fc = FeatureCode.newFromDialString(newDialString, this);
339            if (fc != null) {
340                //mMmiRegistrants.notifyRegistrants(new AsyncResult(null, fc, null));
341                fc.processCode();
342                return null;
343            }
344        }
345        return mCT.dial(newDialString);
346    }
347
348    public SignalStrength getSignalStrength() {
349        return mSST.mSignalStrength;
350    }
351
352    public boolean
353    getMessageWaitingIndicator() {
354        return (getVoiceMessageCount() > 0);
355    }
356
357    public List<? extends MmiCode>
358    getPendingMmiCodes() {
359        Log.e(LOG_TAG, "method getPendingMmiCodes is NOT supported in CDMA!");
360        return null;
361    }
362
363    public void registerForSuppServiceNotification(
364            Handler h, int what, Object obj) {
365        Log.e(LOG_TAG, "method registerForSuppServiceNotification is NOT supported in CDMA!");
366    }
367
368    public CdmaCall getBackgroundCall() {
369        return mCT.backgroundCall;
370    }
371
372    public String getGateway(String apnType) {
373        return mDataConnection.getGateway();
374    }
375
376    public boolean handleInCallMmiCommands(String dialString) {
377        Log.e(LOG_TAG, "method handleInCallMmiCommands is NOT supported in CDMA!");
378        return false;
379    }
380
381    public int enableApnType(String type) {
382        // This request is mainly used to enable MMS APN
383        // In CDMA there is no need to enable/disable a different APN for MMS
384        Log.d(LOG_TAG, "Request to enableApnType("+type+")");
385        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
386            return Phone.APN_ALREADY_ACTIVE;
387        } else {
388            return Phone.APN_REQUEST_FAILED;
389        }
390    }
391
392    public int disableApnType(String type) {
393        // This request is mainly used to disable MMS APN
394        // In CDMA there is no need to enable/disable a different APN for MMS
395        Log.d(LOG_TAG, "Request to disableApnType("+type+")");
396        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
397            return Phone.APN_REQUEST_STARTED;
398        } else {
399            return Phone.APN_REQUEST_FAILED;
400        }
401    }
402
403    public String getActiveApn() {
404        Log.d(LOG_TAG, "Request to getActiveApn()");
405        return null;
406    }
407
408    public void
409    setNetworkSelectionModeAutomatic(Message response) {
410        Log.e(LOG_TAG, "method setNetworkSelectionModeAutomatic is NOT supported in CDMA!");
411    }
412
413    public void unregisterForSuppServiceNotification(Handler h) {
414        Log.e(LOG_TAG, "method unregisterForSuppServiceNotification is NOT supported in CDMA!");
415    }
416
417    public void
418    acceptCall() throws CallStateException {
419        mCT.acceptCall();
420    }
421
422    public void
423    rejectCall() throws CallStateException {
424        mCT.rejectCall();
425    }
426
427    public void
428    switchHoldingAndActive() throws CallStateException {
429        mCT.switchWaitingOrHoldingAndActive();
430    }
431
432    public String getLine1Number() {
433        return mSST.getMdnNumber();
434    }
435
436    public String getCdmaPrlVersion(){
437        return mSST.getPrlVersion();
438    }
439
440    public String getCdmaMin() {
441        return mSST.getCdmaMin();
442    }
443
444    public void getCallWaiting(Message onComplete) {
445        mCM.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
446    }
447
448    public void
449    setRadioPower(boolean power) {
450        mSST.setRadioPower(power);
451    }
452
453    public String getEsn() {
454        return mEsn;
455    }
456
457    public String getMeid() {
458        return mMeid;
459    }
460
461    //returns MEID in CDMA
462    public String getDeviceId() {
463        return getMeid();
464    }
465
466    public String getDeviceSvn() {
467        Log.d(LOG_TAG, "getDeviceSvn(): return 0");
468        return "0";
469    }
470
471    public String getSubscriberId() {
472        return mSST.getImsi();
473    }
474
475    public boolean canConference() {
476        Log.e(LOG_TAG, "canConference: not possible in CDMA");
477        return false;
478    }
479
480    public String getInterfaceName(String apnType) {
481        return mDataConnection.getInterfaceName();
482    }
483
484    public CellLocation getCellLocation() {
485        return mSST.cellLoc;
486    }
487
488    public boolean disableDataConnectivity() {
489        return mDataConnection.setDataEnabled(false);
490    }
491
492    public CdmaCall getForegroundCall() {
493        return mCT.foregroundCall;
494    }
495
496    public void
497    selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo network,
498            Message response) {
499        Log.e(LOG_TAG, "selectNetworkManually: not possible in CDMA");
500    }
501
502    public void setOnPostDialCharacter(Handler h, int what, Object obj) {
503        mPostDialHandler = new Registrant(h, what, obj);
504    }
505
506    public boolean handlePinMmi(String dialString) {
507        Log.e(LOG_TAG, "method handlePinMmi is NOT supported in CDMA!");
508        return false;
509    }
510
511    public boolean isDataConnectivityEnabled() {
512        return mDataConnection.getDataEnabled();
513    }
514
515    public boolean isDataConnectivityPossible() {
516        boolean noData = mDataConnection.getDataEnabled() &&
517                getDataConnectionState() == DataState.DISCONNECTED;
518        return !noData && getIccCard().getState() == IccCard.State.READY &&
519                getServiceState().getState() == ServiceState.STATE_IN_SERVICE &&
520                (mDataConnection.getDataOnRoamingEnabled() || !getServiceState().getRoaming());
521    }
522
523    public void setLine1Number(String alphaTag, String number, Message onComplete) {
524        Log.e(LOG_TAG, "setLine1Number: not possible in CDMA");
525    }
526
527    public String[] getDnsServers(String apnType) {
528        return mDataConnection.getDnsServers();
529    }
530
531    public IccCard getIccCard() {
532        return mRuimCard;
533    }
534
535    public String getIccSerialNumber() {
536        return mRuimRecords.iccid;
537    }
538
539    public void setCallWaiting(boolean enable, Message onComplete) {
540        Log.e(LOG_TAG, "method setCallWaiting is NOT supported in CDMA!");
541    }
542
543    public void updateServiceLocation(Message response) {
544        mSST.getLacAndCid(response);
545    }
546
547    public void setDataRoamingEnabled(boolean enable) {
548        mDataConnection.setDataOnRoamingEnabled(enable);
549    }
550
551    public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
552        mCM.registerForCdmaOtaProvision(h, what, obj);
553    }
554
555    public void unregisterForCdmaOtaStatusChange(Handler h) {
556        mCM.unregisterForCdmaOtaProvision(h);
557    }
558
559    public void setOnEcbModeExitResponse(Handler h, int what, Object obj) {
560        mECMExitRespRegistrant = new Registrant (h, what, obj);
561    }
562
563    public void unsetOnEcbModeExitResponse(Handler h) {
564        mECMExitRespRegistrant.clear();
565    }
566
567    public void registerForCallWaiting(Handler h, int what, Object obj) {
568        mCT.registerForCallWaiting(h, what, obj);
569    }
570
571    public void unregisterForCallWaiting(Handler h) {
572        mCT.unregisterForCallWaiting(h);
573    }
574
575    public String getIpAddress(String apnType) {
576        return mDataConnection.getIpAddress();
577    }
578
579    public void
580    getNeighboringCids(Message response) {
581        /*
582         * This is currently not implemented.  At least as of June
583         * 2009, there is no neighbor cell information available for
584         * CDMA because some party is resisting making this
585         * information readily available.  Consequently, calling this
586         * function can have no useful effect.  This situation may
587         * (and hopefully will) change in the future.
588         */
589        if (response != null) {
590            CommandException ce = new CommandException(
591                    CommandException.Error.REQUEST_NOT_SUPPORTED);
592            AsyncResult.forMessage(response).exception = ce;
593            response.sendToTarget();
594        }
595    }
596
597    public DataState getDataConnectionState() {
598        DataState ret = DataState.DISCONNECTED;
599
600        if ((SystemProperties.get("adb.connected", "").length() > 0)
601                && (SystemProperties.get("android.net.use-adb-networking", "")
602                        .length() > 0)) {
603            // We're connected to an ADB host and we have USB networking
604            // turned on. No matter what the radio state is,
605            // we report data connected
606
607            ret = DataState.CONNECTED;
608        } else if (mSST == null) {
609             // Radio Technology Change is ongoning, dispose() and removeReferences() have
610             // already been called
611
612             ret = DataState.DISCONNECTED;
613        } else if (mSST.getCurrentCdmaDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
614            // If we're out of service, open TCP sockets may still work
615            // but no data will flow
616            ret = DataState.DISCONNECTED;
617        } else {
618            switch (mDataConnection.getState()) {
619                case FAILED:
620                case IDLE:
621                    ret = DataState.DISCONNECTED;
622                break;
623
624                case CONNECTED:
625                case DISCONNECTING:
626                    if ( mCT.state != Phone.State.IDLE
627                            && !mSST.isConcurrentVoiceAndData()) {
628                        ret = DataState.SUSPENDED;
629                    } else {
630                        ret = DataState.CONNECTED;
631                    }
632                break;
633
634                case INITING:
635                case CONNECTING:
636                case SCANNING:
637                    ret = DataState.CONNECTING;
638                break;
639            }
640        }
641
642        return ret;
643    }
644
645    public void sendUssdResponse(String ussdMessge) {
646        Log.e(LOG_TAG, "sendUssdResponse: not possible in CDMA");
647    }
648
649    public void sendDtmf(char c) {
650        if (!PhoneNumberUtils.is12Key(c)) {
651            Log.e(LOG_TAG,
652                    "sendDtmf called with invalid character '" + c + "'");
653        } else {
654            if (mCT.state ==  Phone.State.OFFHOOK) {
655                mCM.sendDtmf(c, null);
656            }
657        }
658    }
659
660    public void startDtmf(char c) {
661        if (!PhoneNumberUtils.is12Key(c)) {
662            Log.e(LOG_TAG,
663                    "startDtmf called with invalid character '" + c + "'");
664        } else {
665            mCM.startDtmf(c, null);
666        }
667    }
668
669    public void stopDtmf() {
670        mCM.stopDtmf(null);
671    }
672
673    public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
674        boolean check = true;
675        for (int itr = 0;itr < dtmfString.length(); itr++) {
676            if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) {
677                Log.e(LOG_TAG,
678                        "sendDtmf called with invalid character '" + dtmfString.charAt(itr)+ "'");
679                check = false;
680                break;
681            }
682        }
683        if ((mCT.state ==  Phone.State.OFFHOOK)&&(check)) {
684            mCM.sendBurstDtmf(dtmfString, on, off, onComplete);
685        }
686     }
687
688    public void getAvailableNetworks(Message response) {
689        Log.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA");
690    }
691
692    public String[] getActiveApnTypes() {
693        String[] result;
694        Log.d(LOG_TAG, "Request to getActiveApn()");
695        result = new String[1];
696        result[0] = Phone.APN_TYPE_DEFAULT;
697        return result;
698    }
699
700    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
701        Log.e(LOG_TAG, "setOutgoingCallerIdDisplay: not possible in CDMA");
702    }
703
704    public void enableLocationUpdates() {
705        mSST.enableLocationUpdates();
706    }
707
708    /**
709     * @deprecated
710     */
711    public void getPdpContextList(Message response) {
712        getDataCallList(response);
713    }
714
715    public void getDataCallList(Message response) {
716        mCM.getDataCallList(response);
717    }
718
719    public boolean getDataRoamingEnabled() {
720        return mDataConnection.getDataOnRoamingEnabled();
721    }
722
723    public List<DataConnection> getCurrentDataConnectionList () {
724        return mDataConnection.getAllDataConnections();
725    }
726
727    public void setVoiceMailNumber(String alphaTag,
728                                   String voiceMailNumber,
729                                   Message onComplete) {
730        Message resp;
731        mVmNumber = voiceMailNumber;
732        resp = h.obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
733        mRuimRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
734    }
735
736    public String getVoiceMailNumber() {
737        String number = null;
738        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
739        // TODO(Moto): The default value of voicemail number should be read from a system property
740        number = sp.getString(VM_NUMBER_CDMA, "*86");
741        return number;
742    }
743
744    /* Returns Number of Voicemails
745     * @hide
746     */
747    public int getVoiceMessageCount() {
748        int voicemailCount =  mRuimRecords.getVoiceMessageCount();
749        // If mRuimRecords.getVoiceMessageCount returns zero, then there is possibility
750        // that phone was power cycled and would have lost the voicemail count.
751        // So get the count from preferences.
752        if (voicemailCount == 0) {
753            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
754            voicemailCount = sp.getInt(VM_COUNT_CDMA, 0);
755        }
756        return voicemailCount;
757    }
758
759    public String getVoiceMailAlphaTag() {
760        // TODO: Where can we get this value has to be clarified with QC.
761        String ret = "";//TODO: Remove = "", if we know where to get this value.
762
763        //ret = mSIMRecords.getVoiceMailAlphaTag();
764
765        if (ret == null || ret.length() == 0) {
766            return mContext.getText(
767                com.android.internal.R.string.defaultVoiceMailAlphaTag).toString();
768        }
769
770        return ret;
771    }
772
773    public boolean enableDataConnectivity() {
774
775        // block data activities when phone is in emergency callback mode
776        if (mIsPhoneInECMState) {
777            Intent intent = new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS);
778            ActivityManagerNative.broadcastStickyIntent(intent, null);
779            return false;
780        } else {
781            return mDataConnection.setDataEnabled(true);
782        }
783    }
784
785    public void disableLocationUpdates() {
786        mSST.disableLocationUpdates();
787    }
788
789    public boolean getIccRecordsLoaded() {
790        return mRuimRecords.getRecordsLoaded();
791    }
792
793    public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
794        Log.e(LOG_TAG, "getCallForwardingOption: not possible in CDMA");
795    }
796
797    public void setCallForwardingOption(int commandInterfaceCFAction,
798            int commandInterfaceCFReason,
799            String dialingNumber,
800            int timerSeconds,
801            Message onComplete) {
802        Log.e(LOG_TAG, "setCallForwardingOption: not possible in CDMA");
803    }
804
805    public void
806    getOutgoingCallerIdDisplay(Message onComplete) {
807        Log.e(LOG_TAG, "getOutgoingCallerIdDisplay: not possible in CDMA");
808    }
809
810    public boolean
811    getCallForwardingIndicator() {
812        Log.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA");
813        return false;
814    }
815
816    public void explicitCallTransfer() {
817        Log.e(LOG_TAG, "explicitCallTransfer: not possible in CDMA");
818    }
819
820    public String getLine1AlphaTag() {
821        Log.e(LOG_TAG, "getLine1AlphaTag: not possible in CDMA");
822        return null;
823    }
824
825   /**
826     * Notify any interested party of a Phone state change  {@link Phone.State}
827     */
828    /*package*/ void notifyPhoneStateChanged() {
829        mNotifier.notifyPhoneState(this);
830    }
831
832    /**
833     * Notify registrants of a change in the call state. This notifies changes in {@link Call.State}
834     * Use this when changes in the precise call state are needed, else use notifyPhoneStateChanged.
835     */
836    /*package*/ void notifyPreciseCallStateChanged() {
837        /* we'd love it if this was package-scoped*/
838        super.notifyPreciseCallStateChangedP();
839    }
840
841     void notifyServiceStateChanged(ServiceState ss) {
842         super.notifyServiceStateChangedP(ss);
843     }
844
845     void notifyLocationChanged() {
846         mNotifier.notifyCellLocation(this);
847     }
848
849    /*package*/ void notifyNewRingingConnection(Connection c) {
850        /* we'd love it if this was package-scoped*/
851        super.notifyNewRingingConnectionP(c);
852    }
853
854    /**
855     * Notifiy registrants of a RING event.
856     */
857    void notifyIncomingRing() {
858        AsyncResult ar = new AsyncResult(null, this, null);
859        mIncomingRingRegistrants.notifyRegistrants(ar);
860    }
861
862    /*package*/ void notifyDisconnect(Connection cn) {
863        mDisconnectRegistrants.notifyResult(cn);
864    }
865
866    void notifyUnknownConnection() {
867        mUnknownConnectionRegistrants.notifyResult(this);
868    }
869
870    void sendEmergencyCallbackModeChange(){
871        //Send an Intent
872        Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
873        intent.putExtra(PHONE_IN_ECM_STATE, mIsPhoneInECMState);
874        ActivityManagerNative.broadcastStickyIntent(intent,null);
875    }
876
877    /*package*/ void
878    updateMessageWaitingIndicator(boolean mwi) {
879        // this also calls notifyMessageWaitingIndicator()
880        mRuimRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
881    }
882
883    /* This function is overloaded to send number of voicemails instead of sending true/false */
884    /*package*/ void
885    updateMessageWaitingIndicator(int mwi) {
886        mRuimRecords.setVoiceMessageWaiting(1, mwi);
887    }
888
889    /**
890     * Removes the given FC from the pending list and notifies
891     * registrants that it is complete.
892     * @param fc FC that is done
893     */
894    /*package*/ void onFeatureCodeDone(FeatureCode fc) {
895        /* Only notify complete if it's on the pending list.
896         * Otherwise, it's already been handled (eg, previously canceled).
897         * The exception is cancellation of an incoming USSD-REQUEST, which is
898         * not on the list.
899         */
900         mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, fc, null));
901    }
902
903
904    @Override
905    public void exitEmergencyCallbackMode() {
906        // Send a message which will invoke handleExitEmergencyCallbackMode
907        mCM.exitEmergencyCallbackMode(h.obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
908    }
909
910    private void handleEnterEmergencyCallbackMode(Message msg) {
911        Log.d(LOG_TAG, "Event EVENT_EMERGENCY_CALLBACK_MODE Received");
912        // if phone is not in ECM mode, and it's changed to ECM mode
913        if (mIsPhoneInECMState == false) {
914            mIsPhoneInECMState = true;
915            // notify change
916            sendEmergencyCallbackModeChange();
917            setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "true");
918
919            // Post this runnable so we will automatically exit
920            // if no one invokes exitEmergencyCallbackMode() directly.
921            long delayInMillis = SystemProperties.getLong(
922                    TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
923            h.postDelayed(mExitEcmRunnable, delayInMillis);
924        }
925    }
926
927    private void handleExitEmergencyCallbackMode(Message msg) {
928        Log.d(LOG_TAG, "Event EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE Received");
929        AsyncResult ar = (AsyncResult)msg.obj;
930
931        // Remove pending exit ECM runnable, if any
932        h.removeCallbacks(mExitEcmRunnable);
933
934        if (mECMExitRespRegistrant != null) {
935            mECMExitRespRegistrant.notifyRegistrant(ar);
936        }
937        // if exiting ecm success
938        if (ar.exception == null) {
939            if (mIsPhoneInECMState) {
940                mIsPhoneInECMState = false;
941                setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "false");
942            }
943            // send an Intent
944            sendEmergencyCallbackModeChange();
945        }
946    }
947
948    //***** Inner Classes
949    class MyHandler extends Handler {
950        MyHandler() {
951        }
952
953        MyHandler(Looper l) {
954            super(l);
955        }
956
957        @Override
958        public void handleMessage(Message msg) {
959            AsyncResult ar;
960            Message     onComplete;
961
962            switch(msg.what) {
963                case EVENT_RADIO_AVAILABLE: {
964                    mCM.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
965
966                    mCM.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));
967                }
968                break;
969
970                case EVENT_GET_BASEBAND_VERSION_DONE:{
971                    ar = (AsyncResult)msg.obj;
972
973                    if (ar.exception != null) {
974                        break;
975                    }
976
977                    if (DBG) Log.d(LOG_TAG, "Baseband version: " + ar.result);
978                    setSystemProperty(TelephonyProperties.PROPERTY_BASEBAND_VERSION, (String)ar.result);
979                }
980                break;
981
982                case EVENT_GET_DEVICE_IDENTITY_DONE:{
983                    ar = (AsyncResult)msg.obj;
984
985                    if (ar.exception != null) {
986                        break;
987                    }
988                    String[] respId = (String[])ar.result;
989                    mEsn  =  respId[2];
990                    mMeid =  respId[3];
991                }
992                break;
993
994                case EVENT_EMERGENCY_CALLBACK_MODE_ENTER:{
995                    handleEnterEmergencyCallbackMode(msg);
996                }
997                break;
998
999                case  EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE:{
1000                    handleExitEmergencyCallbackMode(msg);
1001                }
1002                break;
1003
1004                case EVENT_RUIM_RECORDS_LOADED:{
1005                    Log.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received");
1006                }
1007                break;
1008
1009                case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:{
1010                    Log.d(LOG_TAG, "Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received");
1011                }
1012                break;
1013
1014                case EVENT_RADIO_ON:{
1015                    Log.d(LOG_TAG, "Event EVENT_RADIO_ON Received");
1016                }
1017                break;
1018
1019                case EVENT_SSN:{
1020                    Log.d(LOG_TAG, "Event EVENT_SSN Received");
1021                }
1022                break;
1023
1024                case EVENT_CALL_RING:{
1025                    Log.d(LOG_TAG, "Event EVENT_CALL_RING Received");
1026                }
1027                break;
1028
1029                case EVENT_REGISTERED_TO_NETWORK:{
1030                    Log.d(LOG_TAG, "Event EVENT_REGISTERED_TO_NETWORK Received");
1031                }
1032                break;
1033
1034                case EVENT_NV_READY:{
1035                    Log.d(LOG_TAG, "Event EVENT_NV_READY Received");
1036                    //Inform the Service State Tracker
1037                    mEriManager.loadEriFile();
1038                    mNvLoadedRegistrants.notifyRegistrants();
1039                    if(mEriManager.isEriFileLoaded()) {
1040                        // when the ERI file is loaded
1041                        Log.d(LOG_TAG, "ERI read, notify registrants");
1042                        mEriFileLoadedRegistrants.notifyRegistrants();
1043                    }
1044                    setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE,"false");
1045                }
1046                break;
1047
1048                case EVENT_SET_VM_NUMBER_DONE:{
1049                    ar = (AsyncResult)msg.obj;
1050                    if (IccException.class.isInstance(ar.exception)) {
1051                        storeVoiceMailNumber(mVmNumber);
1052                        ar.exception = null;
1053                    }
1054                    onComplete = (Message) ar.userObj;
1055                    if (onComplete != null) {
1056                        AsyncResult.forMessage(onComplete, ar.result, ar.exception);
1057                        onComplete.sendToTarget();
1058                    }
1059                }
1060
1061                default:{
1062                    throw new RuntimeException("unexpected event not handled");
1063                }
1064            }
1065        }
1066    }
1067
1068    /**
1069     * Retrieves the PhoneSubInfo of the CDMAPhone
1070     */
1071    public PhoneSubInfo getPhoneSubInfo() {
1072        return mSubInfo;
1073    }
1074
1075    /**
1076     * Retrieves the IccSmsInterfaceManager of the CDMAPhone
1077     */
1078    public IccSmsInterfaceManager getIccSmsInterfaceManager() {
1079        return mRuimSmsInterfaceManager;
1080    }
1081
1082    /**
1083     * Retrieves the IccPhoneBookInterfaceManager of the CDMAPhone
1084     */
1085    public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager() {
1086        return mRuimPhoneBookInterfaceManager;
1087    }
1088
1089    public void registerForNvLoaded(Handler h, int what, Object obj) {
1090        Registrant r = new Registrant (h, what, obj);
1091        mNvLoadedRegistrants.add(r);
1092    }
1093
1094    public void unregisterForNvLoaded(Handler h) {
1095        mNvLoadedRegistrants.remove(h);
1096    }
1097
1098    public void registerForEriFileLoaded(Handler h, int what, Object obj) {
1099        Registrant r = new Registrant (h, what, obj);
1100        mEriFileLoadedRegistrants.add(r);
1101    }
1102
1103    public void unregisterForEriFileLoaded(Handler h) {
1104        mEriFileLoadedRegistrants.remove(h);
1105    }
1106
1107    // override for allowing access from other classes of this package
1108    /**
1109     * {@inheritDoc}
1110     */
1111    public final void setSystemProperty(String property, String value) {
1112        super.setSystemProperty(property, value);
1113    }
1114
1115    /**
1116     * {@inheritDoc}
1117     */
1118    public Handler getHandler() {
1119        return h;
1120    }
1121
1122    /**
1123     * {@inheritDoc}
1124     */
1125    public IccFileHandler getIccFileHandler() {
1126        return this.mIccFileHandler;
1127    }
1128
1129    /**
1130     * Set the TTY mode of the CDMAPhone
1131     */
1132    public void setTTYMode(int ttyMode, Message onComplete) {
1133        this.mCM.setTTYMode(ttyMode, onComplete);
1134    }
1135
1136    /**
1137     * Queries the TTY mode of the CDMAPhone
1138     */
1139    public void queryTTYMode(Message onComplete) {
1140        this.mCM.queryTTYMode(onComplete);
1141    }
1142
1143    /**
1144     * Activate or deactivate cell broadcast SMS.
1145     *
1146     * @param activate 0 = activate, 1 = deactivate
1147     * @param response Callback message is empty on completion
1148     */
1149    public void activateCellBroadcastSms(int activate, Message response) {
1150        mSMS.activateCellBroadcastSms(activate, response);
1151    }
1152
1153    /**
1154     * Query the current configuration of cdma cell broadcast SMS.
1155     *
1156     * @param response Callback message is empty on completion
1157     */
1158    public void getCellBroadcastSmsConfig(Message response) {
1159        mSMS.getCellBroadcastSmsConfig(response);
1160    }
1161
1162    /**
1163     * Configure cdma cell broadcast SMS.
1164     *
1165     * @param response Callback message is empty on completion
1166     */
1167    public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) {
1168        mSMS.setCellBroadcastConfig(configValuesArray, response);
1169    }
1170
1171    private static final String IS683A_FEATURE_CODE = "*228";
1172    private static final int IS683A_FEATURE_CODE_NUM_DIGITS = 4;
1173    private static final int IS683A_SYS_SEL_CODE_NUM_DIGITS = 2;
1174    private static final int IS683A_SYS_SEL_CODE_OFFSET = 4;
1175
1176    private static final int IS683_CONST_800MHZ_A_BAND = 0;
1177    private static final int IS683_CONST_800MHZ_B_BAND = 1;
1178    private static final int IS683_CONST_1900MHZ_A_BLOCK = 2;
1179    private static final int IS683_CONST_1900MHZ_B_BLOCK = 3;
1180    private static final int IS683_CONST_1900MHZ_C_BLOCK = 4;
1181    private static final int IS683_CONST_1900MHZ_D_BLOCK = 5;
1182    private static final int IS683_CONST_1900MHZ_E_BLOCK = 6;
1183    private static final int IS683_CONST_1900MHZ_F_BLOCK = 7;
1184    private static final int INVALID_SYSTEM_SELECTION_CODE = -1;
1185
1186    private boolean isIs683OtaSpDialStr(String dialStr) {
1187        int sysSelCodeInt;
1188        boolean isOtaspDialString = false;
1189        int dialStrLen = dialStr.length();
1190
1191        if (dialStrLen == IS683A_FEATURE_CODE_NUM_DIGITS) {
1192            if (dialStr.equals(IS683A_FEATURE_CODE)) {
1193                isOtaspDialString = true;
1194            }
1195        } else {
1196            sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr);
1197            switch (sysSelCodeInt) {
1198                case IS683_CONST_800MHZ_A_BAND:
1199                case IS683_CONST_800MHZ_B_BAND:
1200                case IS683_CONST_1900MHZ_A_BLOCK:
1201                case IS683_CONST_1900MHZ_B_BLOCK:
1202                case IS683_CONST_1900MHZ_C_BLOCK:
1203                case IS683_CONST_1900MHZ_D_BLOCK:
1204                case IS683_CONST_1900MHZ_E_BLOCK:
1205                case IS683_CONST_1900MHZ_F_BLOCK:
1206                    isOtaspDialString = true;
1207                    break;
1208                default:
1209                    break;
1210            }
1211        }
1212        return isOtaspDialString;
1213    }
1214    /**
1215     * This function extracts the system selection code from the dial string.
1216     */
1217    private int extractSelCodeFromOtaSpNum(String dialStr) {
1218        int dialStrLen = dialStr.length();
1219        int sysSelCodeInt = INVALID_SYSTEM_SELECTION_CODE;
1220
1221        if ((dialStr.regionMatches(0, IS683A_FEATURE_CODE,
1222                                   0, IS683A_FEATURE_CODE_NUM_DIGITS)) &&
1223            (dialStrLen >= (IS683A_FEATURE_CODE_NUM_DIGITS +
1224                            IS683A_SYS_SEL_CODE_NUM_DIGITS))) {
1225                // Since we checked the condition above, the system selection code
1226                // extracted from dialStr will not cause any exception
1227                sysSelCodeInt = Integer.parseInt (
1228                                dialStr.substring (IS683A_FEATURE_CODE_NUM_DIGITS,
1229                                IS683A_FEATURE_CODE_NUM_DIGITS + IS683A_SYS_SEL_CODE_NUM_DIGITS));
1230        }
1231        if (DBG) Log.d(LOG_TAG, "extractSelCodeFromOtaSpNum " + sysSelCodeInt);
1232        return sysSelCodeInt;
1233    }
1234
1235    /**
1236     * This function checks if the system selection code extracted from
1237     * the dial string "sysSelCodeInt' is the system selection code specified
1238     * in the carrier ota sp number schema "sch".
1239     */
1240    private boolean
1241    checkOtaSpNumBasedOnSysSelCode (int sysSelCodeInt, String sch[]) {
1242        boolean isOtaSpNum = false;
1243        try {
1244            // Get how many number of system selection code ranges
1245            int selRc = Integer.parseInt((String)sch[1]);
1246            for (int i = 0; i < selRc; i++) {
1247                if (!TextUtils.isEmpty(sch[i+2]) && !TextUtils.isEmpty(sch[i+3])) {
1248                    int selMin = Integer.parseInt((String)sch[i+2]);
1249                    int selMax = Integer.parseInt((String)sch[i+3]);
1250                    // Check if the selection code extracted from the dial string falls
1251                    // within any of the range pairs specified in the schema.
1252                    if ((sysSelCodeInt >= selMin) && (sysSelCodeInt <= selMax)) {
1253                        isOtaSpNum = true;
1254                        break;
1255                    }
1256                }
1257            }
1258        } catch (NumberFormatException ex) {
1259            // If the carrier ota sp number schema is not correct, we still allow dial
1260            // and only log the error:
1261            Log.e(LOG_TAG, "checkOtaSpNumBasedOnSysSelCode, error", ex);
1262        }
1263        return isOtaSpNum;
1264    }
1265
1266    // Define the pattern/format for carrier specified OTASP number schema.
1267    // It separates by comma and/or whitespace.
1268    private static Pattern pOtaSpNumSchema = Pattern.compile("[,\\s]+");
1269
1270    /**
1271     * The following function checks if a dial string is a carrier specified
1272     * OTASP number or not by checking against the OTASP number schema stored
1273     * in PROPERTY_OTASP_NUM_SCHEMA.
1274     *
1275     * Currently, there are 2 schemas for carriers to specify the OTASP number:
1276     * 1) Use system selection code:
1277     *    The schema is:
1278     *    SELC,the # of code pairs,min1,max1,min2,max2,...
1279     *    e.g "SELC,3,10,20,30,40,60,70" indicates that there are 3 pairs of
1280     *    selection codes, and they are {10,20}, {30,40} and {60,70} respectively.
1281     *
1282     * 2) Use feature code:
1283     *    The schema is:
1284     *    "FC,length of feature code,feature code".
1285     *     e.g "FC,2,*2" indicates that the length of the feature code is 2,
1286     *     and the code itself is "*2".
1287     */
1288    private boolean isCarrierOtaSpNum(String dialStr) {
1289        boolean isOtaSpNum = false;
1290        int sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr);
1291        if (sysSelCodeInt == INVALID_SYSTEM_SELECTION_CODE) {
1292            return isOtaSpNum;
1293        }
1294        // mCarrierOtaSpNumSchema is retrieved from PROPERTY_OTASP_NUM_SCHEMA:
1295        if (!TextUtils.isEmpty(mCarrierOtaSpNumSchema)) {
1296            Matcher m = pOtaSpNumSchema.matcher(mCarrierOtaSpNumSchema);
1297            if (DBG) {
1298                Log.d(LOG_TAG, "isCarrierOtaSpNum,schema" + mCarrierOtaSpNumSchema);
1299            }
1300
1301            if (m.find()) {
1302                String sch[] = pOtaSpNumSchema.split(mCarrierOtaSpNumSchema);
1303                // If carrier uses system selection code mechanism
1304                if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("SELC")) {
1305                    if (sysSelCodeInt!=INVALID_SYSTEM_SELECTION_CODE) {
1306                        isOtaSpNum=checkOtaSpNumBasedOnSysSelCode(sysSelCodeInt,sch);
1307                    } else {
1308                        if (DBG) {
1309                            Log.d(LOG_TAG, "isCarrierOtaSpNum,sysSelCodeInt is invalid");
1310                        }
1311                    }
1312                } else if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("FC")) {
1313                    int fcLen =  Integer.parseInt((String)sch[1]);
1314                    String fc = (String)sch[2];
1315                    if (dialStr.regionMatches(0,fc,0,fcLen)) {
1316                        isOtaSpNum = true;
1317                    } else {
1318                        if (DBG) Log.d(LOG_TAG, "isCarrierOtaSpNum,not otasp number");
1319                    }
1320                } else {
1321                    if (DBG) {
1322                        Log.d(LOG_TAG, "isCarrierOtaSpNum,ota schema not supported" + sch[0]);
1323                    }
1324                }
1325            } else {
1326                if (DBG) {
1327                    Log.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern not right" +
1328                          mCarrierOtaSpNumSchema);
1329                }
1330            }
1331        } else {
1332            if (DBG) Log.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern empty");
1333        }
1334        return isOtaSpNum;
1335    }
1336
1337     /**
1338      * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier
1339      * OTASP dial string.
1340      *
1341      * @param dialStr the number to look up.
1342      * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string
1343      */
1344    @Override
1345     public  boolean isOtaSpNumber(String dialStr){
1346         boolean isOtaSpNum = false;
1347         if (dialStr != null) {
1348             isOtaSpNum = isIs683OtaSpDialStr(dialStr);
1349             if(isOtaSpNum == false){
1350                 isOtaSpNum = isCarrierOtaSpNum(dialStr);
1351             }
1352         }
1353         if (DBG) Log.d(LOG_TAG, "isOtaSpNumber " + isOtaSpNum);
1354         return isOtaSpNum;
1355     }
1356
1357    @Override
1358    public int getCdmaEriIconIndex() {
1359        int roamInd = getServiceState().getCdmaRoamingIndicator();
1360        int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
1361        return mEriManager.getCdmaEriIconIndex(roamInd, defRoamInd);
1362    }
1363
1364    /**
1365     * Returns the CDMA ERI icon mode,
1366     * 0 - ON
1367     * 1 - FLASHING
1368     */
1369    @Override
1370    public int getCdmaEriIconMode() {
1371        int roamInd = getServiceState().getCdmaRoamingIndicator();
1372        int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
1373        return mEriManager.getCdmaEriIconMode(roamInd, defRoamInd);
1374    }
1375
1376    /**
1377     * Returns the CDMA ERI text,
1378     */
1379    @Override
1380    public String getCdmaEriText() {
1381        int roamInd = getServiceState().getCdmaRoamingIndicator();
1382        int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
1383        return mEriManager.getCdmaEriText(roamInd, defRoamInd);
1384    }
1385
1386    /**
1387     * Store the voicemail number in preferences
1388     */
1389    private void storeVoiceMailNumber(String number) {
1390        // Update the preference value of voicemail number
1391        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1392        SharedPreferences.Editor editor = sp.edit();
1393        editor.putString(VM_NUMBER_CDMA, number);
1394        editor.commit();
1395    }
1396
1397    /**
1398     * Sets PROPERTY_ICC_OPERATOR_ISO_COUNTRY property
1399     *
1400     */
1401    private void setIsoCountryProperty(String operatorNumeric) {
1402        if (TextUtils.isEmpty(operatorNumeric)) {
1403            setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, "");
1404        } else {
1405            String iso = "";
1406            try {
1407                iso = MccTable.countryCodeForMcc(Integer.parseInt(
1408                        operatorNumeric.substring(0,3)));
1409            } catch (NumberFormatException ex) {
1410                Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
1411            } catch (StringIndexOutOfBoundsException ex) {
1412                Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
1413            }
1414
1415            setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, iso);
1416        }
1417    }
1418
1419    /**
1420     * Sets the "current" field in the telephony provider according to the build-time
1421     * operator numeric property
1422     *
1423     * @return true for success; false otherwise.
1424     */
1425    // TODO(Moto): move this method into PhoneBase, since it looks identical to
1426    // the one in GsmPhone
1427    private boolean updateCurrentCarrierInProvider(String operatorNumeric) {
1428        if (!TextUtils.isEmpty(operatorNumeric)) {
1429            try {
1430                Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
1431                ContentValues map = new ContentValues();
1432                map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
1433                getContext().getContentResolver().insert(uri, map);
1434                return true;
1435            } catch (SQLException e) {
1436                Log.e(LOG_TAG, "Can't store current operator", e);
1437            }
1438        }
1439        return false;
1440    }
1441
1442    /**
1443     * Updates MCC and MNC device configuration information for application retrieving
1444     * correct version of resources
1445     *
1446     */
1447    private void updateMccMncConfiguration(String operatorNumeric) {
1448        if (operatorNumeric.length() >= 5) {
1449            Configuration config = new Configuration();
1450            config.mcc = Integer.parseInt(operatorNumeric.substring(0,3));
1451            config.mnc = Integer.parseInt(operatorNumeric.substring(3));
1452            try {
1453                ActivityManagerNative.getDefault().updateConfiguration(config);
1454            } catch (RemoteException e) {
1455                Log.e(LOG_TAG, "Can't update configuration", e);
1456            }
1457        }
1458    }
1459}
1460