OSDN Git Service

Merge "cherrypick from master: Change-Id: I169749dc594ca1d79a802db4c53ec330924fdd2c...
[android-x86/frameworks-base.git] / telephony / java / com / android / internal / telephony / PhoneBase.java
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.internal.telephony;
18
19 import android.app.ActivityManagerNative;
20 import android.app.IActivityManager;
21 import android.content.Context;
22 import android.content.res.Configuration;
23 import android.content.SharedPreferences;
24 import android.net.LinkCapabilities;
25 import android.net.LinkProperties;
26 import android.net.wifi.WifiManager;
27 import android.os.AsyncResult;
28 import android.os.Handler;
29 import android.os.Looper;
30 import android.os.Message;
31 import android.os.RegistrantList;
32 import android.os.SystemProperties;
33 import android.preference.PreferenceManager;
34 import android.provider.Settings;
35 import android.telephony.ServiceState;
36 import android.text.TextUtils;
37 import android.util.Log;
38
39 import com.android.internal.R;
40 import com.android.internal.telephony.test.SimulatedRadioControl;
41
42 import java.util.Locale;
43
44
45 /**
46  * (<em>Not for SDK use</em>)
47  * A base implementation for the com.android.internal.telephony.Phone interface.
48  *
49  * Note that implementations of Phone.java are expected to be used
50  * from a single application thread. This should be the same thread that
51  * originally called PhoneFactory to obtain the interface.
52  *
53  *  {@hide}
54  *
55  */
56
57 public abstract class PhoneBase extends Handler implements Phone {
58     private static final String LOG_TAG = "PHONE";
59     private static final boolean LOCAL_DEBUG = true;
60
61     // Key used to read and write the saved network selection numeric value
62     public static final String NETWORK_SELECTION_KEY = "network_selection_key";
63     // Key used to read and write the saved network selection operator name
64     public static final String NETWORK_SELECTION_NAME_KEY = "network_selection_name_key";
65
66
67     // Key used to read/write "disable data connection on boot" pref (used for testing)
68     public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
69
70     /* Event Constants */
71     protected static final int EVENT_RADIO_AVAILABLE             = 1;
72     /** Supplementary Service Notification received. */
73     protected static final int EVENT_SSN                         = 2;
74     protected static final int EVENT_SIM_RECORDS_LOADED          = 3;
75     protected static final int EVENT_MMI_DONE                    = 4;
76     protected static final int EVENT_RADIO_ON                    = 5;
77     protected static final int EVENT_GET_BASEBAND_VERSION_DONE   = 6;
78     protected static final int EVENT_USSD                        = 7;
79     protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE  = 8;
80     protected static final int EVENT_GET_IMEI_DONE               = 9;
81     protected static final int EVENT_GET_IMEISV_DONE             = 10;
82     protected static final int EVENT_GET_SIM_STATUS_DONE         = 11;
83     protected static final int EVENT_SET_CALL_FORWARD_DONE       = 12;
84     protected static final int EVENT_GET_CALL_FORWARD_DONE       = 13;
85     protected static final int EVENT_CALL_RING                   = 14;
86     protected static final int EVENT_CALL_RING_CONTINUE          = 15;
87
88     // Used to intercept the carrier selection calls so that
89     // we can save the values.
90     protected static final int EVENT_SET_NETWORK_MANUAL_COMPLETE    = 16;
91     protected static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 17;
92     protected static final int EVENT_SET_CLIR_COMPLETE              = 18;
93     protected static final int EVENT_REGISTERED_TO_NETWORK          = 19;
94     protected static final int EVENT_SET_VM_NUMBER_DONE             = 20;
95     // Events for CDMA support
96     protected static final int EVENT_GET_DEVICE_IDENTITY_DONE       = 21;
97     protected static final int EVENT_RUIM_RECORDS_LOADED            = 22;
98     protected static final int EVENT_NV_READY                       = 23;
99     protected static final int EVENT_SET_ENHANCED_VP                = 24;
100     protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER  = 25;
101     protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 26;
102
103     // Key used to read/write current CLIR setting
104     public static final String CLIR_KEY = "clir_key";
105
106     // Key used to read/write "disable DNS server check" pref (used for testing)
107     public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
108
109     /* Instance Variables */
110     public CommandsInterface mCM;
111     protected IccFileHandler mIccFileHandler;
112     boolean mDnsCheckDisabled = false;
113     public DataConnectionTracker mDataConnection;
114     boolean mDoesRilSendMultipleCallRing;
115     int mCallRingContinueToken = 0;
116     int mCallRingDelay;
117     public boolean mIsTheCurrentActivePhone = true;
118     boolean mIsVoiceCapable = true;
119
120     /**
121      * Set a system property, unless we're in unit test mode
122      */
123     public void
124     setSystemProperty(String property, String value) {
125         if(getUnitTestMode()) {
126             return;
127         }
128         SystemProperties.set(property, value);
129     }
130
131
132     protected final RegistrantList mPreciseCallStateRegistrants
133             = new RegistrantList();
134
135     protected final RegistrantList mNewRingingConnectionRegistrants
136             = new RegistrantList();
137
138     protected final RegistrantList mIncomingRingRegistrants
139             = new RegistrantList();
140
141     protected final RegistrantList mDisconnectRegistrants
142             = new RegistrantList();
143
144     protected final RegistrantList mServiceStateRegistrants
145             = new RegistrantList();
146
147     protected final RegistrantList mMmiCompleteRegistrants
148             = new RegistrantList();
149
150     protected final RegistrantList mMmiRegistrants
151             = new RegistrantList();
152
153     protected final RegistrantList mUnknownConnectionRegistrants
154             = new RegistrantList();
155
156     protected final RegistrantList mSuppServiceFailedRegistrants
157             = new RegistrantList();
158
159     protected Looper mLooper; /* to insure registrants are in correct thread*/
160
161     protected Context mContext;
162
163     /**
164      * PhoneNotifier is an abstraction for all system-wide
165      * state change notification. DefaultPhoneNotifier is
166      * used here unless running we're inside a unit test.
167      */
168     protected PhoneNotifier mNotifier;
169
170     protected SimulatedRadioControl mSimulatedRadioControl;
171
172     boolean mUnitTestMode;
173
174     /**
175      * Constructs a PhoneBase in normal (non-unit test) mode.
176      *
177      * @param context Context object from hosting application
178      * @param notifier An instance of DefaultPhoneNotifier,
179      * unless unit testing.
180      */
181     protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci) {
182         this(notifier, context, ci, false);
183     }
184
185     /**
186      * Constructs a PhoneBase in normal (non-unit test) mode.
187      *
188      * @param context Context object from hosting application
189      * @param notifier An instance of DefaultPhoneNotifier,
190      * unless unit testing.
191      * @param unitTestMode when true, prevents notifications
192      * of state change events
193      */
194     protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci,
195             boolean unitTestMode) {
196         this.mNotifier = notifier;
197         this.mContext = context;
198         mLooper = Looper.myLooper();
199         mCM = ci;
200
201         setPropertiesByCarrier();
202
203         setUnitTestMode(unitTestMode);
204
205         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
206         mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
207         mCM.setOnCallRing(this, EVENT_CALL_RING, null);
208
209         /* "Voice capable" means that this device supports circuit-switched
210         * (i.e. voice) phone calls over the telephony network, and is allowed
211         * to display the in-call UI while a cellular voice call is active.
212         * This will be false on "data only" devices which can't make voice
213         * calls and don't support any in-call UI.
214         */
215         mIsVoiceCapable = mContext.getResources().getBoolean(
216                 com.android.internal.R.bool.config_voice_capable);
217
218         /**
219          *  Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs
220          *  to be generated locally. Ideally all ring tones should be loops
221          * and this wouldn't be necessary. But to minimize changes to upper
222          * layers it is requested that it be generated by lower layers.
223          *
224          * By default old phones won't have the property set but do generate
225          * the RIL_UNSOL_CALL_RING so the default if there is no property is
226          * true.
227          */
228         mDoesRilSendMultipleCallRing = SystemProperties.getBoolean(
229                 TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true);
230         Log.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
231
232         mCallRingDelay = SystemProperties.getInt(
233                 TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000);
234         Log.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
235     }
236
237     public void dispose() {
238         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
239             mCM.unSetOnCallRing(this);
240             mDataConnection.onCleanUpConnection(false, REASON_RADIO_TURNED_OFF);
241             mIsTheCurrentActivePhone = false;
242         }
243     }
244
245     /**
246      * When overridden the derived class needs to call
247      * super.handleMessage(msg) so this method has a
248      * a chance to process the message.
249      *
250      * @param msg
251      */
252     @Override
253     public void handleMessage(Message msg) {
254         AsyncResult ar;
255
256         switch(msg.what) {
257             case EVENT_CALL_RING:
258                 Log.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState());
259                 ar = (AsyncResult)msg.obj;
260                 if (ar.exception == null) {
261                     Phone.State state = getState();
262                     if ((!mDoesRilSendMultipleCallRing)
263                             && ((state == Phone.State.RINGING) || (state == Phone.State.IDLE))) {
264                         mCallRingContinueToken += 1;
265                         sendIncomingCallRingNotification(mCallRingContinueToken);
266                     } else {
267                         notifyIncomingRing();
268                     }
269                 }
270                 break;
271
272             case EVENT_CALL_RING_CONTINUE:
273                 Log.d(LOG_TAG, "Event EVENT_CALL_RING_CONTINUE Received stat=" + getState());
274                 if (getState() == Phone.State.RINGING) {
275                     sendIncomingCallRingNotification(msg.arg1);
276                 }
277                 break;
278
279             default:
280                 throw new RuntimeException("unexpected event not handled");
281         }
282     }
283
284     // Inherited documentation suffices.
285     public Context getContext() {
286         return mContext;
287     }
288
289     /**
290      * Disables the DNS check (i.e., allows "0.0.0.0").
291      * Useful for lab testing environment.
292      * @param b true disables the check, false enables.
293      */
294     public void disableDnsCheck(boolean b) {
295         mDnsCheckDisabled = b;
296         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
297         SharedPreferences.Editor editor = sp.edit();
298         editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);
299         editor.apply();
300     }
301
302     /**
303      * Returns true if the DNS check is currently disabled.
304      */
305     public boolean isDnsCheckDisabled() {
306         return mDnsCheckDisabled;
307     }
308
309     // Inherited documentation suffices.
310     public void registerForPreciseCallStateChanged(Handler h, int what, Object obj) {
311         checkCorrectThread(h);
312
313         mPreciseCallStateRegistrants.addUnique(h, what, obj);
314     }
315
316     // Inherited documentation suffices.
317     public void unregisterForPreciseCallStateChanged(Handler h) {
318         mPreciseCallStateRegistrants.remove(h);
319     }
320
321     /**
322      * Subclasses of Phone probably want to replace this with a
323      * version scoped to their packages
324      */
325     protected void notifyPreciseCallStateChangedP() {
326         AsyncResult ar = new AsyncResult(null, this, null);
327         mPreciseCallStateRegistrants.notifyRegistrants(ar);
328     }
329
330     // Inherited documentation suffices.
331     public void registerForUnknownConnection(Handler h, int what, Object obj) {
332         checkCorrectThread(h);
333
334         mUnknownConnectionRegistrants.addUnique(h, what, obj);
335     }
336
337     // Inherited documentation suffices.
338     public void unregisterForUnknownConnection(Handler h) {
339         mUnknownConnectionRegistrants.remove(h);
340     }
341
342     // Inherited documentation suffices.
343     public void registerForNewRingingConnection(
344             Handler h, int what, Object obj) {
345         checkCorrectThread(h);
346
347         mNewRingingConnectionRegistrants.addUnique(h, what, obj);
348     }
349
350     // Inherited documentation suffices.
351     public void unregisterForNewRingingConnection(Handler h) {
352         mNewRingingConnectionRegistrants.remove(h);
353     }
354
355     // Inherited documentation suffices.
356     public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
357         mCM.registerForInCallVoicePrivacyOn(h,what,obj);
358     }
359
360     // Inherited documentation suffices.
361     public void unregisterForInCallVoicePrivacyOn(Handler h){
362         mCM.unregisterForInCallVoicePrivacyOn(h);
363     }
364
365     // Inherited documentation suffices.
366     public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
367         mCM.registerForInCallVoicePrivacyOff(h,what,obj);
368     }
369
370     // Inherited documentation suffices.
371     public void unregisterForInCallVoicePrivacyOff(Handler h){
372         mCM.unregisterForInCallVoicePrivacyOff(h);
373     }
374
375     // Inherited documentation suffices.
376     public void registerForIncomingRing(
377             Handler h, int what, Object obj) {
378         checkCorrectThread(h);
379
380         mIncomingRingRegistrants.addUnique(h, what, obj);
381     }
382
383     // Inherited documentation suffices.
384     public void unregisterForIncomingRing(Handler h) {
385         mIncomingRingRegistrants.remove(h);
386     }
387
388     // Inherited documentation suffices.
389     public void registerForDisconnect(Handler h, int what, Object obj) {
390         checkCorrectThread(h);
391
392         mDisconnectRegistrants.addUnique(h, what, obj);
393     }
394
395     // Inherited documentation suffices.
396     public void unregisterForDisconnect(Handler h) {
397         mDisconnectRegistrants.remove(h);
398     }
399
400     // Inherited documentation suffices.
401     public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
402         checkCorrectThread(h);
403
404         mSuppServiceFailedRegistrants.addUnique(h, what, obj);
405     }
406
407     // Inherited documentation suffices.
408     public void unregisterForSuppServiceFailed(Handler h) {
409         mSuppServiceFailedRegistrants.remove(h);
410     }
411
412     // Inherited documentation suffices.
413     public void registerForMmiInitiate(Handler h, int what, Object obj) {
414         checkCorrectThread(h);
415
416         mMmiRegistrants.addUnique(h, what, obj);
417     }
418
419     // Inherited documentation suffices.
420     public void unregisterForMmiInitiate(Handler h) {
421         mMmiRegistrants.remove(h);
422     }
423
424     // Inherited documentation suffices.
425     public void registerForMmiComplete(Handler h, int what, Object obj) {
426         checkCorrectThread(h);
427
428         mMmiCompleteRegistrants.addUnique(h, what, obj);
429     }
430
431     // Inherited documentation suffices.
432     public void unregisterForMmiComplete(Handler h) {
433         checkCorrectThread(h);
434
435         mMmiCompleteRegistrants.remove(h);
436     }
437
438     /**
439      * Method to retrieve the saved operator id from the Shared Preferences
440      */
441     private String getSavedNetworkSelection() {
442         // open the shared preferences and search with our key.
443         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
444         return sp.getString(NETWORK_SELECTION_KEY, "");
445     }
446
447     /**
448      * Method to restore the previously saved operator id, or reset to
449      * automatic selection, all depending upon the value in the shared
450      * preferences.
451      */
452     public void restoreSavedNetworkSelection(Message response) {
453         // retrieve the operator id
454         String networkSelection = getSavedNetworkSelection();
455
456         // set to auto if the id is empty, otherwise select the network.
457         if (TextUtils.isEmpty(networkSelection)) {
458             mCM.setNetworkSelectionModeAutomatic(response);
459         } else {
460             mCM.setNetworkSelectionModeManual(networkSelection, response);
461         }
462     }
463
464     // Inherited documentation suffices.
465     public void setUnitTestMode(boolean f) {
466         mUnitTestMode = f;
467     }
468
469     // Inherited documentation suffices.
470     public boolean getUnitTestMode() {
471         return mUnitTestMode;
472     }
473
474     /**
475      * To be invoked when a voice call Connection disconnects.
476      *
477      * Subclasses of Phone probably want to replace this with a
478      * version scoped to their packages
479      */
480     protected void notifyDisconnectP(Connection cn) {
481         AsyncResult ar = new AsyncResult(null, cn, null);
482         mDisconnectRegistrants.notifyRegistrants(ar);
483     }
484
485     // Inherited documentation suffices.
486     public void registerForServiceStateChanged(
487             Handler h, int what, Object obj) {
488         checkCorrectThread(h);
489
490         mServiceStateRegistrants.add(h, what, obj);
491     }
492
493     // Inherited documentation suffices.
494     public void unregisterForServiceStateChanged(Handler h) {
495         mServiceStateRegistrants.remove(h);
496     }
497
498     // Inherited documentation suffices.
499     public void registerForRingbackTone(Handler h, int what, Object obj) {
500         mCM.registerForRingbackTone(h,what,obj);
501     }
502
503     // Inherited documentation suffices.
504     public void unregisterForRingbackTone(Handler h) {
505         mCM.unregisterForRingbackTone(h);
506     }
507
508     // Inherited documentation suffices.
509     public void registerForResendIncallMute(Handler h, int what, Object obj) {
510         mCM.registerForResendIncallMute(h,what,obj);
511     }
512
513     // Inherited documentation suffices.
514     public void unregisterForResendIncallMute(Handler h) {
515         mCM.unregisterForResendIncallMute(h);
516     }
517
518     public void setEchoSuppressionEnabled(boolean enabled) {
519         // no need for regular phone
520     }
521
522     /**
523      * Subclasses of Phone probably want to replace this with a
524      * version scoped to their packages
525      */
526     protected void notifyServiceStateChangedP(ServiceState ss) {
527         AsyncResult ar = new AsyncResult(null, ss, null);
528         mServiceStateRegistrants.notifyRegistrants(ar);
529
530         mNotifier.notifyServiceState(this);
531     }
532
533     // Inherited documentation suffices.
534     public SimulatedRadioControl getSimulatedRadioControl() {
535         return mSimulatedRadioControl;
536     }
537
538     /**
539      * Verifies the current thread is the same as the thread originally
540      * used in the initialization of this instance. Throws RuntimeException
541      * if not.
542      *
543      * @exception RuntimeException if the current thread is not
544      * the thread that originally obtained this PhoneBase instance.
545      */
546     private void checkCorrectThread(Handler h) {
547         if (h.getLooper() != mLooper) {
548             throw new RuntimeException(
549                     "com.android.internal.telephony.Phone must be used from within one thread");
550         }
551     }
552
553     /**
554      * Set the properties by matching the carrier string in
555      * a string-array resource
556      */
557     private void setPropertiesByCarrier() {
558         String carrier = SystemProperties.get("ro.carrier");
559
560         if (null == carrier || 0 == carrier.length() || "unknown".equals(carrier)) {
561             return;
562         }
563
564         CharSequence[] carrierLocales = mContext.
565                 getResources().getTextArray(R.array.carrier_properties);
566
567         for (int i = 0; i < carrierLocales.length; i+=3) {
568             String c = carrierLocales[i].toString();
569             if (carrier.equals(c)) {
570                 String l = carrierLocales[i+1].toString();
571
572                 String language = l.substring(0, 2);
573                 String country = "";
574                 if (l.length() >=5) {
575                     country = l.substring(3, 5);
576                 }
577                 setSystemLocale(language, country);
578
579                 if (!country.isEmpty()) {
580                     try {
581                         Settings.Secure.getInt(mContext.getContentResolver(),
582                                 Settings.Secure.WIFI_COUNTRY_CODE);
583                     } catch (Settings.SettingNotFoundException e) {
584                         // note this is not persisting
585                         WifiManager wM = (WifiManager)
586                                 mContext.getSystemService(Context.WIFI_SERVICE);
587                         wM.setCountryCode(country, false);
588                     }
589                 }
590                 return;
591             }
592         }
593     }
594
595     /**
596      * Utility code to set the system locale if it's not set already
597      * @param language Two character language code desired
598      * @param country Two character country code desired
599      *
600      *  {@hide}
601      */
602     public void setSystemLocale(String language, String country) {
603         String l = SystemProperties.get("persist.sys.language");
604         String c = SystemProperties.get("persist.sys.country");
605
606         if (null == language) {
607             return; // no match possible
608         }
609         language = language.toLowerCase();
610         if (null == country) {
611             country = "";
612         }
613         country = country.toUpperCase();
614
615         if((null == l || 0 == l.length()) && (null == c || 0 == c.length())) {
616             try {
617                 // try to find a good match
618                 String[] locales = mContext.getAssets().getLocales();
619                 final int N = locales.length;
620                 String bestMatch = null;
621                 for(int i = 0; i < N; i++) {
622                     // only match full (lang + country) locales
623                     if (locales[i]!=null && locales[i].length() >= 5 &&
624                             locales[i].substring(0,2).equals(language)) {
625                         if (locales[i].substring(3,5).equals(country)) {
626                             bestMatch = locales[i];
627                             break;
628                         } else if (null == bestMatch) {
629                             bestMatch = locales[i];
630                         }
631                     }
632                 }
633                 if (null != bestMatch) {
634                     IActivityManager am = ActivityManagerNative.getDefault();
635                     Configuration config = am.getConfiguration();
636                     config.locale = new Locale(bestMatch.substring(0,2),
637                                                bestMatch.substring(3,5));
638                     config.userSetLocale = true;
639                     am.updateConfiguration(config);
640                 }
641             } catch (Exception e) {
642                 // Intentionally left blank
643             }
644         }
645     }
646
647     /**
648      * Get state
649      */
650     public abstract Phone.State getState();
651
652     /**
653      * Retrieves the IccFileHandler of the Phone instance
654      */
655     public abstract IccFileHandler getIccFileHandler();
656
657     /*
658      * Retrieves the Handler of the Phone instance
659      */
660     public Handler getHandler() {
661         return this;
662     }
663
664     /**
665      *  Query the status of the CDMA roaming preference
666      */
667     public void queryCdmaRoamingPreference(Message response) {
668         mCM.queryCdmaRoamingPreference(response);
669     }
670
671     /**
672      *  Set the status of the CDMA roaming preference
673      */
674     public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
675         mCM.setCdmaRoamingPreference(cdmaRoamingType, response);
676     }
677
678     /**
679      *  Set the status of the CDMA subscription mode
680      */
681     public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
682         mCM.setCdmaSubscriptionSource(cdmaSubscriptionType, response);
683     }
684
685     /**
686      *  Set the preferred Network Type: Global, CDMA only or GSM/UMTS only
687      */
688     public void setPreferredNetworkType(int networkType, Message response) {
689         mCM.setPreferredNetworkType(networkType, response);
690     }
691
692     public void getPreferredNetworkType(Message response) {
693         mCM.getPreferredNetworkType(response);
694     }
695
696     public void getSmscAddress(Message result) {
697         mCM.getSmscAddress(result);
698     }
699
700     public void setSmscAddress(String address, Message result) {
701         mCM.setSmscAddress(address, result);
702     }
703
704     public void setTTYMode(int ttyMode, Message onComplete) {
705         mCM.setTTYMode(ttyMode, onComplete);
706     }
707
708     public void queryTTYMode(Message onComplete) {
709         mCM.queryTTYMode(onComplete);
710     }
711
712     public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
713         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
714         logUnexpectedCdmaMethodCall("enableEnhancedVoicePrivacy");
715     }
716
717     public void getEnhancedVoicePrivacy(Message onComplete) {
718         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
719         logUnexpectedCdmaMethodCall("getEnhancedVoicePrivacy");
720     }
721
722     public void setBandMode(int bandMode, Message response) {
723         mCM.setBandMode(bandMode, response);
724     }
725
726     public void queryAvailableBandMode(Message response) {
727         mCM.queryAvailableBandMode(response);
728     }
729
730     public void invokeOemRilRequestRaw(byte[] data, Message response) {
731         mCM.invokeOemRilRequestRaw(data, response);
732     }
733
734     public void invokeOemRilRequestStrings(String[] strings, Message response) {
735         mCM.invokeOemRilRequestStrings(strings, response);
736     }
737
738     public void notifyDataActivity() {
739         mNotifier.notifyDataActivity(this);
740     }
741
742     public void notifyMessageWaitingIndicator() {
743         // Do not notify voice mail waiting if device doesn't support voice
744         if (!mIsVoiceCapable)
745             return;
746
747         // This function is added to send the notification to DefaultPhoneNotifier.
748         mNotifier.notifyMessageWaitingChanged(this);
749     }
750
751     public void notifyDataConnection(String reason, String apnType,
752             Phone.DataState state) {
753         mNotifier.notifyDataConnection(this, reason, apnType, state);
754     }
755
756     public void notifyDataConnection(String reason, String apnType) {
757         mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
758     }
759
760     public void notifyDataConnection() {
761         String types[] = getActiveApnTypes();
762         for (String apnType : types) {
763             mNotifier.notifyDataConnection(this, null, apnType, getDataConnectionState(apnType));
764         }
765     }
766
767     public void notifyOtaspChanged(int otaspMode) {
768         mNotifier.notifyOtaspChanged(this, otaspMode);
769     }
770
771     public abstract String getPhoneName();
772
773     public abstract int getPhoneType();
774
775     /** @hide */
776     public int getVoiceMessageCount(){
777         return 0;
778     }
779
780     /**
781      * Returns the CDMA ERI icon index to display
782      */
783     public int getCdmaEriIconIndex() {
784         logUnexpectedCdmaMethodCall("getCdmaEriIconIndex");
785         return -1;
786     }
787
788     /**
789      * Returns the CDMA ERI icon mode,
790      * 0 - ON
791      * 1 - FLASHING
792      */
793     public int getCdmaEriIconMode() {
794         logUnexpectedCdmaMethodCall("getCdmaEriIconMode");
795         return -1;
796     }
797
798     /**
799      * Returns the CDMA ERI text,
800      */
801     public String getCdmaEriText() {
802         logUnexpectedCdmaMethodCall("getCdmaEriText");
803         return "GSM nw, no ERI";
804     }
805
806     public String getCdmaMin() {
807         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
808         logUnexpectedCdmaMethodCall("getCdmaMin");
809         return null;
810     }
811
812     public boolean isMinInfoReady() {
813         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
814         logUnexpectedCdmaMethodCall("isMinInfoReady");
815         return false;
816     }
817
818     public String getCdmaPrlVersion(){
819         //  This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
820         logUnexpectedCdmaMethodCall("getCdmaPrlVersion");
821         return null;
822     }
823
824     public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
825         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
826         logUnexpectedCdmaMethodCall("sendBurstDtmf");
827     }
828
829     public void exitEmergencyCallbackMode() {
830         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
831         logUnexpectedCdmaMethodCall("exitEmergencyCallbackMode");
832     }
833
834     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
835         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
836         logUnexpectedCdmaMethodCall("registerForCdmaOtaStatusChange");
837     }
838
839     public void unregisterForCdmaOtaStatusChange(Handler h) {
840         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
841         logUnexpectedCdmaMethodCall("unregisterForCdmaOtaStatusChange");
842     }
843
844     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
845         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
846         logUnexpectedCdmaMethodCall("registerForSubscriptionInfoReady");
847     }
848
849     public void unregisterForSubscriptionInfoReady(Handler h) {
850         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
851         logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady");
852     }
853
854     /**
855      * Returns true if OTA Service Provisioning needs to be performed.
856      * If not overridden return false.
857      */
858     public boolean needsOtaServiceProvisioning() {
859         return false;
860     }
861
862     /**
863      * Return true if number is an OTASP number.
864      * If not overridden return false.
865      */
866     public  boolean isOtaSpNumber(String dialStr) {
867         return false;
868     }
869
870     public void registerForCallWaiting(Handler h, int what, Object obj){
871         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
872         logUnexpectedCdmaMethodCall("registerForCallWaiting");
873     }
874
875     public void unregisterForCallWaiting(Handler h){
876         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
877         logUnexpectedCdmaMethodCall("unregisterForCallWaiting");
878     }
879
880     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
881         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
882         logUnexpectedCdmaMethodCall("registerForEcmTimerReset");
883     }
884
885     public void unregisterForEcmTimerReset(Handler h) {
886         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
887         logUnexpectedCdmaMethodCall("unregisterForEcmTimerReset");
888     }
889
890     public void registerForSignalInfo(Handler h, int what, Object obj) {
891         mCM.registerForSignalInfo(h, what, obj);
892     }
893
894     public void unregisterForSignalInfo(Handler h) {
895         mCM.unregisterForSignalInfo(h);
896     }
897
898     public void registerForDisplayInfo(Handler h, int what, Object obj) {
899         mCM.registerForDisplayInfo(h, what, obj);
900     }
901
902      public void unregisterForDisplayInfo(Handler h) {
903          mCM.unregisterForDisplayInfo(h);
904      }
905
906     public void registerForNumberInfo(Handler h, int what, Object obj) {
907         mCM.registerForNumberInfo(h, what, obj);
908     }
909
910     public void unregisterForNumberInfo(Handler h) {
911         mCM.unregisterForNumberInfo(h);
912     }
913
914     public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
915         mCM.registerForRedirectedNumberInfo(h, what, obj);
916     }
917
918     public void unregisterForRedirectedNumberInfo(Handler h) {
919         mCM.unregisterForRedirectedNumberInfo(h);
920     }
921
922     public void registerForLineControlInfo(Handler h, int what, Object obj) {
923         mCM.registerForLineControlInfo( h, what, obj);
924     }
925
926     public void unregisterForLineControlInfo(Handler h) {
927         mCM.unregisterForLineControlInfo(h);
928     }
929
930     public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
931         mCM.registerFoT53ClirlInfo(h, what, obj);
932     }
933
934     public void unregisterForT53ClirInfo(Handler h) {
935         mCM.unregisterForT53ClirInfo(h);
936     }
937
938     public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
939         mCM.registerForT53AudioControlInfo( h, what, obj);
940     }
941
942     public void unregisterForT53AudioControlInfo(Handler h) {
943         mCM.unregisterForT53AudioControlInfo(h);
944     }
945
946      public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
947          // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
948          logUnexpectedCdmaMethodCall("setOnEcbModeExitResponse");
949      }
950
951      public void unsetOnEcbModeExitResponse(Handler h){
952         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
953          logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse");
954      }
955
956     public String[] getActiveApnTypes() {
957         return mDataConnection.getActiveApnTypes();
958     }
959
960     public String getActiveApnHost() {
961         return mDataConnection.getActiveApnString();
962     }
963
964     public LinkProperties getLinkProperties(String apnType) {
965         return mDataConnection.getLinkProperties(apnType);
966     }
967
968     public LinkCapabilities getLinkCapabilities(String apnType) {
969         return mDataConnection.getLinkCapabilities(apnType);
970     }
971
972     public int enableApnType(String type) {
973         return mDataConnection.enableApnType(type);
974     }
975
976     public int disableApnType(String type) {
977         return mDataConnection.disableApnType(type);
978     }
979
980     public boolean isDataConnectivityPossible() {
981         return ((mDataConnection != null) && (mDataConnection.isDataPossible()));
982     }
983
984     /**
985      * simulateDataConnection
986      *
987      * simulates various data connection states. This messes with
988      * DataConnectionTracker's internal states, but doesn't actually change
989      * the underlying radio connection states.
990      *
991      * @param state Phone.DataState enum.
992      */
993     public void simulateDataConnection(Phone.DataState state) {
994         DataConnectionTracker.State dcState;
995
996         switch (state) {
997             case CONNECTED:
998                 dcState = DataConnectionTracker.State.CONNECTED;
999                 break;
1000             case SUSPENDED:
1001                 dcState = DataConnectionTracker.State.CONNECTED;
1002                 break;
1003             case DISCONNECTED:
1004                 dcState = DataConnectionTracker.State.FAILED;
1005                 break;
1006             default:
1007                 dcState = DataConnectionTracker.State.CONNECTING;
1008                 break;
1009         }
1010
1011         mDataConnection.setState(dcState);
1012         notifyDataConnection(null, Phone.APN_TYPE_DEFAULT);
1013     }
1014
1015     /**
1016      * Notify registrants of a new ringing Connection.
1017      * Subclasses of Phone probably want to replace this with a
1018      * version scoped to their packages
1019      */
1020     protected void notifyNewRingingConnectionP(Connection cn) {
1021         if (!mIsVoiceCapable)
1022             return;
1023         AsyncResult ar = new AsyncResult(null, cn, null);
1024         mNewRingingConnectionRegistrants.notifyRegistrants(ar);
1025     }
1026
1027     /**
1028      * Notify registrants of a RING event.
1029      */
1030     private void notifyIncomingRing() {
1031         if (!mIsVoiceCapable)
1032             return;
1033         AsyncResult ar = new AsyncResult(null, this, null);
1034         mIncomingRingRegistrants.notifyRegistrants(ar);
1035     }
1036
1037     /**
1038      * Send the incoming call Ring notification if conditions are right.
1039      */
1040     private void sendIncomingCallRingNotification(int token) {
1041         if (mIsVoiceCapable && !mDoesRilSendMultipleCallRing &&
1042                 (token == mCallRingContinueToken)) {
1043             Log.d(LOG_TAG, "Sending notifyIncomingRing");
1044             notifyIncomingRing();
1045             sendMessageDelayed(
1046                     obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
1047         } else {
1048             Log.d(LOG_TAG, "Ignoring ring notification request,"
1049                     + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
1050                     + " token=" + token
1051                     + " mCallRingContinueToken=" + mCallRingContinueToken
1052                     + " mIsVoiceCapable=" + mIsVoiceCapable);
1053         }
1054     }
1055
1056     public boolean isCspPlmnEnabled() {
1057         // This function should be overridden by the class GSMPhone.
1058         // Not implemented in CDMAPhone.
1059         logUnexpectedGsmMethodCall("isCspPlmnEnabled");
1060         return false;
1061     }
1062
1063     /**
1064      * Common error logger method for unexpected calls to CDMA-only methods.
1065      */
1066     private void logUnexpectedCdmaMethodCall(String name)
1067     {
1068         Log.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
1069                 "called, CDMAPhone inactive.");
1070     }
1071
1072     public DataState getDataConnectionState() {
1073         return getDataConnectionState(APN_TYPE_DEFAULT);
1074     }
1075
1076     /**
1077      * Common error logger method for unexpected calls to GSM/WCDMA-only methods.
1078      */
1079     private void logUnexpectedGsmMethodCall(String name) {
1080         Log.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
1081                 "called, GSMPhone inactive.");
1082     }
1083 }