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